VinceSmithangura
VinceSmithangura

Reputation: 21

How to clear jPanel before next drawing

I've searched up online and there are supposedly many ways to clear a jPanel before starting a new drawing however, after trying all I still have no success - the outcomes are either the panel doesn't clear at all and the next drawing simply overlaps the initial one or my paintComponent() simply won't execute at all.

Image of problem (Overlapping)

Code for executing drawing from GUI:

private void BTCGraphActionPerformed(java.awt.event.ActionEvent evt) {                                         

    Graphics2D gfx = (Graphics2D) jPanel2.getGraphics();
    WebScraper WSBTC = new WebScraper();
    float[] HBTC = WSBTC.HScrapeBTC();

    Graph graphExecute = new Graph();

    graphExecute.CurrentValues(HBTC);
    graphExecute.IndexLarge(HBTC);
    graphExecute.IndexSmall(HBTC);
    graphExecute.Plotter(HBTC);
    graphExecute.paintComponent(gfx);
}                                        

private void LTCGraphActionPerformed(java.awt.event.ActionEvent evt) {                                         

    Graphics2D gfx = (Graphics2D) jPanel2.getGraphics();
    WebScraper WSLTC = new WebScraper();
    float[] HLTC = WSLTC.HScrapeLTC();
    Graph graphExecute = new Graph();

    graphExecute.CurrentValues(HLTC);
    graphExecute.IndexLarge(HLTC);
    graphExecute.IndexSmall(HLTC);
    graphExecute.Plotter(HLTC);
    graphExecute.paintComponent(gfx);
}                                        

private void ETHGraphActionPerformed(java.awt.event.ActionEvent evt) {                                         

    Graphics2D gfx = (Graphics2D) jPanel2.getGraphics();
    WebScraper WSETH = new WebScraper();
    float[] HETH = WSETH.HScrapeETH();
    Graph graphExecute = new Graph();

    graphExecute.CurrentValues(HETH);
    graphExecute.IndexLarge(HETH);
    graphExecute.IndexSmall(HETH);
    graphExecute.Plotter(HETH);
    graphExecute.paintComponent(gfx);
}                                        

Code for paintComponent():

protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    Graphics2D g2 = (Graphics2D) g;
    super.paintComponent(g2);
    int DotSize = 10;

    int width = g2.getFontMetrics().stringWidth("Today");
    int middle = width / 2;

    g2.setColor(Color.BLACK);
    /* g2.drawLine(10, 10, 10, 410); //Frame Boundaries
    g2.drawLine(410, 10, 10, 10); //Frame Boundaries
    g2.drawLine(410, 10, 410, 410); //Frame Boundaries
    g2.drawLine(410, 410, 10, 410); //Frame Boundaries */

    //Axis
    g2.drawLine(30, 30, 30, 370);
    g2.drawLine(370, 370, 30, 370);

    //Points & Connections
    PlotPoints(g2, 98, DistanceDay1, DotSize);
    g2.drawLine(98, DistanceDay1, 166, DistanceDay2);
    PlotPoints(g2, 166, DistanceDay2, DotSize);
    g2.drawLine(166, DistanceDay2, 234, DistanceDay3);
    PlotPoints(g2, 234, DistanceDay3, DotSize);
    g2.drawLine(234, DistanceDay3, 302, DistanceDay4);
    PlotPoints(g2, 302, DistanceDay4, DotSize);
    g2.drawLine(302, DistanceDay4, 370, DistanceDay5);
    PlotPoints(g2, 370, DistanceDay5, DotSize);

    //Labels
    g2.drawString("Today", 370 - middle, 390);
    /*  g2.drawString("Test", 98 - middle, 40);
    g2.drawString("Test", 146, 25); */

}

What method should I call and where do I have to place it so that every time I press a button to draw a new graph it clears the panel before drawing

Upvotes: 0

Views: 3398

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347194

I've searched up online and there are supposedly many ways to clear a jPanel before starting a new drawing however

Yes, don't do what you're doing. There is NEVER any need to call paintComponent manually and you should NEVER call getGraphics, apart from be capable of returning null, this is NOT how custom painting should be done.

Paint should only paint the current state of the component. So, if you want to "clear" the panel, clear the state it uses to decide what and how it should be painted.

You can trigger a request to perform a new paint pass by calling repaint on the component you want updated. As part of the paint pass, the Graphics context for the component will be "prepared", usually by painting the component's background color over it.

Start by taking a look at Performing Custom Painting and Painting in AWT and Swing

Updated...

A runnable example would make this much easier. Let's start with...

private void LTCGraphActionPerformed(java.awt.event.ActionEvent evt) {                                         

    Graphics2D gfx = (Graphics2D) jPanel2.getGraphics();
    WebScraper WSLTC = new WebScraper();
    float[] HLTC = WSLTC.HScrapeLTC();
    Graph graphExecute = new Graph();

    graphExecute.CurrentValues(HLTC);
    graphExecute.IndexLarge(HLTC);
    graphExecute.IndexSmall(HLTC);
    graphExecute.Plotter(HLTC);
    graphExecute.paintComponent(gfx);
}    

Graphics2D gfx = (Graphics2D) jPanel2.getGraphics(); is a bad idea. getGraphics can return null and only provides a snapshot of the component. On the next paint cycle, it will be updated.

graphExecute.paintComponent(gfx); is a bad idea, there is NEVER any reason why you should be calling ANY paint method directly. The paint system will tell you when it wants your component painted and to what context it want's used.

And then...

Graph graphExecute = new Graph();

graphExecute.CurrentValues(HLTC);
graphExecute.IndexLarge(HLTC);
graphExecute.IndexSmall(HLTC);
graphExecute.Plotter(HLTC);
graphExecute.paintComponent(gfx);

...wait, what!? You create, what I assume is a component Graph, you seed it some information and then you manually paint it...

Okay, assuming it is a JComponent of some kind, why not just add it to the current UI

jPanel2.removeAll();
jPanel2.add(graphExecute);
jPanel2.invalidate();
jPanel2.repaint();

If, Graph is not a JComponent of some kind, then we have a larger issue, as you will need to pass it to something which can paint it...maybe something like...

public class RenderPane extends JPanel {
    
    private Graph graph;
    
    public RenderPane() {
    }

    public void setGraph(Graph graph) {
        this.graph = graph;
        repaint();
    }

    public Graph getGraph() {
        return graph;
    }
    
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(200, 200);
    }
    
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graph grap = getGraph();
        if (grap != null) {
            grap.paintComponent(g);
        }
    }
    
}

Then you might be able to do something like...

private void LTCGraphActionPerformed(java.awt.event.ActionEvent evt) {                                         

    jPanel2.removeAll();
    WebScraper WSLTC = new WebScraper();
    float[] HLTC = WSLTC.HScrapeLTC();
    Graph graphExecute = new Graph();

    graphExecute.CurrentValues(HLTC);
    graphExecute.IndexLarge(HLTC);
    graphExecute.IndexSmall(HLTC);
    graphExecute.Plotter(HLTC);

    RenderPane renderer = new RenderPane();
    renderer.setGraph(graphExecute.Plotter);
    jPanel.add(renderer);
}    

Upvotes: 1

Related Questions