2012-06-18 109 views
1

我以前有過這個問題,但我不記得我是如何修復它的。我正在研究RAT,迄今爲止它只是將客戶端屏幕發送到服務器。我用來將圖像保存到磁盤,但現在我試圖讓它顯示在JFrame上。它顯示第一個屏幕截圖,但只顯示第一個屏幕截圖,不繪製新的屏幕截圖。Java 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(); 
    } 
} 
} 

回答

0

它看起來像最初調用paint()與image == null發生。這可能不是唯一的問題,但它必須是固定的。

4

就我所瞭解的問題而言,通過編寫諸如Thread.sleep()while(true)之類的東西來阻止事件調度線程,這個問題實際上並不適合Swing的觀點。

,你能做些什麼來排序了這一點:

  • 把裏面SwingWorker循環結構。
  • 直接使用像Socket clientSocket = serverSocket.accept();這樣的代碼片段可以阻止EDT,因此這些東西必須是 ,單獨的ThreadSwingWorker
  • 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);       
    } 
}