Java GUI编程问题:控件添加顺序不同导致按钮闪烁显示异常
问题原因
- 违反Swing单线程模型:Swing是单线程设计,所有组件的创建、属性修改、窗口显示操作都必须在事件调度线程(EDT)中执行,直接在main主线程中操作Swing组件会引发不可预期的渲染异常,包括闪烁、界面绘制不全等问题。
- 布局管理器使用错误:JFrame的内容窗格默认使用
BorderLayout,调用无参add()方法添加组件时,所有组件都会被默认添加到BorderLayout.CENTER区域,该区域同一时间只会应用最后一个添加组件的布局规则。如果要使用setBounds()手动指定组件位置,必须先调用setLayout(null)禁用默认布局管理器,否则手动设置的坐标、尺寸会被布局管理器自动覆盖。 - 窗口显示时机错误:你在所有组件添加、属性配置完成之前就调用了
setVisible(true)显示窗口,后续修改组件属性、添加组件会触发频繁的增量重绘,不同组件的重绘顺序冲突就会出现闪烁现象。 - 组件Z轴层级影响:禁用布局管理器后,同一容器内组件的Z轴显示层级由添加顺序决定,后添加的组件层级更高,会覆盖先添加的同位置组件。先添加JLabel再添加按钮、复选框时,按钮悬停触发的重绘会和底层组件的重绘请求冲突,进而出现闪烁;最后添加JLabel时,JLabel位置和按钮不重叠,不会干扰按钮重绘,因此显示正常。
修正后代码
package javaapplication13; import java.awt.*; import javax.swing.*; public class JavaApplication13 { public static void main(String[] args) { // 所有Swing操作放到EDT中执行 SwingUtilities.invokeLater(() -> { ButtonFrame bf = new ButtonFrame(); }); } } class ButtonFrame extends JFrame { public ButtonFrame() { JButton b1 = new JButton("1. Dugme"); JButton b2 = new JButton("2. Dugme"); JLabel l1 = new JLabel(); JCheckBox c1 = new JCheckBox("Prvo dugme"); JCheckBox c2 = new JCheckBox("Drugo dugme"); setTitle("Dugme"); setSize(400,400); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 禁用默认布局管理器,setBounds才会生效 setLayout(null); b1.setBounds(20, 30, 90, 20); b2.setBounds(20,70,90,20); l1.setBounds(70,120,90,20); c1.setBounds(120,30,120,20); c2.setBounds(120,70,120,20); l1.setText(""); // 添加组件 this.add(b1); this.add(b2); this.add(c1); this.add(c2); this.add(l1); // 所有配置完成后再显示窗口 setVisible(true); } }
内容的提问来源于stack exchange,提问作者narutouzumaki 99
相关产品推荐
相关产品推荐

