如何在下一次绘制之前清除jPanel

时间:2018-08-07 05:22:45

标签: java swing netbeans jpanel graphics2d

我已经在线搜索了,据说在开始绘制新图纸之前,有很多清除jPanel的方法,但是,在尝试了所有尝试后,我仍然没有成功-结果是面板根本无法清除,而下一个绘图只是与初始绘图重叠,否则我的paintComponent()根本不会执行。

Image of problem (Overlapping)

从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);
}                                        

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); */

}

我应该调用什么方法以及在哪里放置它,以便每次我按下按钮绘制新图形时,它都会在绘制之前清除面板

1 个答案:

答案 0 :(得分:1)

  

我已经在网上搜索了,但是在开始绘制新图纸之前,有很多清除jPanel的方法

是的,不要做您正在做的事情。永远不需要手动调用paintComponent,并且除了可以返回getGraphics之外,也永远不要调用null,这不是定制绘画的方式。

Paint应该只绘制组件的当前状态。因此,如果要“清除”面板,请清除其用于决定应绘画的内容和方式的状态。

您可以通过在要更新的组件上调用repaint来触发执行新的绘画传递的请求。作为绘制过程的一部分,通常会通过在其上方绘制组件的背景颜色来“准备”组件的Graphics上下文。

首先查看Performing Custom PaintingPainting in AWT and Swing

已更新...

一个可运行的示例将使此过程变得更加容易。让我们开始...

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();是个坏主意。 getGraphics可以返回null,并且仅提供组件的快照。在下一个绘画周期中,将对其进行更新。

graphExecute.paintComponent(gfx);是个坏主意,从没有任何理由直接调用ANY paint方法。绘制系统会告诉您何时要绘制组件以及要使用什么上下文。

然后...

Graph graphExecute = new Graph();

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

...等等,什么!?您创建了一个我认为是组件Graph的组件,为它播种了一些信息,然后手动对其进行了绘制...

好的,假设它是某种JComponent,为什么不将其添加到当前用户界面

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

如果Graph不是某种类型的JComponent,那么我们遇到的问题更大,因为您需要将其传递给可以对其进行绘制的对象……可能类似于。

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);
        }
    }

}

那么您也许可以做类似...

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);
}