1

以前にこの問題が発生したことがありますが、どのように修正したか覚えていません。私はRATに取り組んでいますが、これまでのところクライアント画面をサーバーに送信するだけです。以前は画像をディスクに保存していましたが、今は JFrame に表示するだけにしようとしています。最初のスクリーンショットが表示されますが、最初のスクリーンショットのみが表示され、新しいスクリーンショットは描画されません。

サーバ:

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);
}
}

クライアント:

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();
    }
}
}
4

2 に答える 2

4

私が問題を理解している限り、Thread.sleep()またはのようなものを書くことによってイベントディスパッチスレッドをブロックするのは問題でwhile(true)あり、これは実際にはSwingの観点からは適切とは言えません。

これを整理するためにできること:

  • ループ構造をSwingWorker内に取り込みます。
  • Socket のようなコード スニペットを直接使用するとclientSocket = serverSocket.accept();、EDT がブロックされるため、このようなことは別のThreadまたは内部で行う必要がありますSwingWorker
  • Filthy Rich Clients からの引用を合体させるための再帰呼び出しはrepaint()、前述のトピックに関する正当化のために次のとおりです。

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.

以下は、さらに役立つプログラムの例です。

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);                        
    }
}
于 2012-06-18T03:50:11.900 に答える
0

paint() への最初の呼び出しが で発生するようimage == nullです。これが唯一の問題ではないかもしれませんが、修正する必要があります。

于 2012-06-18T02:22:16.677 に答える