0

I'd like to make a JPanel that draws itself when it can, using multithread.

My class extends a JPanel and implements Runnable and I want to draw the JPanel not in the EDT because the listener that I have set are freezing it.

The method paintComponent() put a variable to true if the component needs to be painted.

The method drawManager() call the method draw() that paint the component. And set the variable to false when the draw() method has finished to paint.

Thanks in advance for replying!

Here is an overview of my class:

public MyClass extends JPanel implements Runnable {

    private boolean isDrawing = false;
    private Graphics2D gg;


    public MyClasse() {
        Thread t = new Thread(this);
        t.start();
    }

    // here is the run() method
    @Override
    public void run() {
        try {
            this.drawManager();
        }
        catch(InterruptedException ex) {
            Logger.getLogger(PanelPlateau.class.getName()).log(Level.SEVERE, null, ex);
        }
    }



    // here the paintComponent that tells me : you should draw if you are not drawing
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); //To change body of generated methods, choose Tools | Templates.
        synchronized(this) {
            if(!this.isDrawing) {
                this.gg = (Graphics2D)g.create();

                this.doDraw();
                this.notify();
            }
        }
    }

    // here the code that draw the JPanel when it needs to be drawn
    private void drawManager() throws InterruptedException {
        while(true) {
            synchronized(this) {
                while(!this.isDrawing) {
                    wait();
                }
            }
            this.draw(this.gg);
            this.gg.dispose();
            this.isDrawing = false;
        }
    }

    // here the code to draw my JPanel
    private void draw(Graphics2D g2d) {
        ...
    }
}
Asusio
  • 27
  • 1
  • 5
  • In general swing is not intended for multithreaded applications. – PiRocks Apr 24 '20 at 12:17
  • 1
    @PiRocks: that is completely untrue. The library easily allows for multiple threads, background threads, but all GUI library code should be called on the single event thread. – Hovercraft Full Of Eels Apr 24 '20 at 12:18
  • What is the question? – George Z. Apr 24 '20 at 12:19
  • 1
    Right. I should have clarified. Java still lets you run as many threads as you want in the background, but swing needs to be interacted with via a single threaded event thread. – PiRocks Apr 24 '20 at 12:20
  • Asusio: all painting needs to be done in the Swing event thread, so get the synchronization calls *out* of your painting method. In fact, no state-changing logic should go into a painting method but rather elsewhere in the code, and allow the painting method to do just that, painting, and nothing else. – Hovercraft Full Of Eels Apr 24 '20 at 12:20
  • Thank but, can you explain, how do you put your painting method inside another thread? @HovercraftFullOfEels – Asusio Apr 24 '20 at 12:20
  • Asusio: you don't. Yours is a classic [xy problem](http://xyproblem.info) question where your total approach to solving your problem is wrong -- you're barking up the wrong tree. Better to focus on the overall problem that you're trying to solve, not the incorrect way that you're trying to solve it. – Hovercraft Full Of Eels Apr 24 '20 at 12:21
  • You can change state fields in another thread and then call repaint(), and have your GUI use those field values to decide what to paint, but again, the painting itself must be done on the event thread – Hovercraft Full Of Eels Apr 24 '20 at 12:40
  • See [here](https://stackoverflow.com/a/58528000/3992939) an example of a thread (or threads) updating a swing gui. – c0der Apr 24 '20 at 13:19
  • @c0der Thank you! – Asusio Apr 24 '20 at 13:43

0 Answers0