3

I am trying to develop a game in which I need to draw a grid. For that I am using the paintComponent(Graphics g) method which is being called by repaint() method.

The problem is that the repaint method is inside the infinite While loop and it never calls the paintComponent() method unless I minimize and maximize the screen. After that it works fine and calls the paintComponent() perfectly in the while loop.

So in short, I need to trigger it by Minimizing-Maximizing the screen.

Can anybody help me out?

In the code you can see 3 classes namely, Frame.java, MenuHandler.java & Screen.java. Code starts from the main method in Frame class and it adds the Screen class to itself as Screen extends JPanel. However, the control goes to the Screen class only when user selects "Create Map" on the menu. Then MenuHandler class passes the control to the Screen class where the run method is called in the createMap method and I invoking the repaint method inside this run method. package so;

public class Screen extends JPanel implements Runnable {
    Frame frame;

    public Screen(Frame frame) {
        this.frame = frame;
    }

    public void createMap() {

        thread.start();
    }

    public void paintComponent(Graphics g) {
        g.setColor(Color.BLUE);

    }

    @Override
    public void run() {

        System.out.println("Success******");

        long lastFrame = System.currentTimeMillis();

        int frames = 0;
        running = true;
        scene = 0;

        // the map grid would be refreshed every 2 ms so that we don't get the
        // flickering effect
        while (running) {

            frames++;

            if (System.currentTimeMillis() - 1000 >= lastFrame) {
                fps = frames;
                frames = 0;
                lastFrame = System.currentTimeMillis();
            }

            // to draw stuff all the time on the screen : goes around 2 millions
            // frames per second. Which is of no use.
            repaint();

            try {
                Thread.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.exit(0);
    }
}

Timer code in the run method:

 public void run() {

    System.out.println("Success");

    long lastFrame = System.currentTimeMillis();

    int frames = 0;
    running = true;
    scene = 0;

    // the map grid would be refreshed every 2 ms so that we don't get the
    // flickering effect
    while (running) {

        frames++;

        if (System.currentTimeMillis() - 1000 >= lastFrame) {
            fps = frames;
            frames = 0;
            lastFrame = System.currentTimeMillis();
        }
        System.out.println("before repaint");
        // to draw stuff all the time on the screen : goes around 2 millions
        // frames per second. Which is of no use.
        ActionListener taskPerformer = new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                repaint();
            }
        };

        new Timer(200, taskPerformer).start();
        System.out.println("after repaint");

        try {
            Thread.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.exit(0);
 }
David ten Hove
  • 2,748
  • 18
  • 33
Manpreet
  • 570
  • 5
  • 20
  • 7
    *"the repaint() method is inside the infinite While loop"* `repaint()` should be triggered by a Swing `Timer`. It seems this code is blocking the EDT. But for better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete Verifiable Example). – Andrew Thompson Oct 23 '14 at 04:16
  • I have updated the question with the code and explanation. – Manpreet Oct 23 '14 at 05:30
  • OK since it uses another thread it is not blocking the EDT, but then it is attempting to update the GUI ***off*** the EDT, which is another no-no. Using a `Timer` ensures the updates are performed on the EDT. – Andrew Thompson Oct 23 '14 at 05:36
  • Can you please show me where exactly should I include the Timer and how. – Manpreet Oct 23 '14 at 05:45
  • See exactly [How to Use Swing Timers](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html). – Andrew Thompson Oct 23 '14 at 05:47
  • 1
    I cannot compile the code. First of all what is the `menubar` variable in the Frame class and where does it come from? Please post an MCVE as Andrew suggested, and validate that the code you are about to post will compile and run as-is. – Olavi Mustanoja Oct 23 '14 at 06:15
  • Sorry I missed the JMenuBar object. I have updated the code. I'll try to validate the code. It the first time I am doing it. Let me try that. – Manpreet Oct 23 '14 at 06:25
  • 1
    It's better to use Timer but also you can try to wrap the repaint() call in SwingUtilities.invokeAndWait() – StanislavL Oct 23 '14 at 07:32
  • I tried using Timer but still the same issue. I have added the Timer code in my post above. Any pointers – Manpreet Oct 23 '14 at 08:22
  • Please figure out how to make an MCVE! It needs to be one source file (which might contain more than one class). The code in the question is uncompilable code snippets, we cannot compile and run it. – Andrew Thompson Oct 23 '14 at 08:38
  • Sorry guys. Due to shortage of time I was not able to validate the code I posted. But I figured out a way to do it and have posted the answer. – Manpreet Oct 24 '14 at 17:19

1 Answers1

2

I figured out the issue. it was just one line that I had to add to trigger the paintComponent method instead of doing it by minimizing-maximizing the window.

Frame was my top level container and I was adding Screen component (that extends JPanel and has the implementation of paintComponent) to the frame. So while adding, earlier I was doing

frame.add(screen);

I changed this to:

frame.getContentPane().add(screen);
frame.getContentPane().validate();

Calling the validate method after adding it did it for me. I don't know if it makes sense but yes that was the only line that worked for me.

Hope it helps.

Manpreet
  • 570
  • 5
  • 20