【发布时间】:2012-03-07 22:02:02
【问题描述】:
我有一个奇怪的问题,可能源于对 Swing 的工作原理缺乏了解。自程序启动以来,当我第一次尝试在按下其中一个字母键时重新渲染窗口框架内的面板时,在面板再次变白之前,相关字符会在面板上非常简短地绘制.
在随后的击键中,程序会按预期运行:面板将使用与按下的键关联的字符重新渲染。
由于字符是在第一次击键时绘制的,因此它立即消失的事实一定意味着面板再次呈现,从而覆盖了以前的内容。
代码如下:
// Main.java
public class Main {
public static void main(String[] args) {
new GlyphFrame(new GlyphPanel());
}
}
// ---------------------------------------------------
// GlyphFrame.java
import javax.swing.JFrame;
public class GlyphFrame extends JFrame {
private static final long serialVersionUID = -7754180294993638709L;
private final int WIDTH = 500;
private final int LENGTH = 400;
public GlyphFrame(GlyphPanel panel){
this.add(panel);
this.setSize(WIDTH, LENGTH);
this.setVisible(true);
}
}
// ---------------------------------------------------
// GlyphPanel.java
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
public class GlyphPanel extends JPanel {
private static final long serialVersionUID = -6330730323655696958L;
public GlyphPanel(){
this.setBackground(Color.WHITE);
this.setFocusable(true);
this.requestFocusInWindow();
this.setFont(new Font("Dialog", Font.PLAIN, 12));
this.addKeyListener(new GlyphKeyListener(this));
}
private void paintPanel(Graphics g, char c){
super.paintComponent(g);
g.drawString("" + c, 10, 10);
g.setColor(this.getBackground());
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.BLACK);
g.drawString("" + c, 10, 10);
}
private class GlyphKeyListener implements KeyListener{
private GlyphPanel panel;
private int i = 0;
public GlyphKeyListener(GlyphPanel panel){
this.panel = panel;
}
@Override
public void keyTyped(KeyEvent e) {}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() >= KeyEvent.VK_A && e.getKeyCode() <= KeyEvent.VK_Z){
System.out.println("Call number " + (++i));
panel.paintPanel(panel.getGraphics(), e.getKeyChar());
}
}
@Override
public void keyReleased(KeyEvent e) {}
}
}
编辑:感谢您的回答。现在我明白了绘画应该如何在 Swing 中工作。
如果我需要面板自行重绘,我只需调用repaint(),这会使系统调用paintComponent(Graphics g)。因此,无论我想画什么,我都会把它放在一个被覆盖的paintComponent() 方法中。 paintComponent() 永远不会被直接调用。只使用repaint()。
【问题讨论】:
-
@Konstantin 的答案绝对正确(答案为 1+)。如果其中的任何部分让您感到困惑,请要求澄清,我们中的一位将帮助您解决这个问题。
-
错误是使用someComponent.getGraphics,根本不要在Swing中。
-
我明白了,paintComponent() 似乎工作正常。但是如果我不应该从我当前所在的面板调用 getGraphics,我从哪里获得必要的 Graphics 对象?
-
没关系,刚刚意识到康斯坦丁的答案正是我所需要的。