Java Graphics不会在连续的函数调用中显示,为什么?

时间:2010-05-01 07:25:37

标签: java user-interface swing graphics

我正在为BST实施进行可视化(我前几天发布了另一个关于它的问题)。我创建了一个显示查看区域和按钮的GUI。我已经向BST实现添加了代码以递归遍历树,该函数接收坐标以及最初由主GUI类传入的Graphics对象。我的想法是,我只是让这个函数在每次更新(添加,删除等等)之后重新绘制树,首先在所有内容上绘制一个矩形以“刷新”查看区域。这也意味着我可以改变BST实现(即通过添加平衡操作),它不会影响可视化。

我遇到的问题是绘图功能仅在第一次调用时才起作用,之后它不会显示任何内容。我想我并不完全理解Graphics对象是如何工作的,因为它不会像我从不同函数传递/调用时那样预期。我知道getGraphics函数与它有关。

相关代码:

    private void draw(){
    Graphics g = vPanel.getGraphics();      
    tree.drawTree(g,ORIGIN,ORIGIN);
}

vPanel是我正在使用的

private void drawTree(Graphics g, BinaryNode<AnyType> n, int x, int y){
    if( n != null ){
        drawTree(g, n.left, x-10,y+10 );
            if(n.selected){
                g.setColor(Color.blue);
            }
            else{
                g.setColor(Color.gray);
            }        
            g.fillOval(x,y,20,20);
            g.setColor(Color.black);
            g.drawString(n.element.toString(),x,y);
        drawTree(g,n.right, x+10,y+10);
    }
}

当公共函数调用它时,它会传递给根节点。我必须要:

Graphics g = vPanel.getGraphics();

...在drawTree函数中?这没有意义!!

感谢您的帮助。

2 个答案:

答案 0 :(得分:4)

这不是正确的做法。如果您想要一个显示树的组件,您应该创建自己的JComponent并覆盖paintComponent - 方法。

每当模型(树/当前节点等)发生变化时,您都会调用redraw(),这将触发paintComponent

我实际上不认为你可以从Graphics方法的参数以外的任何地方获取paintComponent对象。

试用以下程序

import java.awt.Graphics;

public class FrameTest {

    public static void main(String[] args) {
        final JFrame f = new JFrame("Frame Test");
        f.setContentPane(new MyTreeComponent());
        f.setSize(400, 400);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);

        new Thread() {
            public void run() {
                for (int i = 0; i < 10; i++) {
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    f.repaint();
                }
            }
        }.start();
    }
}

class MyTreeComponent extends JComponent {
    public void paintComponent(Graphics g) {
        // Draw your tree. (Using random here to visualize the updates.)
        g.drawLine(30, 30, 50, 30 + new Random().nextInt(20));
        g.drawLine(30, 30, 50, 30 - new Random().nextInt(20));
    }
}

最佳起点可能是http://java.sun.com/docs/books/tutorial/uiswing/painting/index.html

答案 1 :(得分:2)

@ aioobe的方法是合理的,这个例子很有说服力。除了引用的教程Performing Custom Painting之外,我还要补充一点,绘图应该在Event Dispatch Thread (EDT)上进行。在下面的变体中,请注意如何使用EventQueue.invokeLater构建GUI。同样,actionPerformed()的{​​{1}}方法会在EDT上调用javax.swing.Timer来显示最近添加的节点。可以找到更详细的示例here

repaint()