0

我在网上搜索过,据说有很多方法可以在开始新绘图之前清除 jPanel 但是,在尝试了所有之后我仍然没有成功 - 结果是面板根本不清除并且下一个绘图只是重叠第一个或我的paintComponent()根本不会执行。

问题图像(重叠)

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

}

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

4

1 回答 1

1

我在网上搜索过,据说有很多方法可以在开始新绘图之前清除 jPanel

是的,不要做你正在做的事情。永远不需要paintComponent手动调用,你不应该调用getGraphics,除了能够返回之外null,这不是自定义绘画的方式。

绘制应该只绘制组件的当前状态。因此,如果您想“清除”面板,请清除它用来决定应该绘制什么以及如何绘制的状态。

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

首先看一下在 AWT 和 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);是个坏主意,你没有任何理由paint直接调用任何方法。绘制系统会告诉您它何时需要绘制您的组件以及它想要使用的上下文。

接着...

Graph graphExecute = new Graph();

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

……等等,什么!?你创建,我假设是一个组件Graph,你给它播种一些信息,然后你手动绘制它......

好的,假设它是JComponent某种类型的,为什么不将它添加到当前 UI

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);
}    
于 2018-08-07T05:32:51.513 回答