繁体   English   中英

甩漆方法

[英]Swing paint method

我在JPanel中的绘制方法有问题。 首先,我创建一个扩展JFrame的类。 然后,我创建一个扩展面板的类,并从该类中创建一个对象并添加到框架中。

我想要通过按键盘上的右键( VK_RIGHT )在2秒内在面板上绘制小矩形。 (这意味着将矩形清除并绘制到新位置。我的问题是:我无法执行定时绘制方法和重新绘制方法。我希望每两秒矩形前进5次(逐步),但矩形仅前进一次。

我的代码是:

Panel

import java.awt.Color;

import java.awt.Graphics;

import javax.swing.JPanel;

public class Panel extends JPanel{

    private int x;
    private int y;
    public Panel()
    {
        x=100;
        y=100;
        this.setBackground(Color.RED);
    }

    //--------------------------------

    @Override
    public void paint(Graphics g)
    {
        super.paint(g);

        g.setColor(Color.BLACK);

        g.fillRect(x, y, 20, 20);
    }

    //--------------------------------

    @Override
    public void repaint()
    {
        super.repaint();

        x+=20;
    }

    //--------------------------------
}

Frame

import java.awt.event.KeyEvent;

import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class Frame extends JFrame {

    private Panel p;

    public Frame()
    {
        super("Test");
        this.setBounds(1200, 300, 400, 400);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        p=new Panel();
        this.add(p);


        this.addKeyListener(new KeyLis());
    }

    //----------------------------------

    public static void main(String[] args) {

        Frame a=new Frame();

        a.setVisible(true);
    }

    //-----------------------------------

    private class KeyLis implements KeyListener
    {

        @Override
        public void keyPressed(KeyEvent arg0) {

            if(arg0.getKeyCode() == KeyEvent.VK_RIGHT)
            {
                for(int i=0;i<5;i++)
                {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    p.repaint();
                }
            }
        }
        //---------------
        @Override
        public void keyReleased(KeyEvent arg0) {
            // TODO Auto-generated method stub

        }
        //---------------
        @Override
        public void keyTyped(KeyEvent arg0) {
            // TODO Auto-generated method stub

        }
        //---------------
    }
    //-----------------------------------------
}

您的问题主要是在KeyListenerfor-loop ,该for-loop阻塞了Event调度线程,从而阻止绘制更新。

一个简单的解决方案是使用Swing Timer ,它在后台等待,在EDT上触发滴答,从而确保从中更新ui并定期安排更新。

有关更多详细信息,请参见Swing中的并发如何使用Swing计时器

如果由于某种原因而难以理解Swing Timer ,则也可以尝试使用SwingWorker ,它允许您使用后台线程进行循环,但是它提供了在EDT上下文中更新状态的方法。

有关更多详细信息,请参见工作线程和SwingWorker

推荐建议

通常,覆盖paintComponent而不是paint 有关更多详细信息,请参见执行自定义绘画

不要使用repaint来更新您的状态,您可能不是唯一一个调用它的人,而是创建一个可以在视图和关键控制器之间共享的模型。

有关一些想法,请参见模型-视图-控制器观察者模式

我也建议不要使用KeyListener而要使用键绑定API

有关更多详细信息,请参见如何使用键绑定

如果您设置使用线程:

将您的KeyPressed事件更改为:

        @Override
        public void keyPressed(KeyEvent arg0) {

            if (arg0.getKeyCode() == KeyEvent.VK_RIGHT) {
                PaintThread th = new PaintThread(p);
                th.start();
            }
        }

创建了一个线程:

import java.util.logging.Level;
import java.util.logging.Logger;

public class PaintThread extends Thread{

    Panel panel;

    PaintThread(Panel panel){
        this.panel = panel;
    }

    @Override
    public void run() {
        for(int i = 0; i<5; i++){
            try {
                this.sleep(1000);
                panel.repaint();
            } catch (InterruptedException ex) {
                Logger.getLogger(PaintThread.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM