更改了其中一个侦听器适合可见性的 JPanel
Posted
技术标签:
【中文标题】更改了其中一个侦听器适合可见性的 JPanel【英文标题】:JPanel which one of Listeners is proper for visibility is changed 【发布时间】:2012-06-08 11:14:30 【问题描述】:AncestorListener
、ComponentListener
或 HierarchyListener
是否有一些规则或好/坏体验?
其中一个比其他的更好或更安全吗?我特别想知道JPanel
/ JComponent
何时以及如何隐藏。
注意以下代码包含不正确的 Swing 规则,例如在这种情况下使用 Thread.sleep(int)
,以允许我在 Swing GUI 中打印出正确的 Listeners
顺序
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;
public class CardlayoutTest extends JFrame
private static final long serialVersionUID = 1L;
public CardLayout card = new CardLayout();
public CardlayoutTest()
JPanel pnlA = new JPanel(new BorderLayout());
pnlA.add(new JButton("A"), BorderLayout.CENTER);
JPanel pnlB = new JPanel(new BorderLayout());
pnlB.add(new JButton("B"), BorderLayout.CENTER);
JPanel pnlC = new JPanel(new BorderLayout());
pnlC.add(new JButton("C"), BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(card);
add(pnlA, "A");
add(pnlB, "B");
add(pnlC, "C");
pnlA.addAncestorListener(new EventHandler());
pnlB.addAncestorListener(new EventHandler());
pnlC.addAncestorListener(new EventHandler());
pnlA.addHierarchyListener(new EventHandler());
pnlB.addHierarchyListener(new EventHandler());
pnlB.addHierarchyListener(new EventHandler());
pnlA.addComponentListener(new EventHandler());
pnlB.addComponentListener(new EventHandler());
pnlB.addComponentListener(new EventHandler());
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());
public void componentHidden(ComponentEvent e)
System.out.println(e.getComponent().getClass().getName() + " --- Hidden");
public void componentMoved(ComponentEvent e)
System.out.println(e.getComponent().getClass().getName() + " --- Moved");
public void componentResized(ComponentEvent e)
System.out.println(e.getComponent().getClass().getName() + " --- Resized ");
public void componentShown(ComponentEvent e)
System.out.println(e.getComponent().getClass().getName() + " --- Shown");
public static void main(String[] args)
CardlayoutTest t = new CardlayoutTest();
t.setSize(500, 500);
System.out.println("CardlayoutTest.main()------------------------ FIRST");
t.card.show(t.getContentPane(), "A");
t.setVisible(true);
System.out.print("\n");
try
Thread.sleep(2000);
catch (InterruptedException e)
System.out.println("CardlayoutTest.main()------------------------ SECOND");
t.card.show(t.getContentPane(), "B");
System.out.print("\n");
try
Thread.sleep(2000);
catch (InterruptedException e)
System.out.println("CardlayoutTest.main()------------------------ THIRD");
t.card.show(t.getContentPane(), "C");
System.out.print("\n");
【问题讨论】:
【参考方案1】:如果您想准确了解可见性变化 - 使用 ComponentListener
或 ComponentAdapter
:
JPanel panel = new JPanel ();
panel.addComponentListener ( new ComponentAdapter ()
public void componentShown ( ComponentEvent e )
System.out.println ( "Component shown" );
public void componentHidden ( ComponentEvent e )
System.out.println ( "Component hidden" );
);
但这种可见性可能不是您所想的。 isVisible()
标志将是 true
,即使 Component
未添加到任何 Container
并且因此根本不显示!
可见性 a 的目的略有不同。您可以使用它手动隐藏已添加并显示在应用程序某处的Component
。在这种情况下,(如果您使用setVisible(false)
)它将被隐藏,并且该Component
中的每个ComponentListener
都会被告知该更改。
所以,谈论实际可见性...
这是您应该用来聆听实际组件出现/消失的内容:
JPanel panel = new JPanel ();
panel.addAncestorListener ( new AncestorListener ()
public void ancestorAdded ( AncestorEvent event )
// Component added somewhere
public void ancestorRemoved ( AncestorEvent event )
// Component removed from container
public void ancestorMoved ( AncestorEvent event )
// Component container moved
);
我总是使用该侦听器来确定何时将Component
添加到某处,并在移动/移除它时进行侦听。
此外,您可以随时通过调用isShowing()
方法检查Component
是否对应用程序用户真正可见:
boolean userCanSeeThePanel = panel.isShowing();
仅当该面板添加到对用户框架的可见性并且isVisible()
标志也为真时,这将返回true
(通常为true
,除非您将其设置为false
)。
关于可见性,我想这就是我能告诉你的全部内容了。我可能误解了你的问题。如果我在这种情况下错了,请纠正我。
【讨论】:
@mKorbel 如果您仍然不了解可见性的某些部分,请随时询问更多信息。这实际上是 Swing 的一个非常棘手的部分 当已经可见的 JComponent 被(更改为)隐藏时,我很感兴趣地捕捉适当的事件 如果更改是通过“setVisible(false)”方法进行的 - 使用 ComponentListener 或 ComponentAdapter。在“componentHidden”中,当组件隐藏时(调用“setVisible(false)”)和在“componentShown”中显示(调用“setVisible(true)”)时,您将收到通知 直到这一刻一切都清楚了,正如我的 SSCCE 所展示的那样,所有三个 Listener 都触发了预期的事件, 那么,有什么问题呢?您正在为适当的事件使用适当的侦听器......我想在这种情况下没有什么可说的了。还是您发现了其他问题?以上是关于更改了其中一个侦听器适合可见性的 JPanel的主要内容,如果未能解决你的问题,请参考以下文章
OnItemClick 侦听器和单击的 View 项的可见性