首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java JFrame绘画

Java JFrame绘画
EN

Stack Overflow用户
提问于 2012-06-18 09:49:08
回答 2查看 1.2K关注 0票数 1

我以前遇到过这个问题,但我不记得我是如何解决它的。我正在处理一个RAT,到目前为止,它只是将客户端屏幕发送到服务器。我过去常常将图像保存到磁盘上,但现在我正尝试将其显示在JFrame上。它会显示第一个屏幕截图,但只显示第一个,不会绘制新的屏幕截图。

服务器:

代码语言:javascript
复制
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

@SuppressWarnings("serial")
public class Server extends JFrame {

private BufferedImage image;
private BufferedImage oldImage;

public Server() {
    setTitle("RAT");
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}

public static void main(String[] args) throws IOException {
    try {
        Server server = new Server();

        ServerSocket serverSocket = new ServerSocket(25565);
        Socket clientSocket = serverSocket.accept();
        System.out.println("Connection accepted!");

        ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
        boolean firstConnection = true;

        int width = 0;
        int height = 0;

        while (true) {
            if(firstConnection) {
                width = in.readShort();
                height = in.readShort();
                server.setSize(width, height);
                server.setVisible(true);
                firstConnection = false;
            }
            server.oldImage = ImageIO.read(in);
            if(server.oldImage != null) {
                server.image = server.oldImage;
            }
            server.repaint();

        }
    } catch (IOException e) {
        System.err.println("Accept failed.");
        System.exit(1);
    }
}

public void paint(Graphics g) {
    g.drawImage(image, 0, 0, this);
}
}

客户端:

代码语言:javascript
复制
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.Socket;

import javax.imageio.ImageIO;

public class Client {

public static void main(String[] args) {
    try {
        Socket socket = new Socket("127.0.0.1", 25565);
        ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
        Robot robot = new Robot();
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Rectangle rectangle = new Rectangle(toolkit.getScreenSize());
        out.writeShort(toolkit.getScreenSize().width);
        out.writeShort(toolkit.getScreenSize().height);

        while(true) {
            ImageIO.write(robot.createScreenCapture(rectangle), "jpg", out);
            Thread.sleep(200);
        }
    } catch (AWTException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}
EN

回答 2

Stack Overflow用户

发布于 2012-06-18 11:50:12

据我所知,问题是你通过编写像Thread.sleep()while(true)这样的东西阻塞了Event Dispatch Thread,从Swing的角度来看,这真的不是合适的。

你可以做些什么来解决这个问题:

Socket

  • 将循环结构带入内部使用像Socket clientSocket = serverSocket.accept();这样的代码片段阻塞了EDT,因此这样的事情必须在单独的Thread或内部完成对repaint()的递归调用gets合并从肮脏的富客户端的引用如下所述主题

的合理性

代码语言:javascript
复制
It is important to note that repaint requests get “coalesced,” or combined. 
So, for example, if you request a repaint and there is already one on the 
queue that has not yet been serviced, then the second request is ignored 
because your request for a repaint will already be fulfilled by the earlier 
request. This behavior is particularly helpful in situations where many
repaint requests are being generated, perhaps by very different situations 
and components, and Swing should avoid processing redundant requests and 
wasting effort.

与直接在JFrame上绘制不同,明智的做法是通过重写JPanel/JComponentpaintComponent(...) method.

  • Recursive Paint调用(可以通过使用paintImmediately(Rectangle rect)paintImmediately(int x, int y, int w, int h)方法来实现)在JPanel/JComponent上进行绘制。

下面是一个进一步帮助的示例程序:

代码语言:javascript
复制
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class PointsExample
{   
    private CustomPanel contentPane;
    private Timer timer;
    private int x = 1;
    private int y = 1;

    /*
     * This is just JFrame, that we be 
     * using as the Base for our Application.
     * Though here we are calling our
     * JPanel (CustomPanel), whose
     * paintComponent(...) method, we had
     * override.
     */
    private void createAndDisplayGUI()
    {
        JFrame frame = new JFrame("Locate Mouse Position");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        contentPane = new CustomPanel();
        frame.setContentPane(contentPane);  
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

        for (int i = 0; i < 500; i++)
        {
            contentPane.set(x, y);
            x++;
            y++;
            if (x == 450)
                break;
        }
    }

    public static void main(String\u005B\u005D args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new PointsExample().createAndDisplayGUI();
            }
        });
    }
}

class CustomPanel extends JComponent
{
    private int x;
    private int y;

    public void set(int a, int b)
    {
        x = a;
        y = b;
        paintImmediately(0, 0, getWidth(), getHeight());

    }   

    @Override
    public Dimension getPreferredSize()
    {
        return (new Dimension(500, 500));
    }

    @Override
    public void paintComponent(Graphics g)
    { 
        super.paintComponent(g);
        g.clearRect(0, 0, getWidth(), getHeight());
        g.fillOval(x, y, 4, 4);                        
    }
}
票数 4
EN

Stack Overflow用户

发布于 2012-06-18 10:22:17

看起来对paint()的初始调用是在image == null中进行的。这可能不是唯一的问题,但它必须得到解决。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11076168

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档