4

这是我试图重绘但未正确重绘的屏幕。

 public class arenaScreenBuild extends JPanel{
     int pX=200, pY=150;
     public void updateScreen(){
         repaint();
     }
     public void paintComponent(Graphics g) {
         g.drawString("x:"+pX, 535, 525);
         g.drawString("y:"+pY, 535, 545);       
     }
     public void refreshXY(int x, int y){
         pX=x;
         pY=y;
         System.out.println("Refreshed X&Y");
         updateScreen();
     }
 }

这是显示图形的屏幕。运行时,每次我移动(按右箭头键)时,它都会显示“Refreshed X&Y”,但即使它调用 updateScreen() 方法,显示的项目也不会重绘。该代码,如果它已经工作,应该在“刷新的 X&Y”之后显示 x:XVALUE, y:YVALUE。

 public class ArenaKeys extends KeyAdapter {
     arenaScreenBuild arenaBG = new arenaScreenBuild();
     int xPos = 0, playerFace = 4,xPPos = 200, yPPos = 150;

     public void keyPressed(KeyEvent e) {
         int keyCode = e.getKeyCode();
         if (keyCode == e.VK_RIGHT) {
             if (xPos <= 3250) 
               if (((xPos + xPPos) >= 825) && ((xPos + xPPos) <= 910)
                       && (yPPos >= 170) && (yPPos <= 255)) {
               } else if (((xPos + xPPos) >= 1325) && ((xPos + xPPos)<= 1410)
                       && (yPPos >= 170) && (yPPos <= 255)) {
               } else
                   xPos += 5;
           }
           arenaBG.refreshXY(xPPos+xPos,yPPos);
       }
    }

编辑: *结果它确实有效,但我正在做的是在另一个绘图面板的顶部添加一个绘图面板,这个代码是针对下面的,所以它不会让底部代码更新,我通过将两者合并在一起解决了这个问题两个拉板的代码。*

4

3 回答 3

3

在 keyPressed callEventQueue.invokeLater(new Runnable())中,由于在事件处理线程上调用了 keyPressed,因此必须推迟重绘。


有一个 AWT 事件队列,其中事件在一个线程中处理。当一个事件被处理时,比如keyPressedGUI 被冻结;其他事件不并行处理。

所以这样的事件不应该做一些花费很长时间的事情,或者改变显示。

解决方案是推迟想要执行的代码。

这可以通过以下方式完成:

EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        ... the code ...
    }
 });

在 Java 中,有一个线程(进程)在无限循环中处理 GUI 事件,例如keyPressed,按钮单击或(间接)paintComponent。为此存在一个事件等待队列,称为java.awt.EventQueue.

所以这些事情不是并行完成的。这种限制使编码更简单,并且可以更好地映射到操作系统上,比如旧的 MacOS。

因此,当keyPressed(在事件线程上)被调用时,对 repaint 的调用将不起作用,因为它必须稍后在同一线程上的 repaintComponent 上处理。

解决方案是调用invokeLaterwhich 将带有 Runnable 的事件放在事件队列中以供以后使用。

于 2012-12-19T00:03:14.503 回答
2

xPos=0 最初和

  if (xPos <= 3250) { }
         else
            xPos += 5;

这意味着 xPos 永远不会增加

于 2012-12-19T09:51:55.630 回答
1

这似乎对我有用(它是根据您的代码创建的 SSCCE)。由于它可以工作并且几乎没有对您的代码进行任何修改,因此问题可能不在于您发布的代码,而在于其他一些代码。此外,通常您希望使用Key Bindings而不是 KeyListener 来处理这类事情。

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

public class Temp extends JPanel{
     int pX=200, pY=150;
     Dimension preferredSize = new Dimension(500,300);
    public Temp(){
        addKeyListener(new KeyAdapter() {
         int xPos = 0, playerFace = 4,xPPos = 200, yPPos = 150;

         public void keyPressed(KeyEvent e) {
             int keyCode = e.getKeyCode();
             if (keyCode == e.VK_RIGHT) {
                 if (xPos <= 3250) 
                   if (((xPos + xPPos) >= 825) && ((xPos + xPPos) <= 910)
                           && (yPPos >= 170) && (yPPos <= 255)) {
                   } else if (((xPos + xPPos) >= 1325) && ((xPos + xPPos)<= 1410)
                           && (yPPos >= 170) && (yPPos <= 255)) {
                   } else
                       xPos += 5;
               }
               refreshXY(xPPos+xPos,yPPos);
           }
        });

        setFocusable(true);
        requestFocus();
    }

    public Dimension getPreferredSize(){
        return preferredSize;
    }

     public void updateScreen(){
         repaint();
     }
     public void paintComponent(Graphics g) {
         super.paintComponent(g);
         g.drawString("x:"+pX, 0, 20);
         g.drawString("y:"+pY, 0, 40);       
     }
     public void refreshXY(int x, int y){
         pX=x;
         pY=y;
         System.out.println("Refreshed X&Y");
         updateScreen();
     }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new Temp());
        frame.pack();
        frame.setVisible(true);
    }
 }
于 2012-12-19T22:39:52.270 回答