Java JPanel在线程中绘制组件

Java JPanel在线程中绘制组件,java,multithreading,swing,jpanel,Java,Multithreading,Swing,Jpanel,我在网上找到了一个画二叉树的好代码。我为它创建了二叉搜索树算法,现在如果我传递函数的根节点,它就会绘制出我的树。我想让它一步一步地画,在线程中运行它,并在插入元素后使它休眠。现在的问题是,我想,JPanel本身在绘图完成之前不会被返回,因此即使它运行在不同的线程上,也不会被添加到我的拆分窗格中(我已经实现了许多排序算法,并且已经在绘制,所有算法都可以从同一个选项卡式窗格访问。每个选项卡式窗格都包含一个拆分窗格,每个拆分窗格都包含控制按钮和一个jpanel,我在其中绘制算法,但其他算法不从jpan

我在网上找到了一个画二叉树的好代码。我为它创建了二叉搜索树算法,现在如果我传递函数的根节点,它就会绘制出我的树。我想让它一步一步地画,在线程中运行它,并在插入元素后使它休眠。现在的问题是,我想,JPanel本身在绘图完成之前不会被返回,因此即使它运行在不同的线程上,也不会被添加到我的拆分窗格中(我已经实现了许多排序算法,并且已经在绘制,所有算法都可以从同一个选项卡式窗格访问。每个选项卡式窗格都包含一个拆分窗格,每个拆分窗格都包含控制按钮和一个jpanel,我在其中绘制算法,但其他算法不从jpanel扩展!).你能帮我找到一种方法,在一个与主程序完全不同的线程中运行它,并能看到它是如何绘制树的吗

请不要在这个代码上评判我,我只是快速地把它组合起来,试图让它工作,这不是我编码的方式

public class BinaryTree extends JPanel implements Runnable {

private int radius = 20;
private int vGap = 45, hGap = 150;
private int x = 350, y = 25;
private GraphNode root;
private BinarySearchTreeSort binaryTreeSort;
private int latency = 270;
private boolean isManual = false;

//Stores the sorting algorithm's instance
public BinaryTree(BinarySearchTreeSort binaryTreeSort) {
    this.binaryTreeSort = binaryTreeSort;
}

@Override
public void run() {
//Maybe i should put here the paintComponent somehow???
    root = binaryTreeSort.binaryTreeSort();
}

@Override
public void paintComponent(final Graphics g) {
    displayTree(g, root, x, y, hGap);
}

private void displayTree(Graphics g, GraphNode root, int x, int y, int hGap) {
    // Display the root  
    while (!isStarted) {
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            Logger.getLogger(BinaryTreeFrame.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    g.drawOval(x - radius, y - radius, 2 * radius, 2 * radius);

    if (root.getValue() != 0) {
        g.drawString(root.getValue() + "", x - 13, y + 4);

    }

    sleep();

    if (root.getLeftChild() != null) {
        // Draw a line to the left node  
        g.setColor(Color.black);
        leftChild(g, x - hGap, y + vGap, x, y);
        //Draw the left subtree   
        displayTree(g, root.getLeftChild(), x - hGap, y + vGap, hGap / 2);
    }

    if (root.getRightChild() != null) {
        // Draw a line to the right node  
        g.setColor(Color.black);
        rightChild(g, x + hGap, y + vGap, x, y);
        // Draw the right subtree recursively  
        displayTree(g, root.getRightChild(), x + hGap, y + vGap, hGap / 2);
    }

}

/* Draw left child */
private void leftChild(Graphics g, int x1, int y1, int x2, int y2) {
    double d = Math.sqrt(vGap * vGap + (x2 - x1) * (x2 - x1));
    int x11 = (int) (x1 + radius * (x2 - x1) / d);
    int y11 = (int) (y1 - radius * vGap / d);
    int x21 = (int) (x2 - radius * (x2 - x1) / d);
    int y21 = (int) (y2 + radius * vGap / d);
    g.drawLine(x11, y11, x21, y21);

    //g.drawString("0", ((x21 + x11) - 20) / 2, (y21 + y11) / 2);
}

/*Draw right child */
private void rightChild(Graphics g, int x1, int y1, int x2, int y2) {
    double d = Math.sqrt(vGap * vGap + (x2 - x1) * (x2 - x1));
    int x11 = (int) (x1 - radius * (x1 - x2) / d);
    int y11 = (int) (y1 - radius * vGap / d);
    int x21 = (int) (x2 + radius * (x1 - x2) / d);
    int y21 = (int) (y2 + radius * vGap / d);
    g.drawLine(x11, y11, x21, y21);

    //g.drawString("1", (x21 + x11) / 2, (y21 + y11) / 2);
}

public void sleep() {
    if (!isManual) {
        try {
            Thread.sleep(latency);
        } catch (InterruptedException ex) {
            Logger.getLogger(BinaryTree.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

这种想法对于Java>1.4是错误的,有一种方法可以测试isEventDisp…,在false上立即绘制在true Repait上(int,x,x)仅限片段,重新创建1)阅读。2) 在自定义绘制之前调用super.paintComponent()。3) 似乎您需要使用
SwingWorker
ExecutorService
进行后台工作,而不阻塞
EDT
进行重新喷漆。永远不要在EDT上睡觉(尤其是在喷漆周期内)!相反,使用一些逻辑将节点取消/标记为“可见”(或树状态的某些其他属性),然后在每个步骤后调用repaint——大声思考(如在头脑风暴会议中),也许您可以创建树,但不能绘制它。然后绘制一棵新树,只包含根文件夹。然后逐个将子文件夹/文件添加到此树,并在每次“添加”后重新绘制和休眠。因此,你使用第一棵树来运行,并在第一棵树的基础上一步一步地创建新的树。谢谢你的回答,我回家后会试试。