4

This is the screen that im trying to repaint but it is not repainting properly.

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

This is the screen displaying the graphics. When run, every time i move(press the right arrow key), it displays "Refreshed X&Y" but even though it calls the updateScreen() method, the displayed items are not redrawn. The code, if it had worked, should display x:XVALUE, y:YVALUE after the "refreshed X&Y".

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

EDIT: *Turns out that it does work but what i was doing was adding a Drawpanel on top of another drawpanel and this code was for the one underneath so it wasn't letting the bottom code update, i solved this by merging together the two codes for both drawpanels.*

Exikle
  • 1,155
  • 2
  • 18
  • 42
  • 2
    For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Dec 18 '12 at 23:58
  • Not done. I see 2 source files, and no `main(String[])`. Also 1) Use Key Bindings for Swing 2) Those magic numbers in the `ArenaKeys` look suspicious. 3) Add @Override notation – Andrew Thompson Dec 19 '12 at 00:10
  • I took out those numbers, i'm not sure what @override is because i have never learned it (I'm a beginner student) and what are key bindings for swing? – Exikle Dec 19 '12 at 00:40
  • 2
    *"and what are key bindings for swing?"* Have you heard of Google?!? Try 'key+bindings+swing'. I also recommend 'override+java'. Go on, give it a crack.. Are you still working on that SSCCE, or have you even read the document yet? – Andrew Thompson Dec 19 '12 at 00:42

3 Answers3

3

In keyPressed call EventQueue.invokeLater(new Runnable()), as keyPressed is called on the event handling thread, and the repainting must be postponed.


There is a AWT event queue where event are handled in one single thread. When an event is handled, like keyPressed the GUI is frozen; other events are not parallel handled.

So such events should not do something taking a long time, or changing the display.

The solution is to postpone the code one wants to execute.

This can be done with:

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

In java there is one single thread (process) that handles GUI events in an endless loop, like keyPressed, button click or (indirectly) paintComponent. For that exists a wait queue of events, called java.awt.EventQueue.

So these things are not done in parallel. That limitation makes coding a bit simpler, and mapped better on the operating systems, like the old MacOS.

So when keyPressed is called (on the event thread), a call to repaint will have no effect, as that must be handled on a repaintComponent later, on the same thread.

The solution is to call invokeLater which places an event with a Runnable on the event queue for later.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • I'm sorry, not sure what that means – Exikle Dec 19 '12 at 00:06
  • No offence, but I have no idea what that code does and i dont understand your explanation. Im a beginner java student – Exikle Dec 19 '12 at 00:24
  • No offense at all; one should be able to clearly state things; and I just failed. – Joop Eggen Dec 19 '12 at 00:40
  • So i read the second part of your explanation. Does it mean that i have to place the code you gave in place of the repaint and put repaint() where "...the code..." is? so when should i call it? – Exikle Dec 19 '12 at 01:24
  • @Swing GUI objects should be constructed and manipulated _only_ on the [event dispatch thread](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html). – trashgod Dec 19 '12 at 01:46
  • @trashgod Sorry that just confused me, what do you mean? – Exikle Dec 19 '12 at 01:49
  • @Exikle: Here's a complete [example](http://stackoverflow.com/a/2114490/230513) for reference. – trashgod Dec 19 '12 at 01:59
2

xPos=0 initially and

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

That means xPos is never increased

StanislavL
  • 56,971
  • 9
  • 68
  • 98
  • sorry, that was a mistake of me moving the code from eclipse to this site and editing the code so it'll be easier to see, i changed it so that its closer to the original – Exikle Dec 19 '12 at 16:54
1

This seems to work for me (it's an SSCCE created out of your code). Since it works and there's virtually no modifications to your code, the problem probably doesn't lay in the code you posted, but in some other code. Also, generally you'd want to use Key Bindings instead of a KeyListener for these sorts of things.

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);
    }
 }
Nick Rippe
  • 6,465
  • 14
  • 30
  • Turns out that it does work but what i was doing was adding a Drawpanel on top of another drawpanel and this code was for the one underneath so it wasn't letting the bottom code update, i solved this by merging together the two codes for both drawpanels. – Exikle Dec 22 '12 at 06:51