Java Swing中点击按钮后图形需最小化恢复JFrame才显示的问题
解决点击按钮后JPanel图形不立即显示的问题
嘿,这个问题我之前也碰到过!你现在的情况是:点击按钮后,对应的图形元素不会立刻在窗口里显示,非得把JFrame最小化再恢复才出来。这其实是Swing绘图机制的一个常见坑——当你修改了控制图形显示的状态变量(比如nodeA、nodeB这些)之后,没有主动触发组件的重绘操作,所以界面不会自动刷新。
先说说你代码里的两个小问题:
- 监听器重复添加:你把所有按钮的
ActionListener都写在了paintComponent方法里,而paintComponent会被频繁调用(比如窗口刷新、大小变化时),这就导致每次重绘都会给按钮重复添加监听器,完全没必要,还可能引发奇怪的问题。 - 没有主动触发重绘:每次点击按钮修改完状态变量后,你没有通知Swing去重新绘制界面,所以只有当窗口最小化恢复(系统自动触发重绘请求)时,图形才会显示出来。
修改方案
我们只需要做两件事:
- 把所有按钮的监听器移到构造方法里初始化,避免重复添加
- 在每个监听器的
actionPerformed方法末尾,调用repaint()触发重绘
下面是修改后的完整代码:
package tutorial; import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class Tutorial extends JPanel{ JButton b1,b2,b3,b4,b5; boolean nodeA, nodeB,communicate, key, acknowledge = false; public Tutorial(){ b1 = new JButton("Node A"); add(b1); b2 = new JButton("Node B"); add(b2); b3 = new JButton("Communicate"); add(b3); b4 = new JButton("send key"); add(b4); b5 = new JButton("Request B"); add(b5); // 把所有监听器移到构造方法里初始化 b1.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { nodeA = true; repaint(); // 触发重绘,更新界面 } }); b2.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { nodeB = true; repaint(); // 触发重绘 } }); b3.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { if(nodeA == true && nodeB == true) communicate = true; repaint(); // 触发重绘 } }); b4.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { if(communicate == true) key = true; repaint(); // 触发重绘 } }); b5.addActionListener(new ActionListener(){ @Override public void actionPerformed(ActionEvent e) { if(key == true) acknowledge = true; repaint(); // 触发重绘 } }); } public void paintComponent(Graphics g){ super.paintComponent(g); g.setColor(Color.black); g.fillRect(300, 100,100, 50); g.setColor(Color.red); g.drawString("KDC/KMC",320,130); if(nodeA == true){ g.setColor(Color.green); g.fillOval(100, 300, 70, 70); g.setColor(Color.red); g.drawString("Node A", 113, 340); g.drawString("Node A added",150,220); g.drawLine(150, 300, 300, 150); } if(nodeB == true){ g.setColor(Color.green); g.fillOval(530, 300, 70, 70); g.setColor(Color.red); g.drawString("Node B",545,340); g.drawString("Node B added",473,220); g.drawLine(550, 300, 400, 150); } if(communicate == true){ g.drawString("A requests for B's Session Key", 230,260); g.drawLine(165, 310, 325, 150); } if(key == true){ g.drawString("A's key is 4",210,175); g.drawString("B's key is 5",430,175); } if(acknowledge == true){ g.drawLine(170,325,530,325); g.drawString("A sends part of session key to B", 260, 320); g.drawLine(170,350,530,350); g.drawString("if sessiion key match then B sent Acknowledgement", 215, 365); } } public static void main(String[] args) { Tutorial t = new Tutorial(); JFrame jf = new JFrame("Assignment"); jf.setSize(1200,900); jf.add(t); jf.setVisible(true); jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }
为什么这样修改有效?
Swing的绘图是被动触发的:只有在组件第一次显示、窗口大小改变,或者你主动调用repaint()方法时,Swing才会调用paintComponent方法来更新界面。之前你修改了状态变量,但没告诉Swing要重绘,所以界面一直停留在旧状态;而窗口最小化再恢复时,系统会自动发送重绘请求,这时候新的状态才会被绘制出来。现在每次修改状态后调用repaint(),就能让界面立刻更新啦!
内容的提问来源于stack exchange,提问作者Shery
相关产品推荐
相关产品推荐

