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();
     }
 }

グラフィックを表示する画面です。実行すると、移動する(右矢印キーを押す)たびに「RefreshedX&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);
       }
    }

編集: *動作することがわかりましたが、私が行っていたのは、別のドローパネルの上にドローパネルを追加することでした。このコードは下のコード用であるため、下部のコードを更新できませんでした。2つをマージすることでこれを解決しました。両方のドローパネルのコード。*

4

3 に答える 3

3

keyPressed callEventQueue.invokeLater(new Runnable())では、イベント処理スレッドで keyPressed が呼び出されるため、再描画を延期する必要があります。


イベントが 1 つのスレッドで処理される AWT イベント キューがあります。keyPressedGUI がフリーズするなど、イベントが処理されるとき。他のイベントは並行して処理されません。

したがって、このようなイベントは、長時間かかることや表示の変更を行うべきではありません。

解決策は、実行したいコードを延期することです。

これは次の方法で実行できます。

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

keyPressedJavaでは、ボタンのクリックや (間接的に)などの無限ループで GUI イベントを処理する単一のスレッド (プロセス) がありますpaintComponent。そのため、 と呼ばれるイベントの待機キューが存在しますjava.awt.EventQueue

したがって、これらのことは並行して行われません。この制限により、コーディングが少し簡単になり、古い MacOS などのオペレーティング システムでより適切にマッピングされます。

そのkeyPressedため、(イベント スレッドで) が呼び出された場合、repaint の呼び出しは効果がありません。これは、後で同じスレッドの repaintComponent で処理する必要があるためです。

invokeLater解決策は、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です)。それは機能し、コードにほとんど変更がないため、投稿したコードではなく、他のコードに問題がある可能性があります。また、一般的に、これらの種類のものには KeyListener の代わりにKey Bindingを使用する必要があります。

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 に答える