Java run + repaint =灰色窗口

时间:2013-05-03 07:17:28

标签: java swing jpanel paint

我正在尝试使用JFrame / JPanels repaint();等等,但是当我启动一个线程,并通过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的任何帮助表示赞赏,因为我不确定这是否正确完成。

2 个答案:

答案 0 :(得分:3)

不要在Thread.sleep(n)中调用Thread,而是为重复任务实施Swing Timer。这可确保在事件调度线程上调用repaint()

有关详细信息,请参阅Concurrency in Swing

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

工作SSCCE E.G. (注意这个版本实际上改变了结果绘制操作的共同点,所以我们知道发生了什么事情!

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

答案 1 :(得分:1)

  1. 使用java.lang.Thread.Thread( Runnable )构造函数在新线程中启动Runnable。
  2. 在Swing事件循环之外调用GUI组件的方法不是一个好习惯,而是使用Swing timer
  3. 您的代码变为:

    public static void main(String[] args) {
       ...
       new Timer( 40, new ActionListener() {
          public void actionPerformed(ActionEvent evt) {
             repaint
          }
       }).start();
       ...
    }