Java JPanel在线程中绘制组件
我在网上找到了一个画二叉树的好代码。我为它创建了二叉搜索树算法,现在如果我传递函数的根节点,它就会绘制出我的树。我想让它一步一步地画,在线程中运行它,并在插入元素后使它休眠。现在的问题是,我想,JPanel本身在绘图完成之前不会被返回,因此即使它运行在不同的线程上,也不会被添加到我的拆分窗格中(我已经实现了许多排序算法,并且已经在绘制,所有算法都可以从同一个选项卡式窗格访问。每个选项卡式窗格都包含一个拆分窗格,每个拆分窗格都包含控制按钮和一个jpanel,我在其中绘制算法,但其他算法不从jpanel扩展!).你能帮我找到一种方法,在一个与主程序完全不同的线程中运行它,并能看到它是如何绘制树的吗 请不要在这个代码上评判我,我只是快速地把它组合起来,试图让它工作,这不是我编码的方式Java JPanel在线程中绘制组件,java,multithreading,swing,jpanel,Java,Multithreading,Swing,Jpanel,我在网上找到了一个画二叉树的好代码。我为它创建了二叉搜索树算法,现在如果我传递函数的根节点,它就会绘制出我的树。我想让它一步一步地画,在线程中运行它,并在插入元素后使它休眠。现在的问题是,我想,JPanel本身在绘图完成之前不会被返回,因此即使它运行在不同的线程上,也不会被添加到我的拆分窗格中(我已经实现了许多排序算法,并且已经在绘制,所有算法都可以从同一个选项卡式窗格访问。每个选项卡式窗格都包含一个拆分窗格,每个拆分窗格都包含控制按钮和一个jpanel,我在其中绘制算法,但其他算法不从jpan
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——大声思考(如在头脑风暴会议中),也许您可以创建树,但不能绘制它。然后绘制一棵新树,只包含根文件夹。然后逐个将子文件夹/文件添加到此树,并在每次“添加”后重新绘制和休眠。因此,你使用第一棵树来运行,并在第一棵树的基础上一步一步地创建新的树。谢谢你的回答,我回家后会试试。