0

I am trying to generate two continous graphs in a JPanel without blocking the JFrame, with Graphics and Graphics2D library. Example of one: https://gyazo.com/2027cab6799d8416b1df8ee953d71b21

What I plan to do with this is to generate the graph at the same time that the user can change values and automatically the graph changes and is generated with these.

I am trying using Threads

Thread:

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Thread3 extends Thread {

    static int state;
    double X = 0;
    // Workspace state = 1

    @Override
    public void run() {
        if (state == 1) {
            // Graphic 2
            Graphics g = Thread1.ws.graphic2.getGraphics();
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

            double lastX = 3;
            double lastY = 0;
            double Y = 0;
            double XonScreen = 0;

            int width = Thread1.ws.graphic2.getWidth();
            int height = Thread1.ws.graphic2.getHeight();

            while (Thread1.active) {
                if (Thread1.ws.graphic2Active) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException ex) {

                    }
                    g.clearRect(0, 0, width, height);
                    XonScreen = 0;
                    for (int j = 0; j < 48; j++) {
                        lastX = XonScreen;
                        lastY = Y;

                        X += 0.005 * 10000;
                        XonScreen += 0.005 * 10000;
                        Y = Math.sin(X) * 120;

                        g2.drawLine(0, height / 2, width, height / 2);
                        g2.drawLine((int) XonScreen, ((int) Y + height / 2), (int) lastX, ((int) lastY + height / 2));
                        g2.drawLine(0, 0, 0, height);
                    }

                } else {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Thread3.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
    }
}

In this case I just set the JPanel to public and instantiated the JFrame in a static way. So far it works correctly but when running it, the graph does not update, it only updates when there is an event running. https://gyazo.com/dc72d3c1a119b2ec93b442063f32c797

I tried using frame.repaint(); but it just makes all the JPanel flick. I also tried using a timer with an ActionPerformed event:

    private Timer timer = new Timer(20, new ActionListener() {
       @Override
       public void actionPerformed(ActionEvent ae) {
           repaint();
       }
    });

but it also didn't work (I'm not sure if I implemented it correctly; if you have any suggestions about this, please let me know.) .

Do you know of any way that I can make the graphs update constantly and still manage the rest of the frame without any problems?

Danermar
  • 11
  • 1
  • Myself I'd scrap all the direct threading (and NEVER extend Thread) and static anything and would simply use a Swing Timer. It is for exactly this situation and would simply everything and reduce threading risks – DontKnowMuchBut Getting Better Oct 15 '22 at 18:38
  • In other words if I had your code I'd scrap it completely and start fresh. I'm unfortunately on a cell phone and so that is about all I can suggest: avoid fighting against the library that you use – DontKnowMuchBut Getting Better Oct 15 '22 at 18:39
  • Also, your current code looks to not be Swing thread-safe, but I am not sure what the rest of your code looks like (consider creating a [mre]). Also I'm not sure how you are getting the Graphics object, it's ultimate source, and this matters. Avoid extracting it from a Swing component via getGraphics(). Also Google "concurrency and Swing" – DontKnowMuchBut Getting Better Oct 15 '22 at 18:52
  • @DontKnowMuchButGettingBetter I didn't know about this thread-safe concepts, just searched them and decided to follow your advice and start from 0, can you give me an example of this Swing Timer, or some place where I can look for an example. Also another question, How do you recommend me to make the graph without using the .getGraphics()?, thank you a lot. – Danermar Oct 15 '22 at 20:11
  • *How do you recommend me to make the graph without using the .getGraphics()?* - custom painting is done by overriding the paintCompnent() method of a JPanel. 2) You then define properties in this panel to control the painting. 3) When the Swing Timer fires you update the properties and then invoke repaint(). Check out: https://stackoverflow.com/questions/54028090/get-width-and-height-of-jpanel-outside-of-the-class/54028681#54028681 which demonstrates the basics of using a Timer for animation. Of course, your painting logic will be different. – camickr Oct 15 '22 at 22:00
  • @camickr Justly checked, tried this and works perfectly, thank you – Danermar Oct 16 '22 at 16:11

0 Answers0