java - 线程绘制方法

标签 java multithreading swing paintcomponent event-dispatch-thread

我想知道如何线程化以下代码,或者只是一般的方法:

public void run (){

    public void paint(Graphics g) {
        g.fillRect(20, 20, 20, 20);
        for (int i = 20; i < 1000; i++) {
            g.fillRect(20, i, 20, 20);
            Thread.sleep(10);
        }
    }
}

我发现我无法创建此代码的线程,因为我遇到了表达式错误的非法开始,这很公平,但我没有找到解决方法。

最佳答案

很难说清楚自己在做什么,

但您似乎正试图覆盖 paint()Runnable从其内部 run()方法。

这肯定是做不到的。

逻辑是

  • 拿一个组件
  • 重写它的paint方法来绘制我们需要的东西
  • 调用方法来更新矩形的坐标(或者在这种情况下计时器会这样做)
  • 比电话 repaint()在组件上,因此可以再次调用 paint 方法并使用其新坐标重绘矩形(Timer 也会在更改 Rectangle 的坐标后负责重绘)
  • 根据需要/需要多次重复最后 2 个步骤

(当我说组件时,我实际上是指 JPanel绘制方法指的是重写 paintComponent(..)JPanel,因为这是最佳实践。)

一些建议:

1) 不要覆盖 paint而是使用 JPanel并覆盖 paintComponent .

2) 不要忘记兑现油漆链并调用super.XXX覆盖的实现 paintComponent(Graphics g) (或针对该事实的任何覆盖方法)除非有意将其排除在外。即

class MyPanel extends JPanel {
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

         //do drawings here
    }
}

3) 如果绘制paintComponent通常需要覆盖 getPreferredSize()并返回 Dimension符合 JPanel 的内容/图纸的 s ,即:

class MyPanel extends JPanel {
    @Override
    public Dimension getPreferredSize() {
         return new Dimension(300,300);
    }
}

3) 查看 Swing Timer 而不是 Thread.sleep(..)作为sleep将阻塞 GUI 线程并使其看起来被卡住。即

Timer t = new Timer(10, new AbstractAction() {
    int count = 20;
    @Override
    public void actionPerformed(ActionEvent ae) {
        if (count < 1000) {
            //increment rectangles y position
            //now repaint container so we can see changes in co-ordinates (unless you have a timer which repaints for you too)
            count++;
        } else {//counter is at 1000 stop the timer
            ((Timer) ae.getSource()).stop();
        }
    }
});
t.start();

4) Swing 计时器的替代方案(因为我现在看到您只是将 Rectangle 不是 Swing 组件)移动为 TimerTask ,只要不会从其 run() 中创建/操作 Swing 组件,就可以使用它。方法(因为 TimerTask 不像 Swing Timer 那样在 EDT 上运行)。备注revalidate()repaint()线程安全的,因此可以在 TimerTask 中使用.

上面的优点是保留了 EDT 的不必要代码(即通过更改坐标移动 AWT 矩形)即

    final TimerTask tt = new TimerTask() {
        @Override
        public void run() {
            if (count < 1000) {
               //increment rectangles y position
                //now repaint container so we can see changes in co-ordinates (unless you have a timer which repaints for you too)
            count++;
            } else {//counter is at 1000 stop the timer
                cancel();
            }
        }
    };

    new Timer().scheduleAtFixedRate(tt, 0, 10);//start in 0milis and call run every 10 milis

关于java - 线程绘制方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14072940/

相关文章:

java - Jsoup如何查询html键/值对的值

Java Swing 矩形2D : how to select the one on the top

java - Selenium Webdriver TestNG 测试彼此都是 "overwriting"

c++ - 何时在多线程中使用 volatile ?

c++ - gdb 错误 : Backtrace stopped: previous frame identical to this frame (corrupt stack? )

java - 如何使用 AbstractTableModel 在 JTable 上添加行?

java - java GUI 中 JFileChooser 的问题

java - 如何让tomcat7一直在线?

java - 让火箭彼此相邻显示

java - 具有连接类级联问题的 Hibernate 多对多