简体   繁体   English

单击按钮后,Swing自动重绘JPanel

[英]Swing auto repaints JPanel after button clicked

I'm having this weird issue with Swing. 我在Swing中遇到这个奇怪的问题。 I am drawing few points and lines between them, directly on JPanel. 我直接在JPanel上绘制它们之间的一些点和线。 I'm just calling: 我只是在打电话:

g.drawLine(pointAX, pointAY, pointBX, pointBY);

Where g is Graphics object taken from panel.getGraphics() 其中g是来自panel.getGraphics() Graphics对象

And this works alright, gives me nice output. 这样就可以了,给了我很好的输出。 But then I'm trying to move it and I use ActionListener on my button, which does: 但是然后我尝试移动它,并在按钮上使用了ActionListener ,它可以:

    panel.revalidate();
    panel.repaint();
    drawPanel();
    moveVector(moveX, moveY);

    drawPoints();
    drawConnections(connections);

The other methods: drawPanel just draws some lines, so it's easier to see: 其他方法: drawPanel仅绘制一些线,因此更容易看到:

private void drawPanel(){
    Graphics g = panel.getGraphics();
    zeroX = panel.getWidth() / 2;
    zeroY = panel.getHeight() / 2;

    g.setColor(Color.GRAY);

    for(int i = zeroX + 10; i < panel.getWidth(); i += 10){
        g.drawLine(i, 0, i, panel.getHeight());
    }

    for(int i = zeroX + 10; i > 0; i -= 10){
        g.drawLine(i, 0, i, panel.getHeight());
    }

    for(int j = zeroY - 10; j < panel.getHeight(); j += 10){
        g.drawLine(0, j, panel.getWidth(), j);
    }

    for(int j = zeroY - 10; j > 0; j -= 10){
        g.drawLine(0, j, panel.getWidth(), j);
    }

    g.setColor(Color.BLACK);
    g.drawLine(zeroX, 0, zeroX, panel.getHeight());
    g.drawLine(0, zeroY, panel.getWidth(), zeroY);

    panel.paintComponents(g);
}

drawPoints looks like this drawPoints看起来像这样

private void drawPoints() {
    for(int i = 0; i < points.size(); i++){
        int x = Integer.parseInt(points.get(i)[1]);
        int y = Integer.parseInt(points.get(i)[2]);
        drawPoint(x, y);
    }
}

private void drawPoint(int x, int y) {
    Graphics g = panel.getGraphics();

    for (int i = -1; i < 2; i++) {
        g.drawLine(zeroX + x + i, zeroY + y - 1, zeroX + x + i, zeroY + y);
    }

    panel.paintComponents(g);
}

    g.setColor(Color.BLACK);
    g.drawLine(zeroX, 0, zeroX, panel.getHeight());
    g.drawLine(0, zeroY, panel.getWidth(), zeroY);

    panel.paintComponents(g);
}

and drawConnections : drawConnections

private void drawConnections(ArrayList<String[]> lines) {
    for (String[] arr : lines) {
        String x = arr[1];
        String y = arr[2];

        drawConnection(x, y);
    }
}

private void drawConnection(String pointA, String pointB) {
    int pointAX = 0, pointAY = 0, pointBX = 0, pointBY = 0;
    Graphics g = panel.getGraphics();

    for (String[] arr : points) {
        if (arr[0].equals(pointA)) {
            pointAX = Integer.parseInt(arr[1]);
            pointAY = Integer.parseInt(arr[2]);
        } else if (arr[0].equals(pointB)) {
            pointBX = Integer.parseInt(arr[1]);
            pointBY = Integer.parseInt(arr[2]);
        }
    }

    g.drawLine(zeroX + pointAX, zeroY + pointAY, zeroX + pointBX, zeroY + pointBY);
    panel.paintComponents(g);
}

What I don't understand here is that everything looks OK. 我在这里不明白的是,一切看起来都还不错。 I did debug and it looks ok and at the end of listener call, when everything is painted (although it paints over the old one instead of clearing it) it suddenly clears everything and nothing is visible at all. 我进行了调试,看起来一切正常,在侦听器调用结束时,所有内容绘制完毕(尽管它覆盖了旧的而不是清除了旧的内容),但它突然清除了所有内容,并且什么都看不到。

You need to implement all the drawing in paintComponent(Graphics) in your JPanel class (or methods that are called from it). 您需要在JPanel类(或从中调用的方法paintComponent(Graphics)中实现所有paintComponent(Graphics) Calling getGraphics on the panel instance and using the Graphics object is not always guaranteed to work. 并非总是保证可以在面板实例上调用getGraphics并使用Graphics对象。 It's also strange that you call panel.repaint() and immediately afterwards try to do additional drawing using the graphics object from the panel, that additional drawing should just be done in paintComponent(Graphics) . 同样奇怪的是,您调用panel.repaint()并随后立即尝试使用面板中的图形对象进行其他绘制,该其他绘制应仅在paintComponent(Graphics)

Using paintComponent(Graphics) will ensure your painting is done at the right time, and that the panel's graphics will be cleared (if you call the super method at least). 使用paintComponent(Graphics)将确保您的绘画在正确的时间完成,并且将清除面板的图形(如果至少调用了super方法)。

panel.repaint does not immediately repaint the panel, but it tells Swing that this panel should be repainted in the near future (see API docs: https://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#repaint(long,%20int,%20int,%20int,%20int) . So your custom painting will be cleared once the panel repaints itself. panel.repaint不会立即重新绘制面板,但它告诉Swing该面板应在不久的将来重新绘制(请参阅API文档: https : //docs.oracle.com/javase/7/docs/api/javax/swing /JComponent.html#repaint(long,%20int,%20int,%20int,%20int) ,因此一旦面板重新绘制自身,您的自定义绘制将被清除。

Create a custom component by inheriting from JPanel and overwriting the method paintComponent with your custom painting code. 通过从JPanel继承并使用自定义绘画代码覆盖方法paintComponent来创建自定义组件。 Then, whenever the panel needs to be repainted, your code is called, and not only the user pressed a button. 然后,只要需要重新粉刷面板,就会调用您的代码,而不仅是用户按下了按钮。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM