0

I have a main class that holds a Array List of objects and has a Swing timer that repaints a separate JFrame Class. Despite the repaint method being called, the screen isn't being updated.

What's supposed to happen: When any key is pressed, the x location of two objects are updated. A swing timer that ticks every half second calls the repaint method. The images are then redrawn in their updated locations.

From what I can tell the location of the images are being updated, as when I minimize and reopen the JFrame window, the images have moved.

I've tried changing the intervals at which the timer runs, moving the swing timer to the JFrame class, putting the repaint(); in a thread. However I still don't know why repaint(); isn't updating the screen.

Here's a sketch of my code: JFrame class

public class testingGround extends JPanel { private Image image; private qwq getter = new qwq(); protected Keyboard keyboard = new Keyboard(); //KeyListener, imported from Keyboard class private JFrame frame = new JFrame(); //JFrame variable public void createGUI(){ testingGround panel = new testingGround(); // Creating a new JPanel, for objects to be drawn on JFrame frame = new JFrame("Game"); //Creating a new JFrame called frame frame.setSize(600, 600); //Setting the size of the JFrame frame to be 600x600 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// Setting so the frame exits on close frame.setVisible(true); frame.add(panel);// Adding the JPanel panel to the JFrame frame, so it's visible frame.addKeyListener(keyboard); //Adding a KeyListener to detect users input in the JFrame frame } public Frame getFrame() { //Constructor class to get JFrame in other classes return frame; } public void initComponents(){ ImageIcon imageIcon = new ImageIcon("C:/Users/destr/workspace/GameWIP3/bin/A2.png"); image =imageIcon.getImage(); } protected void paintComponent (Graphics g){//Drawing super.paintComponent(g); initComponents(); for (int i=0;i<getter.getFListSize();i++) { System.out.print("paint called"); g.drawImage(image, getter.getFighter(i).getFighterX(), getter.getFighter(i).getFighterY(), null); } } } 

Keyboard Class

public class Keyboard implements KeyListener { private qwq getter = new qwq(); @Override public void keyPressed(KeyEvent e) { getter.getFighter(0).setFighterX(500);; getter.getFighter(1).setFighterX(200);; System.out.print("Updated the x value of two"); } 

Main Class

public class qwq implements ActionListener { private static ArrayList<Fighter> FighterList = new ArrayList<Fighter>(); // ArrayList // of // Fighters Timer timer = new Timer(500, this); private static testingGround GUI = new testingGround(); public qwq() { timer.start(); } public Fighter getFighter(int i) { return FighterList.get(i); // To retrieve a fighter from the Array List } public void addFighter(Fighter i) { FighterList.add(i); // To add a fighter to the Array list } public int getFListSize() { return FighterList.size(); } public static void main(String[] args) { GUI.createGUI(); GUI.getFrame(); FighterList.add(new Fighter(0, 0)); FighterList.add(new Fighter(20, 50)); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == timer) { GUI.repaint(); } } } 

Object Class

public class Fighter { private int fighterX; private int fighterY; public Fighter ( int fighterX, int fighterY) { this.setFighterX(fighterX); this.setFighterY (fighterY); } public int getFighterX (){ return fighterX; //method to get x coordinate of a fighter } public int getFighterY (){ return fighterY;//method to get y coordinate of a fighter } public void setFighterX(int fighterX) { this.fighterX = fighterX; //method to set the x coordinate of a fighter } public void setFighterY(int fighterY) { this.fighterY = fighterY; //method to set the y coordinate of a fighter } } 
3
  • Just about every one of your classes is creating a new instance qwq, along with the static references to FighterList and GUI, it's impossible to know who's actually referencing who, this is just a bunch of tightly coupled spaghetti code Commented Oct 21, 2015 at 1:49
  • It also means you have at least two Timers running Commented Oct 21, 2015 at 1:50
  • In TestingGround, you create another instance of TestingGround, so the reference that have you Qwq has nothing to do with the instance which is actually displayed on the screen, also, you create a new instance of a JFrame which has absolutely nothing to do with the instance of the JFrame you return via getFrame! Commented Oct 21, 2015 at 1:52

1 Answer 1

3
  • You are creating multiple instances of qwq, in testingGround and Keyboard, these having nothing to do with each other and only mean that you are now creating a new Timer each time you create a new instance of it
  • In your testingGround#createGUI you create a new instance of testingGround, which gets added to a new instance of a JFrame, so the reference that qwq has to testingGround has nothing to do with the instance which is actually on the screen!? Further more, you create a new instance of JFrame in createGUI which has no relationship to the instance of JFrame you return from getFrame!?

OO is all about responsibilities, whose responsible for what. For example, you testingGround class shouldn't be making frames, it's not it's responsibility. It should be responsible for rendering the current state of the game.

For example...

import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class Qwq { public static void main(String[] args) { new Qwq(); } public Qwq() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { ex.printStackTrace(); } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(new TestingGround()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class Keyboard extends KeyAdapter { private List<Fighter> fighterList; public Keyboard(List<Fighter> fighterList) { this.fighterList = fighterList; } @Override public void keyPressed(KeyEvent e) { fighterList.get(0).setFighterX(500); fighterList.get(1).setFighterX(200); System.out.print("Updated the x value of two"); } } public class TestingGround extends JPanel { private ArrayList<Fighter> fighterList = new ArrayList<>(); private Image image; private Keyboard keyboard; public TestingGround() { loadImages(); addKeyListener(new Keyboard(Collections.unmodifiableList(fighterList))); Timer timer = new Timer(500, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { repaint(); } }); timer.start(); } public void loadImages() { ImageIcon imageIcon = new ImageIcon("C:/Users/destr/workspace/GameWIP3/bin/A2.png"); image = imageIcon.getImage(); } protected void paintComponent(Graphics g) {//Drawing super.paintComponent(g); for (Fighter fighter : fighterList) { System.out.print("testing"); g.drawImage(image, fighter.getFighterX(), fighter.getFighterY(), null); } } } public static class Fighter { private int fighterX; private int fighterY; public Fighter(int fighterX, int fighterY) { this.setFighterX(fighterX); this.setFighterY(fighterY); } public int getFighterX() { return fighterX; //method to get x coordinate of a fighter } public int getFighterY() { return fighterY;//method to get y coordinate of a fighter } public void setFighterX(int fighterX) { this.fighterX = fighterX; //method to set the x coordinate of a fighter } public void setFighterY(int fighterY) { this.fighterY = fighterY; //method to set the y coordinate of a fighter } } } 

Now, it would easy to have the Timer separate, but I was to lazy

Sign up to request clarification or add additional context in comments.

2 Comments

This part made it from the main source code: protected void paintComponent(Graphics g) {//Drawing super.paintComponent(g); initComponents();.. That last method (which loads an image) should be called once from the constructor. The method should probably also be renamed (e.g. loadImage()).
I also did add the "addFighter" methods, so it's still a little messy, but thanks for the proof read

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.