Exikle
Exikle

Reputation: 1165

Not sure why this graphics screen is not updating

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.*

Upvotes: 4

Views: 739

Answers (3)

Nick Rippe
Nick Rippe

Reputation: 6465

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

Upvotes: 1

StanislavL
StanislavL

Reputation: 57381

xPos=0 initially and

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

That means xPos is never increased

Upvotes: 2

Joop Eggen
Joop Eggen

Reputation: 109557

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.

Upvotes: 3

Related Questions