摇绘法
Swing paint method
我在 JPanel
中的绘画方法有问题。
首先,我创建了一个扩展 JFrame
的 class。
然后我创建一个扩展面板的 class 并从这个 class 创建一个对象并添加到框架。
我想通过按键盘上的右键 (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
}
//---------------
}
//-----------------------------------------
}
您的问题主要是 KeyListener
中的 for-loop
,它阻塞了事件调度线程,阻止了更新。
简单的解决方案是使用 Swing Timer
,它在后台等待,在 EDT 上触发滴答,确保安全地更新 ui 并定期安排更新。
有关详细信息,请参阅 Concurrency in Swing and How to use Swing Timers
如果出于某种原因,您发现 Swing Timer
难以理解,您也可以尝试使用 SwingWorker
,这将允许您使用后台线程循环,但是它提供了在 EDT 上下文中更新状态的方法。
有关详细信息,请参阅 Worker Threads and SwingWorker
建议
作为一般规则覆盖 paintComponent
而不是 paint
。有关详细信息,请参阅 Performing Custom Painting
不要使用 repaint
来更新你的状态,你可能不是唯一调用它的人,而是创建一个可以在视图和你的关键控制器之间共享的模型。
请参阅 Model-View-Controller and Observer Pattern 了解一些想法
我也不鼓励使用 KeyListener
并改用键绑定 API
有关详细信息,请参阅 How to Use Key Bindings
如果您准备使用线程:
将您的 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);
}
}
}
}
我在 JPanel
中的绘画方法有问题。
首先,我创建了一个扩展 JFrame
的 class。
然后我创建一个扩展面板的 class 并从这个 class 创建一个对象并添加到框架。
我想通过按键盘上的右键 (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
}
//---------------
}
//-----------------------------------------
}
您的问题主要是 KeyListener
中的 for-loop
,它阻塞了事件调度线程,阻止了更新。
简单的解决方案是使用 Swing Timer
,它在后台等待,在 EDT 上触发滴答,确保安全地更新 ui 并定期安排更新。
有关详细信息,请参阅 Concurrency in Swing and How to use Swing Timers
如果出于某种原因,您发现 Swing Timer
难以理解,您也可以尝试使用 SwingWorker
,这将允许您使用后台线程循环,但是它提供了在 EDT 上下文中更新状态的方法。
有关详细信息,请参阅 Worker Threads and SwingWorker
建议
作为一般规则覆盖 paintComponent
而不是 paint
。有关详细信息,请参阅 Performing Custom Painting
不要使用 repaint
来更新你的状态,你可能不是唯一调用它的人,而是创建一个可以在视图和你的关键控制器之间共享的模型。
请参阅 Model-View-Controller and Observer Pattern 了解一些想法
我也不鼓励使用 KeyListener
并改用键绑定 API
有关详细信息,请参阅 How to Use Key Bindings
如果您准备使用线程:
将您的 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);
}
}
}
}