2

JPanel がある JFrame があり、paintComponent() を使用してその上にフリーハンドで描画しようとしています。ここで、xPOS および yPOS 変数を mouseDragged メソッド内から変更し、repaint() を呼び出すと、正常に動作します。

//**PROGRAM 1**-My DrawPanel Class
  public class DrawPanel extends JPanel implements Runnable, MouseMotionListener{
    int xpos = 0;
    int ypos = 0;
    String message;
    DrawPanel(){
        //constructor ini
        addMouseMotionListener(this);
        setBackground(Color.green);
        setSize(500, 400);
        setBounds(10, 10, 500, 400);
        }

    public void paintComponent(Graphics g) {

      g.setColor(Color.red);
      g.fillOval(xpos, ypos, 5, 5);
      }

    @Override
    public void mouseDragged(MouseEvent arg0) {
     xpos= arg0.getX();
         ypos= arg0.getY();
    //   s.SendData(xpos,ypos);
        repaint();
    }

    public void run() {

        try{
            while((message = reader.readLine())!=null) {
                int in = message.indexOf("#");
                xpos = Integer.parseInt(message.substring(0, in));
                ypos = Integer.parseInt(message.substring(in+1));
                System.out.print(xpos+" "+ypos);

                repaint();
            }}catch(Exception e){e.printStackTrace();}
    }

}

私はソケットを介して他のJavaプログラムからいくつかの新しい座標を受け入れるスレッドを持っています、私はそれらを受け入れることができます、私の

System.out.print(xpos+" "+ypos);

正常に動作しますが、その直後の repaint() メソッドは動作していないようで、エラーも何も起こりません。

参考までに、私が言及した他のJavaプログラムは同じ種類の構造を持っており、このJavaプログラムからそのJavaプログラムに座標を送ります。

//   s.SendData(xpos,ypos);

そして、スレッド内から repaint() メソッドを呼び出すことができます。しかし、なぜこれが起こっていないのか、理解できないようです。どんな助けでも感謝します、ありがとう。

SSCCE PaintBrushServer

 import java.awt.*;
 import java.awt.event.*;
//import java.awt.image.BufferedImage;
import java.io.*;
import java.net.*;
import javax.imageio.ImageIO;
import javax.swing.*;
public class PaintBrush {

DrawPanel dr = new DrawPanel();
 myFrame mf;
 Graphics g1;
 boolean flag=false;
 server s;
 BufferedReader reader;
PaintBrush(){
myFrame mf = new myFrame();
s = new server();
}

public static void main(String[] args) {

    new PaintBrush();
   }

public class ButtonPanel extends JPanel{
ButtonPanel(){
    add(new myButton());
}
 }

public class DrawPanel extends JPanel implements Runnable, MouseMotionListener{

int xpos = 0;
 int ypos = 0;
String message;

DrawPanel(){
    //constructor ini
    addMouseMotionListener(this);
    setBackground(Color.green);
    setSize(500, 400);
    setBounds(10, 10, 500, 400);
    //s = new server();

}

public void paintComponent(Graphics g) {

  g.setColor(Color.red);
  g.fillOval(xpos, ypos, 5, 5);

}

@Override
public void mouseDragged(MouseEvent arg0) {
     xpos= arg0.getX();
     ypos= arg0.getY();
     s.SendData(xpos,ypos);
    repaint();
}


@Override
public void run() {
    try{

        while((message = reader.readLine())!=null) {

            int in = message.indexOf("#");
            xpos = Integer.parseInt(message.substring(0, in));
            ypos = Integer.parseInt(message.substring(in+1));
           // System.out.print(xpos+" "+ypos);
           repaint();
        }}catch(Exception e){e.printStackTrace();}
}




}
 public class myFrame extends JFrame{
 myFrame(){
     DrawPanel dr = new DrawPanel();
    //setBackground(Color.black); 
    setResizable(false);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   setVisible(true);
    setSize(665,490);
    getContentPane().add(BorderLayout.CENTER,dr);
    getContentPane().add(BorderLayout.NORTH, new ButtonPanel());
 }
}public class myButton extends JButton{

 myButton(){
     setText("PaintBrushServer");
    // addActionListener(new listen());

 }

 }

public class server {
  ServerSocket ssock;
 Socket clientSocket;
 PrintWriter writer;
 DataOutputStream os = null;
 server(){
     //ini server
      try {
        ssock = new ServerSocket(42422);
        System.out.println("waiting");
        clientSocket = ssock.accept();
        System.out.println(clientSocket.getRemoteSocketAddress()+" connected\n");
        //writer = new PrintWriter(.getOutputStream());
        InputStreamReader streamReader = new InputStreamReader(clientSocket.getInputStream());
        reader = new BufferedReader(streamReader);
        os = new DataOutputStream(clientSocket.getOutputStream());
        new Thread(dr).start();
      } catch (IOException e) {

        e.printStackTrace();
    }
 }
 public void SendData(int x, int y){
    try{ 
        os.writeBytes(x+"#"+y+"\n");
    }catch(Exception e){e.printStackTrace();}
 }

}
}

