键上的JTextField输入闪烁的黑色

时间:2012-10-17 02:16:21

标签: java swing jtextfield

我正在使用swing制作游戏画布并决定使用JTextField来输入用户名和密码到面板中。

我正在缓冲图像,然后将其渲染到屏幕上,而不是将所有内容直接绘制到面板上。

我遇到了一个问题,我画了一个背景并将我的两个文本字段都设置为不透明,但似乎每当我在那些文本字段中输入内容时它会闪烁一个黑框,其中{{1是的。

它出现在我的用户名和密码字段中。知道原因可能是什么?

其他有用的信息:每当我点击一个文本框时,两个组件都会在第一个字符的位置闪烁黑色。

编辑 - 我刚注意到登录按钮在JTextFieldMOUSE_ENTERED时也闪烁黑色。

MOUSE_EXIT

这是文本字段:(来自使用getPanel()完全调用GamePanel的单独类...)

public class GamePanel extends JPanel implements Runnable {


public GamePanel(int width, int height) {
    this.pWidth = width; 
    this.pHeight = height;

    setController(new LoginGameController(this));

    setPreferredSize( new Dimension(pWidth, pHeight));
    setBackground(Color.BLACK);

    setFocusable(true);
    requestFocus();    // the JPanel now has focus, so receives key events

    // create game components

    addMouseListener(this);
    addKeyListener(this);

    setLayout(null);

    startGame();
}
 private void startGame()
  // initialise and start the thread 
  { if (animator == null) {
      animator = new Thread(this);
      animator.start();
    }
  }

public void run() {
    while(true) {
          gameUpdate(); 
          if(getGraphics() != null){
              gameRender();   // render the game to a buffer
              paintScreen();  // draw the buffer on-screen
          }
          try {
            Thread.sleep(28);
          } catch (InterruptedException e) {}
    }
}

private void paintScreen() {
    Graphics2D g = (Graphics2D) getGraphics();

    if ((g != null) && (img != null))
            g.drawImage(img, 0, 0, null);

    Toolkit.getDefaultToolkit().sync();
    g.dispose();
}

private void gameRender() {
    if(getWidth() > 0 && getHeight() > 0)
        img = createImage(getWidth(), getHeight());

    if(img != null) {
        Graphics2D g = (Graphics2D) img.getGraphics();
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g.setColor(Color.BLACK);
        g.fillRect(0, 0, pWidth, pHeight);

        getController().render(img);

        paintComponents(img.getGraphics());


    }
}

}

谢谢!

2 个答案:

答案 0 :(得分:3)

基本问题是,当你更新你的图形时,你绕过了Swings重绘过程并且不尊重EDT。

JComponent#getGraphics是一个临时/临时缓冲区,将在下次重绘时重新绘制。此外,如果您没有创建图形,则不应将其丢弃!

public void run() {
    while(true) {
          gameUpdate(); 
          if(getGraphics() != null){
              gameRender();   // render the game to a buffer
              try {
                  SwingUtilities.invokeAndWait(new Runnable() {
                      public void run() {
                          paintScreen();  // draw the buffer on-screen
                      }
                  });
              } catch (Exception exp) {
                  exp.printStackTrace(); // please clean this up
              }
          }
          try {
            Thread.sleep(28);
          } catch (InterruptedException e) {}
    }
}

我不知道这是否会解决它,但它不会伤害。 (这会影响你的FPS,你应该考虑画画需要多长时间以及你想等多久)

另外,而不是调用paintScreen(),您可以调用repaint(或让paintScreen执行此操作)并覆盖paintComponent方法来绘制缓冲区。

这将允许Swing正确地恢复对绘制过程的控制。

答案 1 :(得分:2)

窗口或组件至少有三种重绘方式。

  1. 当操作系统丢失部分窗口缓冲区时按需操作。
  2. 在库组件更改其状态时按需提供。
  3. 通过操纵自己的帧缓冲区手动。
  4. 通常,以下途径是有效的:

    操作系统可以请求更新特定矩形。这是由工具包提取的。此外,组件也可以通过其repaint方法向工具箱发出变化信号。该工具包持续收集合并传入重绘请求一段时间,然后要求窗口重新绘制特定矩形。窗口的默认操作是通过调用其paintComponent方法来绘制自身,其中它不与实心子项重叠,然后递归绘制其组件。

    如果你自己进行渲染,工具包也是这样做的。由于您没有覆盖paintComponent,因此当此方法运行时,它将作为默认值。默认操作是什么都不做。然后工具包拾取空帧缓冲区并在其上绘制按钮(不会绘制背景)。

    您可以禁用工具包的渲染过程并自行渲染(抓取缓冲区,绘制到其中,然后提交)。您可以调用setIgnoreRepaint(true)方法忽略操作系统的请求。