Java 重新绘制方法不起作用
我正在尝试通过从文本字段插入其元素来创建一个AVL树,然后按draw按钮来绘制树。我的问题是,当我将随机元素存储在主目录树中并运行程序时,绘制方法工作正常,树绘制在框架上,但当我使用文本字段插入元素并调用actionPerformed方法中的repaint方法绘制按钮时,它不会绘制任何内容。 有人能帮我知道draw按钮的actionPerformed方法有什么问题,以及为什么repaint方法没有响应 这是我的第一个包含所有组件的面板Java 重新绘制方法不起作用,java,swing,graphics,awt,Java,Swing,Graphics,Awt,我正在尝试通过从文本字段插入其元素来创建一个AVL树,然后按draw按钮来绘制树。我的问题是,当我将随机元素存储在主目录树中并运行程序时,绘制方法工作正常,树绘制在框架上,但当我使用文本字段插入元素并调用actionPerformed方法中的repaint方法绘制按钮时,它不会绘制任何内容。 有人能帮我知道draw按钮的actionPerformed方法有什么问题,以及为什么repaint方法没有响应 这是我的第一个包含所有组件的面板 public class PanelComponents e
public class PanelComponents extends JPanel {
private JButton insertB;
private JButton drawB;
private JTextField insertTF;
private AvlTree<Integer> avl = new AvlTree<Integer>();// use AVL tree class
private TreeCanvas treeCanvas;
public PanelComponents() {
setPreferredSize(new Dimension(780, 500));
insertB = new JButton("insert");
drawB = new JButton("draw");
insertTF = new JTextField(7);
createTreeCanvas();
insertB.addActionListener(new ActionListener() {
// here is the event handler
public void actionPerformed(ActionEvent e) {
int number = Integer.parseInt(insertTF.getText());
avl.insert(number);
}
});
drawB.addActionListener(new ActionListener() {
// here is the event handler
public void actionPerformed(ActionEvent e) {
if (avl.isEmpty()) return;
treeCanvas.setRoot(avl.getRoot());
treeCanvas.repaint();
}
});
add(insertTF);
add(insertB);
add(drawB);
}
private TreeCanvas createTreeCanvas() {
if (treeCanvas == null) {
treeCanvas = new TreeCanvas();
treeCanvas.setBounds(5,5,680,230);
add(treeCanvas);
}
return treeCanvas;
}
}
这是演示课
public class TreeDemo {
public TreeDemo(){
/**
* when I use this way of inserting the tree painted
*/
// AvlTree<Integer> t = new AvlTree<Integer>();
// t.insert (new Integer(2));
// t.insert (new Integer(1));
// t.insert (new Integer(4));
// t.insert (new Integer(5));
// t.insert (new Integer(9));
// t.insert (new Integer(3));
// t.insert (new Integer(6));
// t.insert (new Integer(7));
// TreeCanvas b =new TreeCanvas();
// b.setRoot(t.getRoot());
JFrame frame = new JFrame("AVL Tree");
PanelComponents panel = new PanelComponents();
// frame.add(b);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(1000, 700);
}
public static void main (String[] args){
new TreeDemo();
}}
该类用于在面板上绘制树,效果良好。你不需要经历它
public class TreeCanvas extends JPanel {
private static final int NODE_WIDTH = 30;
private static final int ROW_GAP = 10;
private AvlNode<Integer> root;
public TreeCanvas() {
root = null;
}
interface RenderNode {
public void draw(Graphics g, AvlNode<Integer> parent, Point parentLoc,
AvlNode<Integer> child, Point childLoc);
}
public void paint(Graphics g) {
super.paint(g);
int startX = getWidth() / 2;
int startY = ROW_GAP + (NODE_WIDTH / 2);
render(g, null, null, root, new Point(startX, startY), getWidth() / 2,
new RenderNode() {public void draw(Graphics g, AvlNode<Integer>
parent, Point parentLoc, AvlNode<Integer> child, Point childLoc) {
if (parent != null) {
g.setColor(Color.black);
g.drawLine(parentLoc.x, parentLoc.y, childLoc.x,childLoc.y);
}
}
});
render(g, null, null, root, new Point(startX, startY), getWidth() / 2,
new RenderNode() {
public void draw(Graphics g, AvlNode<Integer>parent,
point parentLoc, AvlNode<Integer> child, Point childLoc) {
child.draw(g, childLoc);
}
});
}
private void render(Graphics g, AvlNode<Integer> parent, Point parentLoc,
AvlNode<Integer> child, Point childLoc, int spacing, RenderNode
callback) {
if (child == null)
return;
callback.draw(g, parent, parentLoc, child, childLoc);
int nextY = childLoc.y + (ROW_GAP + NODE_WIDTH);
render(g, child, childLoc, child.getLeft(), new Point(childLoc.x
- (spacing / 2), nextY), spacing / 2, callback);
render(g, child, childLoc, child.getRight(), new Point(childLoc.x
+ (spacing / 2), nextY), spacing / 2, callback);
}
public void setRoot(AvlNode<Integer> root){
this.root = root;
}
}
所有JPanel在重新喷漆之前都需要重新验证,否则一切都不会改变 重新验证将面板标记为已更改,以便考虑重新喷漆 下面是实现这一点的代码:
treeCanvas.revalidate(); //revalidate first.
treeCanvas.repaint(); //then repaint.
它们必须重新验证,因为它们在第一次喷漆后就被标记为有效,重新验证后会将其标记为无效,以便重新喷漆
我的问题是,当我将随机元素存储在主目录树中并运行程序时,绘制方法工作正常,树绘制在框架上
我不知道代码是怎么工作的。你所做的就是:
TreeCanvas b =new TreeCanvas();
b.setRoot(t.getRoot());
这样就创建了一个面板,但我看不到在哪里将面板添加到框架中
不管怎样,我想说你的问题是布局经理。您创建的所有类都扩展了默认使用FlowLayout的JPanel。在某些代码中,您只需将组件添加到面板中,这样布局管理器就会根据组件的首选大小确定组件的大小/位置
问题是您的TreePanel类的首选大小为0,因此没有任何可绘制的内容。您需要重写类的getPreferredSize方法以返回面板的大小,这样布局管理器才能正常工作。不要试图在代码中使用setBounds。布局管理器将忽略该代码
解决布局问题后,所有其他建议仍然有效:
替代绘制组件而不是绘制
在更新树后调用重新验证并重新绘制
不要在自定义绘画中使用绘画,请使用paintComponent。谢谢,我使用了paintComponent,但仍然存在相同的问题。您的渲染代码令人困惑,难以理解。但乍一看,您真的想要if父级吗!=无效的{一旦添加了TreeCanvas并因此已经有了父级,请检查?我的建议是添加简单的system.out.println语句,或使用调试器,以验证方法是否按照您期望的顺序被调用。如果是这样,则代码中存在逻辑错误。实际上,当我使用此代码时,我只是在该状态中放置了b而不是panelnt jframe.addpanel;我非常感谢您的帮助,我重写了getPreferredSize方法,现在它可以正常工作了。谢谢。@user3600270,实际上,当我使用此代码时,我只放了b而不是panel-我们会发布您使用的实际代码,所以我们不需要猜测您在做什么。我重写了getPreferredSize方法,现在它可以正常工作了,那么您应该接受答案,让人们知道问题已经解决。谢谢你的评论