如何获知控件可见状态变化?父控件影响下子控件无事件问题咨询
SWT控件随父控件可见性变化时的事件监听问题
问题原因
SWT中SWT.Show和SWT.Hide事件仅在控件自身被调用setVisible()方法时才会触发。当父控件的可见性改变时,子控件的实际可见状态(通过isVisible()获取)会同步变化,但不会自动触发子控件的Show/Hide事件,这就是你代码中无法获取Button的Show/Hide事件的核心原因。
解决方案
方法1:父控件事件中手动触发子控件事件
在父控件的Show/Hide监听逻辑里,手动调用子控件的notifyListeners()方法发送对应事件,直接关联父控件状态变化与子控件事件:
Display display = Display.getDefault(); Shell shell = new Shell(display); shell.setSize(400, 600); shell.setLayout(new FillLayout(SWT.VERTICAL)); Composite composite = new Composite(shell, SWT.NONE); composite.setLayout(new FillLayout()); Button test = new Button(composite, SWT.NONE); test.setText("test"); composite.addListener(SWT.Show, e -> { System.out.println("Composite Show"); // 手动给子Button发送Show事件 test.notifyListeners(SWT.Show, new Event()); }); composite.addListener(SWT.Hide, e -> { System.out.println("Composite Hide"); // 手动给子Button发送Hide事件 test.notifyListeners(SWT.Hide, new Event()); }); test.addListener(SWT.Show, e -> System.out.println("Button Show")); test.addListener(SWT.Hide, e -> System.out.println("Button Hide")); Button btn = new Button(shell, SWT.TOGGLE); btn.setText("Show / Hide"); btn.addListener(SWT.Selection, e -> { composite.setVisible(btn.getSelection()); System.out.println(test.isVisible()); }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } }
方法2:递归触发所有子控件事件(适合多层嵌套场景)
如果控件存在多层嵌套结构,可以写一个递归工具方法,遍历父控件下所有子控件并触发对应事件,无需逐个手动关联:
Display display = Display.getDefault(); Shell shell = new Shell(display); shell.setSize(400, 600); shell.setLayout(new FillLayout(SWT.VERTICAL)); Composite composite = new Composite(shell, SWT.NONE); composite.setLayout(new FillLayout()); Button test = new Button(composite, SWT.NONE); test.setText("test"); // 递归触发控件及其所有子控件的可见性事件 private static void fireVisibilityEvent(Control control, int eventType) { control.notifyListeners(eventType, new Event()); if (control instanceof Composite) { for (Control child : ((Composite) control).getChildren()) { fireVisibilityEvent(child, eventType); } } } composite.addListener(SWT.Show, e -> { System.out.println("Composite Show"); fireVisibilityEvent(composite, SWT.Show); }); composite.addListener(SWT.Hide, e -> { System.out.println("Composite Hide"); fireVisibilityEvent(composite, SWT.Hide); }); test.addListener(SWT.Show, e -> System.out.println("Button Show")); test.addListener(SWT.Hide, e -> System.out.println("Button Hide")); Button btn = new Button(shell, SWT.TOGGLE); btn.setText("Show / Hide"); btn.addListener(SWT.Selection, e -> { composite.setVisible(btn.getSelection()); System.out.println(test.isVisible()); }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } }
补充说明
如果不需要严格依赖SWT的Show/Hide事件,也可以通过监听父控件的可见性变化,结合子控件的isVisible()方法判断状态后处理逻辑,但手动触发事件的方式更贴合SWT的事件驱动设计模式。
内容的提问来源于stack exchange,提问作者Bourbon_7
相关产品推荐
相关产品推荐

