代码之家  ›  专栏  ›  技术社区  ›  user2489415

试图重新绘制奔跑中的桂

  •  0
  • user2489415  · 技术社区  · 11 年前

    我正试图从代码中的run()中调用重新绘制方法。如果我从鼠标碎片或鼠标移动中重新绘制(),效果很好。但我需要从run()中完成。以下代码不会调用run()重新绘制方法。

    我是JAVA新手。有人能修复代码并粘贴代码吗?请原谅任何愚蠢的错误。顺便说一句,我看到了SwingUtilities。Vokelater可能会解决这个问题。但我不知道该怎么做。请修正代码。

    提前谢谢。

    import java.awt.Graphics;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseMotionListener;
    import javax.swing.JFrame;
    
    public class Tester {
    
    public static int x,y;
    public static void main(String[] args) {
        x = 10; y= 10;
        Draw d = new Draw();
        new Thread(d).start();
    }
    
    
    public static class Draw extends JFrame implements Runnable,MouseMotionListener
    {
    
        public Draw()
        {
            super("Title");
            setSize(500,500);
            addMouseMotionListener(this);
            setVisible(true);
        }
    
    
        @Override
        public void run() {
            for(int i = 0 ; i < 10 ; i++)
            {   
                System.out.println("Multithreaded");
                repaint();
            }
    
        }
    
        @Override
        public void mouseDragged(MouseEvent e) {
    
        }
    
        @Override
        public void mouseMoved(MouseEvent e) {
    
    
        }
    
        public void paint(Graphics g)
        {
            System.out.println("repaint called");
        }
    
    }
    
    
    }
    
    2 回复  |  直到 11 年前
        1
  •  2
  •   MadProgrammer    11 年前

    给员工一个被动的重新喷漆引擎。也就是说,它只会在需要时更新 RepaintManager 还进行了优化,以将多个重新绘制合并为其认为需要的尽可能少的重新绘制事件。

    这意味着您可以请求 repaint ,但无法保证何时或是否会重新喷漆。

    这样做主要是为了优化性能。

    退房 Painting in AWT and Swing 了解更多详细信息。

    因为它是自然的, 重新喷漆 是线程安全的。 重新喷漆 询问 重新喷漆管理器 将绘制事件发布到事件队列中。此队列由事件调度线程处理,这意味着您不必同步 重新喷漆 使用EDT。

    下面的例子说明了这一观点。它提供了一个简单的滑块,可以重置绘制计数器并设置之间的延迟 重新喷漆 请求。

    线程延迟0毫秒。。。

    enter image description here

    线程延迟2秒

    enter image description here

    正如你所看到的。在0毫秒时(这实际上是你在循环中所做的),实际绘制的数量与重新绘制请求的数量不匹配,但在延迟2秒时,实际绘制和绘制请求几乎相等(我认为额外的一个来自滑块进行的重新绘制)。

    事实上,在我的测试中,在大约100毫秒的时间里,我能够使它大致相等。我甚至尝试了5毫秒,并使其达到平衡。

    实际油漆的作用和EDT上的负载也会影响这些结果。。。

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.Font;
    import java.awt.FontMetrics;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JSlider;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.event.ChangeEvent;
    import javax.swing.event.ChangeListener;
    
    public class RepaintTest {
    
        public static void main(String[] args) {
            new RepaintTest();
        }
    
        public RepaintTest() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException ex) {
                    } catch (InstantiationException ex) {
                    } catch (IllegalAccessException ex) {
                    } catch (UnsupportedLookAndFeelException ex) {
                    }
    
                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new TestPane());
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class TestPane extends JPanel {
    
            private int paintRequests;
            private int paints;
            private int delay = 0;
    
            public TestPane() {
                Thread t = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        while (true) {
                            paintRequests++;
                            try {
                                Thread.sleep(delay);
                            } catch (InterruptedException exp) {
                            }
                            System.out.println("tick");
                            repaint();
                        }
                    }
                });
                t.setDaemon(true);
                setLayout(new BorderLayout());
                final JSlider slider = new JSlider();
                slider.setMinimum(0);
                slider.setMaximum(2000);
                slider.setPaintTicks(true);
                slider.setMajorTickSpacing(100);
                slider.addChangeListener(new ChangeListener() {
                    @Override
                    public void stateChanged(ChangeEvent e) {
                        delay = slider.getValue();
                        paintRequests = 0;
                        paints = 0;
                    }
                });
                slider.setValue(0);
                add(slider, BorderLayout.SOUTH);
                t.start();
            }
    
            @Override
            public Dimension getPreferredSize() {
                return new Dimension(200, 200);
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                paints++;
                String text = "Paints = " + paints + "; Paint Requests = " + paintRequests;
                Graphics2D g2d = (Graphics2D) g.create();
                FontMetrics fm = g2d.getFontMetrics();
                int x = (getWidth() - fm.stringWidth(text)) / 2;
                int y = ((getHeight() - fm.getHeight()) / 2) + fm.getAscent();
                g2d.drawString(text, x, y);
                g2d.dispose();
            }
    
        }
    }
    
        2
  •  0
  •   Omar Abdeldayem    11 年前

    尝试实施 ActionListener ,然后添加此代码位:

    import javax.swing.Timer;
    private final int DELAY = 60;
    private Timer t;
    public Draw() {
        //your code
        t = new Timer(DELAY, this);
        t.start();
    }
    //implemented method
    @Override
    public void actionPerformed(ActionEvent e) {
        repaint();
    }
    

    很不言自明,不管里面是什么 actionPerformed 方法的调用频率为 DELAY 毫秒。