Java Swing-AncestorListener:Don';切换制表符时不点火?
我使用下面的代码让我的组件在分别添加/删除事件监听器时注册/取消注册事件监听器Java Swing-AncestorListener:Don';切换制表符时不点火?,java,swing,jtabbedpane,ancestor,Java,Swing,Jtabbedpane,Ancestor,我使用下面的代码让我的组件在分别添加/删除事件监听器时注册/取消注册事件监听器 addAncestorListener(new AncestorListener() { @Override public void ancestorRemoved(AncestorEvent event) { log.info("========= Remove listeners by " + ContentViewingComponent.this);
addAncestorListener(new AncestorListener() {
@Override public void ancestorRemoved(AncestorEvent event) {
log.info("========= Remove listeners by " + ContentViewingComponent.this);
...
}
@Override public void ancestorMoved(AncestorEvent event) {}
@Override public void ancestorAdded(AncestorEvent event) {
log.info("========= Add listeners by " + ContentViewingComponent.this);
...
}
});
我的意图是,在大多数情况下,这两个事件(添加和删除)基本上都会触发一次,即创建和添加组件时,以及删除和忘记组件时
但是,当该组件所在的选项卡(JTabbedPane)被选中/隐藏时,它们也会被激发。有没有办法规避/检测这种情况
也许是JTabbedPane
的一个版本,它使用显示/隐藏而不是添加/删除?更新:更多的调查显示该组件实际上没有被删除,但是选项卡是隐藏的,ancestorRemoved()。我可以检测组件是否仍有根*并忽略事件(如果有),但问题是,当组件实际被删除时(不可见时),不会再次触发该事件
*好吧,这还有待观察。它似乎在实际删除之前触发了antestorremoved()
,因此我无法沿着getParent()
链查找组件是否有根。更新:通过一步后使用SwingUtilities.invokeLater()
检查来修复
(对于那些熟悉Flash/AS3的人,我正在寻找一种类似于添加到\u STAGE
/从\u STAGE
事件中删除\u的Swing。)
我的意图是两个事件(添加和删除)基本上都会触发
在大多数情况下,即创建和添加组件时
当它被移除和遗忘时
有AncestorListener、ComponentListener和HierarchyListener,它们可以是异步的,与使用SwingUtilities从这些事件或祖先获取组件的方式相同
比如说
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTabbedPane;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
public class MyTabbedPane {
private JTabbedPane tabbedPane = new JTabbedPane();
private JFrame f = new JFrame();
private JLabel label1 = new JLabel("Tab1");
private JLabel label2 = new JLabel("Tab2");
private JLabel label3 = new JLabel("Tab3");
private JLabel label4 = new JLabel("Tab4");
public MyTabbedPane() {
tabbedPane.addTab("Tab1", label1);
tabbedPane.addTab("Tab2", label2);
tabbedPane.addTab("Tab3", label3);
tabbedPane.addTab("Tab4", label4);
tabbedPane.setTabPlacement(JTabbedPane.TOP);
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
label1.addAncestorListener(new EventHandler());
label2.addAncestorListener(new EventHandler());
label3.addAncestorListener(new EventHandler());
label4.addAncestorListener(new EventHandler());
label1.addHierarchyListener(new EventHandler());
label2.addHierarchyListener(new EventHandler());
label3.addHierarchyListener(new EventHandler());
label4.addAncestorListener(new EventHandler());
label1.addComponentListener(new EventHandler());
label2.addComponentListener(new EventHandler());
label3.addComponentListener(new EventHandler());
label4.addComponentListener(new EventHandler());
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(tabbedPane, BorderLayout.CENTER);
f.setPreferredSize(new Dimension(600, 400));
f.pack();
f.setVisible(true);
}
class EventHandler implements AncestorListener, ComponentListener, HierarchyListener {
@Override
public void ancestorAdded(AncestorEvent event) {
System.out.println("CardlayoutTest.EventHandler.ancestorAdded()");
}
@Override
public void ancestorMoved(AncestorEvent event) {
System.out.println("CardlayoutTest.EventHandler.ancestorMoved()");
}
@Override
public void ancestorRemoved(AncestorEvent event) {
System.out.println("CardlayoutTest.EventHandler.ancestorRemoved()");
}
@Override
public void hierarchyChanged(HierarchyEvent e) {
System.out.println("Components Change: " + e.getChanged());
if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0) {
if (e.getComponent().isDisplayable()) {
System.out.println("Components DISPLAYABILITY_CHANGED : " + e.getChanged());
} else {
System.out.println("Components DISPLAYABILITY_CHANGED : " + e.getChanged());
}
}
if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
if (e.getComponent().isDisplayable()) {
System.out.println("Components SHOWING_CHANGED : " + e.getChanged());
} else {
System.out.println("Components SHOWING_CHANGED : " + e.getChanged());
}
}
}
@Override
public void componentHidden(ComponentEvent e) {
System.out.println(e.getComponent().getClass().getName() + " --- Hidden");
}
@Override
public void componentMoved(ComponentEvent e) {
System.out.println(e.getComponent().getClass().getName() + " --- Moved");
}
@Override
public void componentResized(ComponentEvent e) {
System.out.println(e.getComponent().getClass().getName() + " --- Resized ");
}
@Override
public void componentShown(ComponentEvent e) {
System.out.println(e.getComponent().getClass().getName() + " --- Shown");
}
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
MyTabbedPane frame = new MyTabbedPane();
}
});
}
}
通过使用分层侦听器修复
public static void addDisplayableListeners(final Component comp, final Runnable onDisplayable, final Runnable onNotDisplayable) {
comp.addHierarchyListener(new HierarchyListener() {
@Override public void hierarchyChanged(HierarchyEvent e) {
System.out.println("HIERARCHY CHANGE ===== " + comp);
final boolean dc = (e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0;
if (dc) {
System.out.println("DISPLAYABILITY_CHANGED");
if (comp.isDisplayable()) {
onDisplayable.run();
} else {
onNotDisplayable.run();
}
}
}
});
}
旧版本:
addHierarchyListener(new HierarchyListener() {
private boolean hadRoot = false;
@Override public void hierarchyChanged(HierarchyEvent e) {
System.out.println("HIERARCHY CHANGE ===== " + ContentViewingComponent.this);
final boolean hasRoot = Swing.hasRoot(ContentViewingComponent.this);
System.out.println("Has root: " + hasRoot);
if (hasRoot != hadRoot) {
System.out.println("...which is not what was.");
hadRoot = hasRoot;
if (hasRoot) {
log.info("========= Add listeners by " + ContentViewingComponent.this);
...
} else {
log.info("========= Remove listeners by " + ContentViewingComponent.this);
...
}
}
}
});
注意:我会看看是否可以用@mKorbel的答案中提到的官方方法替换我自己的助手(hadRoot
和hasRoot()
)。但是,您可以在侦听器中使用if语句,仅为您想要的事件执行代码。@GilbertLeBlanc是的,但有一个问题。我可以忽略一个仅表示“不可见”的事件,但如果该组件随后被移除(虽然不可见),它不会让我知道。与此同时,我“修复”了它(请参见我自己的答案),但我也可以从这个答案中加入一些元素。