2014-11-04 60 views
0

在下面的代码中,箭头键用于在etch-a-sketch中绘制一条线(但您必须先调整窗口大小以在正确的时间触发面板的焦点请求 - 这是针对不同的问题时间,也许)。图形命令g.drawLine()发生在keyPressed()函数中,repaint()不是显式调用的,但图像会在按下箭头键时自动更新。这是为什么?我所看到的所有文档都只是谈论JPanel在调整大小或发现大小时自动重新绘制自己。什么是导致此代码重新绘制自己?

import java.awt.event.*; 
import java.awt.*; 
import javax.swing.*; 

public class Etch extends JPanel implements KeyListener{ 
    public int xPrev, yPrev, xNew, yNew, inc; 

    public Etch(int start){ 
     xPrev = start; 
     yPrev = start; 
     xNew = start; 
     yNew = start; 
     inc = 10; 
     addKeyListener(this); 


    } 

    public void paintComponent(Graphics g){ 
     super.paintComponent(g); 
     this.requestFocusInWindow(); 
    } 


    public static void main(String[] args) 
    { 
     JFrame w = new JFrame("Keyboard"); 
     w.setBounds(100, 100, 600, 600); 
     w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     Etch panel = new Etch(200); 
     panel.setFocusable(true); 
     panel.setBackground(Color.RED); 

     Container c = w.getContentPane(); 
     c.add(panel); 

     w.setResizable(true); 
     w.setVisible(true); 

    } 

    public void keyPressed(KeyEvent e){ 
     int code = e.getKeyCode(); 


     if (code == KeyEvent.VK_UP){ 
      xPrev = xNew; 
      yPrev = yNew; 
      yNew -= inc; 

     } 
     if (code == KeyEvent.VK_DOWN){ 
      xPrev = xNew; 
      yPrev = yNew; 
      yNew += inc; 

     } 
     if (code == KeyEvent.VK_LEFT){ 
      xPrev = xNew; 
      yPrev = yNew; 
      xNew -= inc; 
     } 
     if (code == KeyEvent.VK_RIGHT){ 
      xPrev = xNew; 
      yPrev = yNew; 
      xNew += inc; 
     } 

     Graphics g = this.getGraphics(); 
     g.setColor(Color.BLUE); 
     g.drawLine(xPrev, yPrev, xNew, yNew); 
    } 

    // Not used but required by the KeyListener interface 
    public void keyReleased (KeyEvent e) { } 

    public void keyTyped (KeyEvent e) { } 
} 
+1

'this.requestFocusInWindow();'是'paintComponent'方法中的一个坏主意。绘画应绘制当前状态并永不改变组件的状态 – MadProgrammer 2014-11-04 23:11:59

回答

2
  • this.requestFocusInWindow();paintComponent方法中的一个坏主意。绘画应绘制当前状态并永不改变组件的状态
  • getGraphics不是如何在Swing中完成绘画。自定义绘画应该在paintComponent方法的范围内完成。有关更多详细信息,请参见Painting in AWT and SwingPerforming Custom Painting
  • 考虑使用密钥绑定而不是KeyListener,因为您可以控制触发按键事件所需的焦点级别。有关详细信息,

记住见How to Use Key Bindings,你不控制Swing中的油漆工艺,油漆周期可以由任何数量的事件,其中大部分你不实际控制的被触发。尝试在这个过程中工作,而不是外面。

首先创建一个Listjava.awt.Point。发生关键事件时,将每个点添加到List。使用paintComponent遍历List并绘制Point之间的连线...

+0

感谢您提出有关如何改进代码的评论。鉴于我发布的代码不是实现其目的的好方法,我仍然对它的实际工作方式感到困惑,即在每次箭头键事件之后导致屏幕图像更新的原因。对图形对象所做的任何更改都会导致屏幕被重新绘制?这对我来说似乎不太可能,因为每次按下按键时都会重新绘制屏幕。 – 2014-11-05 12:52:46

+0

这是因为Swing使用被动绘画alrogtihim,也就是说,只有当RepaintManager认为它需要时,才会调用paintComponent方法。这使您可以使用getGraphics绘制最后一个已知的绘制周期结果,这也是当paintComponent再次被调用时它被擦干净的原因。绘画应该在paintComponent方法的范围内完成,这样,您就知道何时需要更新屏幕。您的关键事件应该调用repaint来发出更新UI的请求 – MadProgrammer 2014-11-05 20:09:55

相关问题