SSCCE-PaintBrushClient

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.*;
import java.net.*;
import javax.swing.*;
public class Client {
int xpos = 0;
int ypos = 0;
Boolean flag = false;
ClientConnect cc ;
DataOutputStream os = null;

BufferedReader reader;
Client(){
//server connect
ClientConnect cc = new ClientConnect();

}
public static void main(String[] args) {

new Client();
}

public class ClientConnect {
private Socket sock;
String message;
ClientConnect(){
   try {
    sock = new Socket("127.0.0.1", 42422);
    InputStreamReader streamReader = new InputStreamReader(sock.getInputStream());
    reader = new BufferedReader(streamReader);
    os = new DataOutputStream(sock.getOutputStream());
     //sr = new ServerReader();
     //sr.start();
    new myFrame();

} catch (UnknownHostException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}
}}

public void SendData(int x, int y){
try{ 
    os.writeBytes(x+"#"+y+"\n");
}catch(Exception e){e.printStackTrace();}
}
public class DrawPanel extends JPanel implements Runnable, MouseMotionListener{

 String message;
DrawPanel(){
    //constructor ini
    addMouseMotionListener(this);
    setBackground(Color.green);
    setSize(500, 400);
    setBounds(10, 10, 500, 400);
}

public void paintComponent(Graphics g) {
  g.setColor(Color.red);
  g.fillOval(xpos, ypos, 5, 5);

}

@Override
public void run() {

    // TODO Auto-generated method stub
       try{

        while((message = reader.readLine())!=null) {
            int in = message.indexOf("#");
            xpos = Integer.parseInt(message.substring(0, in));
            ypos = Integer.parseInt(message.substring(in+1));
            //System.out.println(message);
            System.out.println(xpos+" "+ypos);
            repaint();

        }}catch(Exception e){e.printStackTrace();}
}

@Override
public void mouseDragged(MouseEvent arg0) {
    // TODO Auto-generated method stub
     xpos= arg0.getX();
     ypos= arg0.getY();
     //flag = true;
     //System.out.println(xpos);
     //SendData(xpos,ypos);
    repaint();
}

public void mouseMoved(MouseEvent arg0) {
    }
}
 public class myButton extends JButton{
 myButton(){
 setText("PaintBrushClient");
 //addActionListener(new listen());
 }
 }
public class ButtonPanel extends JPanel{
ButtonPanel(){
    add(new myButton());
}
}

public class myFrame extends JFrame{
 myFrame(){
 DrawPanel dr = new DrawPanel();
 new Thread(dr).start();
setResizable(false);
 setBackground(Color.black); 
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
    setSize(665,490);
    getContentPane().add(BorderLayout.CENTER,dr);
    getContentPane().add(BorderLayout.NORTH, new ButtonPanel());


 }
}
}
4

6 に答える 6

