0

我正在尝试使用 JFrame/JPanelsrepaint();等,但是当我启动一个线程并通过 run while true 调用 repaint 时,它只会吐出System.out.println("as");我放置的一行以检查循环是否正在运行。

所以问题是:为什么我的图纸在循环调用重绘时消失了?(似乎只有JFrame/canvas_width出现height了,没有面板等)

public static void main(String[] args) {

    JFrame frame = new JFrame();
    frame.setSize(CANVAS_WIDTH, CANVAS_HEIGHT);
    frame.setPreferredSize(new Dimension(CANVAS_WIDTH, CANVAS_HEIGHT));
    frame.setVisible(true);
    frame.setResizable(false);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel p = new JPanel(new GridLayout());

    frame.getContentPane().add(p);
    Something s = new Something();

    p.add(s);
    p.setBackground(Color.black);
    frame.pack();

}

还有东西类:

public class Something extends JPanel implements Runnable {


public Something(){
    Thread t = new Thread();
    t.start();
    run();

}


@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    g.setColor(Color.cyan);
    g.fillRect(0, 0, getWidth()-150, getHeight()-100);
    g.setColor(Color.BLACK);
    g.fillOval(10, 10, 25, 25);

}


@Override
public void run() {
    while(true){
    repaint();
    System.out.println("as");

    try {
        Thread.sleep(1);
    } catch (InterruptedException e){}
    }
}
}

任何有关的帮助contentpane表示赞赏,因为我不确定这样做是否正确。

4

2 回答 2

3

而不是调用Thread.sleep(n)你的Thread,实现一个Timer用于重复任务的 Swing。这确保repaint()在事件调度线程上调用它。

有关更多详细信息,请参阅Swing 中的并发。

此外,每 1 毫秒重绘一次是非常乐观的。

工作 SSCCE EG(注意这个版本实际上改变了绘制操作的坐标,只是为了让我们知道正在发生一些事情!

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Something extends JPanel {

    static final int CANVAS_WIDTH = 400;
    static final int CANVAS_HEIGHT = 100;
    private int xDelta = 0;

public Something(){
    ActionListener animater = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            repaint();
        }
    };
    Timer t = new Timer(10,animater);
    t.start();
}


@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    g.setColor(Color.cyan);
    g.fillRect(0, 0, getWidth()-(xDelta--), getHeight()-100);
    g.setColor(Color.BLACK);
    g.fillOval(xDelta, 10, 25, 25);

    if (xDelta<0) {
        xDelta = CANVAS_WIDTH;
    }
}

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

public static void main(String[] args) {

    JFrame frame = new JFrame();

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel p = new JPanel(new GridLayout());

    frame.getContentPane().add(p);
    Something s = new Something();

    p.add(s);
    p.setBackground(Color.black);
    frame.pack();
    frame.setResizable(false);
    frame.setVisible(true);
}
}
于 2013-05-03T07:33:09.587 回答
1
  1. 在新线程中启动 Runnable 是使用java.lang.Thread.Thread(Runnable)构造函数完成的。
  2. 在 Swing 事件循环之外调用 GUI 组件的方法不是一个好习惯,请改用Swing 计时器

您的代码变为:

public static void main(String[] args) {
   ...
   new Timer( 40, new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
         repaint
      }
   }).start();
   ...
}
于 2013-05-03T07:21:54.633 回答