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

时间:2014-11-12 20:19:47

标签: java swing

我遇到了Swing这个奇怪的问题。 我在它们之间绘制了几个点和线,直接在JPanel上。 我只是打电话:

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

其中g是来自Graphics

panel.getGraphics()对象

这项工作正常,给我很好的输出。 但后来我试图移动它并在我的按钮上使用ActionListener,这样做:

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

    drawPoints();
    drawConnections(connections);

其他方法: 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看起来像这样

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

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

我不明白的是,一切看起来都不错。我做了调试,它看起来没问题,在听众调用结束时,当所有内容都被绘制时(尽管它描绘了旧的而不是清除它),它突然清除了所有内容,根本没有任何内容可见。

2 个答案:

答案 0 :(得分:1)

您需要在paintComponent(Graphics)类(或从中调用的方法)JPanel中实现所有绘图。在面板实例上调用getGraphics并使用Graphics对象并不总能保证有效。你调用panel.repaint()然后立即尝试使用面板中的图形对象进行额外绘制也很奇怪,只需在paintComponent(Graphics)中完成附加绘图。

使用paintComponent(Graphics)将确保您的绘画在合适的时间完成,并且面板的图形将被清除(如果您至少调用超级方法)。

答案 1 :(得分:0)

panel.repaint没有立即重新绘制该面板,但它告诉Swing该面板应该在不久的将来重新绘制(请参阅API文档:https://docs.oracle.com/javase/7/docs/api/javax/swing/JComponent.html#repaint(long,%20int,%20int,%20int,%20int)。因此,一旦面板,您的自定义绘图将被清除重新粉刷自己。

通过继承JPanel并使用自定义绘制代码覆盖方法paintComponent来创建自定义组件。然后,每当需要重新绘制面板时,都会调用您的代码,而不仅仅是用户按下按钮。