2
  1. データを読み取るためにスレッドを開始することはありません(サーバーで実行します。コメントアウトされた行を除いて、重複したコードを4回投稿するのはなぜですか> <)
  2. あるスレッドでの xpos/ypos の更新は、別のスレッドでは表示されない場合があります。少なくともそれらは揮発性であるべきですが、私は setXYPosition() メソッドを好むでしょう:

    public synchronized void setXYPosition(int x, int y) {
      this.xpos = x;
      this.ypos = y;
      repaint();
    }
    
  3. なぜあなたはバイトを書いて(文字)行を読んでいるのですか?
  4. レイアウト/コンポーネント階層を変更せずに、直接ペイントしているため、他の人が提案したような revalidate() は必要ありません。
于 2012-04-11T10:21:34.227 に答える
2

OK、最終的に自分のコンピューターで動作するようになったので、これはあなたに興味があると思います:

ここで 2 つのこと:

  1. をオーバーライドする場合でも、残りの上に描画する前にpaintComponentsuper: を呼び出す必要があります。super.paintComponents(g);

  2. volatile別のスレッドからアクセスするため、xpos を yposにします。

また、コードにオーバーライドされたメソッドがありません。最終的に、私はそれをすべて修正し、両方でペイントされているのを見ながら1つのフレームで描画できました(2つの異なるプログラムを起動しました)。

デザインやその他のことについて怒鳴るつもりはありません。素敵な提案を持つ他の投稿があります。

言及されていないと思う唯一のことですが、2つのプログラム間でクラスを共有している場合は、それらを別のファイルに入れて、コピー/貼り付けする代わりに数回使用します。これは、いくつかのクラスに当てはまります。そして、2 つの間にわずかな違いしかない場合は、どちらのケースにいるかを示すために変更できるパラメーターを追加するだけです。

OK、私は怒鳴っていますが、クライアントが反応して同じものを描画するのは、実際にはサーバー フレームに描画するときです。個人的には、あなたの場合、クライアントをサーバー、サーバーをクライアントと呼んでいたでしょう。通常、サーバーはクライアントを「リッスン」します。この場合、描画する場所はクライアントであり、複製された場所はサーバーですが、それは単なるセマンティクスです。

于 2012-04-11T23:02:01.387 に答える
1

1)JTextArea着信StringまたはObjectからの表示ServerSockedに使用します。使用する予定の場合はStylled Text、を見てください。JTextPane

2)SwingWorkerのopen、read、close(のfinally block)に使用するには、次のSocket2つのオプションがあります。

  • 出力がEDTであると宣言されているので、着信またはからの配信に使用するか、またはを配布するために、ラップメソッドをに提案しpublish()ます。process()CharsStringObjectSocketJTextCompoent#appendinvokeLater

  • Socked終了し、done()プットStringまたはObject希望する場合は、より簡単に待つことができますJComponent

4) Swing GUIへのRunnable#Thread配布StringまたはObjectからの使用は確かに可能ですSocketが、出力をにラップする必要があることをお勧めしますinvokeLater

Socket + SwingWorker + JTextArea3)このフォーラムに関するいくつかの非常に優れたコード

于 2012-04-11T08:50:54.963 に答える
1

上記の repaint() メソッドが PaintBrushClient で呼び出されているときに、PaintBrushServer でスレッド内から呼び出されないという問題の回答は....

DrawPanel dr = new DrawPanel();最初にすでに行ったように、 myFrame(JFrame) クラスから を削除するだけです。

コメントと提案に感謝します。@andrewThompson も良い SSCCE を提供する方法を知っています..笑

于 2012-04-12T06:21:47.007 に答える
0

座標を受け取るスレッドがあるとのことですが、これはイベント ディスパッチ スレッドですか? その場合、UI の更新がブロックされている可能性があります。

于 2012-04-11T08:26:27.487 に答える
-1

SwingUtilities.invokelater( ... )他の計算を行っている間に UI を更新するために使用できます。あなたの場合

repaint() 

またはさらに良い

revalidate();
repaint();

invokeLater実行可能な実装内で呼び出す必要があります。

于 2012-04-11T08:25:39.687 に答える