简体   繁体   中英

Repainting a JPanel with data from another object (thread)

I'm facing a problem where a JPanel takes data from an object which has a cycle updating its state variables.

The scenario is as follows: a JFrame calls a method of the object, the method creates the second JFrame has a cycle then updating a state variable. The second JFrame access that variable and should be displayed in a JPanel, but no, the GUI hangs.

I reduced the problem to an example with the same behavior so it can be easily tested.

I appreciate any help, thanks!

Starter.java

public class Starter extends JFrame {

    JButton button = new JButton("Fight!");

    public Starter() {

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                OneClass.getInstance().start();
            }
        });
        add(button);
    }

    public static void main(String[] args) {

        Starter frame = new Starter();

        frame.setTitle("Test");
        frame.setSize(400, 300);
        frame.setVisible(true);

    }
}

OneClass.java

public class OneClass {

    private OneFrame frame;
    private int count;
    private static OneClass instance;

    private OneClass() {
    }

    public static OneClass getInstance() {
        if (instance == null)
            instance = new OneClass();

        return instance;
    }

    public void start() {
        frame = new OneFrame();
        frame.setSize(400, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

        while (true)
        {
            count++;
            System.out.println(count);

            frame.repaint();            
        }
    }

    public int getCount() {
        return count;
    }
}

OneFrame.java

public class OneFrame extends JFrame {

    private OnePanel panel = new OnePanel();

    public OneFrame() {
        setTitle("Test frame");
        setContentPane(panel);
        setResizable(false);
    }
}

OnePanel.java

public class OnePanel extends JPanel {

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Font ft = new Font("Times New Roman", Font.PLAIN, 20);
        g.setFont(ft);

        g.drawString("Count = " + OneClass.getInstance().getCount(), 20, 20);
    }
}

Try this:

  public Starter() {

    button.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent arg0) {
        new Thread() {
          public void run() {
            OneClass.getInstance().start();
          }
        }.start();
      }
    });
    add(button);
  }

Since your loop runs in the same Thread as the GUI it will hangs once you reach the infinite loop.

If you run your infinite loop inside another thread then the GUI will be free of that loop.

This may not be the best thread implementation

Take a look to concurrency tutorials: http://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html

Now since you are using a Singleton like class, if you call the getInstance before the thread then it may still hang.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM