【问题标题】:How to listen for "visible" property of Window in Swing/AWT?如何在 Swing/AWT 中监听 Window 的“可见”属性?
【发布时间】:2014-03-28 12:37:16
【问题描述】:

有一个bean属性“visible”,在类Window中用getter isVisible()和setter setVisible()表示。

如何监听这个值?

我想用带有绑定库的复选框来实现流行的“查看”菜单。不幸的是,我看不到如何绑定窗口的“可见”属性。即使我不会写翻译器,因为我看不到任何预定义的方式来监听这个属性:

package tests;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowStateListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

    public class Try_Swing2 {

        public static void main(String[] args) {

            SwingUtilities.invokeLater(new Runnable() {

                @Override
                public void run() {


                    final JFrame frame2 = new JFrame();
                    frame2.addWindowStateListener(new WindowStateListener() {

                        @Override
                        public void windowStateChanged(WindowEvent e) {

                            System.out.println("windowState.newState = " + e.getNewState());


                        }
                    });

                    frame2.addWindowListener(new WindowListener() {

                        @Override
                        public void windowOpened(WindowEvent e) {
                            System.out.println("windowOpened");
                        }

                        @Override
                        public void windowIconified(WindowEvent e) {
                            System.out.println("windowIconified");

                        }

                        @Override
                        public void windowDeiconified(WindowEvent e) {
                            System.out.println("windowDeiconified");

                        }

                        @Override
                        public void windowDeactivated(WindowEvent e) {
                            System.out.println("windowDeactivated");
                        }

                        @Override
                        public void windowClosing(WindowEvent e) {
                            System.out.println("windowClosing");
                        }

                        @Override
                        public void windowClosed(WindowEvent e) {
                            System.out.println("windowClosed");
                        }

                        @Override
                        public void windowActivated(WindowEvent e) {
                            System.out.println("windowActivated");
                        }
                    });

                    frame2.addPropertyChangeListener("visible", new PropertyChangeListener() {

                        @Override
                        public void propertyChange(PropertyChangeEvent evt) {
                            System.out.println("visible = " + evt.getNewValue());
                        }
                    });

                    frame2.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);

                    frame2.setTitle("This window is controlled by another window");

                    frame2.setSize(800, 600);
                    frame2.setLocationRelativeTo(null);
                    frame2.setVisible(true);

                    AbstractAction toggleAction = new AbstractAction("Toggle another window visibility") {

                        @Override
                        public void actionPerformed(ActionEvent e) {
                            frame2.setVisible( !frame2.isVisible() );
                        }

                    };


                    JButton toggleButton = new JButton(toggleAction);

                    JFrame frame1 = new JFrame();

                    frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                    frame1.setTitle("This windows controls");
                    frame1.setLayout(new FlowLayout());
                    frame1.add(toggleButton);


                    frame1.pack();
                    frame1.setLocation(0, 0);
                    frame1.setVisible(true);




                }
            });

        }
    }

【问题讨论】:

  • bean 属性“可见” 不,它不是 bean 属性。您需要一个适配器来监听 windowEvents 并将它们映射到一个 bean 属性,然后将您的客户端绑定到该适配器
  • 您可以使用ComponentListener 并覆盖componentShowncomponentHidden。本质上是相似的

标签: java swing awt windowstate


【解决方案1】:

Component.addPropertyChangeListenermethod documentation 清楚地列出了正在观察的属性。可见性状态未列出。由于JFrame(或其超类之一直到Component)不会添加任何新行为,因此您无法观察到JFrame 上可见性状态的变化。

但是,您可以通过覆盖 setVisible 方法来继承 JFrame。在这个新实现中,您可以触发这样的属性更改:

public class VisibleAwareFrame extends JFrame {
    public void setVisible(boolean b) {
        boolean visible = isVisible();
        super.setVisible(b);
        firePropertyChange("visible", visible, b);
    }
}

【讨论】:

  • 子类化是次优的 - 如果框架没有完全在绑定代码的控制之下,将无济于事。相反,使用一个适配器(这是我今天的标语;-),它将 windowEvents 映射到适当的 bean 属性。此外,触发是不正确的,因为在调用 super 之后您不知道新可见是否真的是 b - 作为一般规则,触发时始终查询新属性
  • 你整天都在说什么适配器?为什么要保密?
  • @Seelenvirtuose 这会对鼠标按十字起反应吗?
  • @kleopatra 你完全正确。我想到了一个快速的解决方案。 SuzanCioc:他讲述了一个添加到 JFrame 的 WindowAdapter,它的方法将被窗口系统调用。这样的方法调用会告诉你发生了什么。
  • visible 属性不是Window 类的一部分,而是Component class 的一部分。因此,要使用的正确侦听器是具有componentShown 方法的ComponentListener。请参阅下面的答案。
【解决方案2】:

visible 属性并没有真正绑定到 WindowsListener,而是绑定到 ComponentListener,因为它属于 Component 类,而不是 Window 类。

为了监听visible 属性的变化,需要实现ComponentListenercomponentShown(ComponentEvent e) 方法。从适配器继承总是更容易,所以在这种情况下:

frame2.addComponentListener(new ComponentAdapter() {

    @Override
    public void componentShown(WindowEvent e) {
        System.out.println("Component is Visible");
    }

}

适配器具有侦听器的空实现,例如ComponentAdapter 类在 ComponentListenerWindowAdapter 中具有来自 WindowListener 的方法的空实现。

更多详情请见Component AdapterComponent ListenerHow to Write a Component Listener

【讨论】:

    【解决方案3】:

    试试Global AWT Event Listener

    long eventMask = AWTEvent.COMPONENT_EVENT_MASK;
    
    Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
        public void eventDispatched(AWTEvent e) {
            String paramString = e.paramString();
            System.out.println(paramString);
        }
    }, eventMask);
    

    这是一些输出

    COMPONENT_RESIZED (0,0 500x500)
    COMPONENT_HIDDEN
    COMPONENT_RESIZED (0,0 500x500)
    COMPONENT_RESIZED (0,0 500x500)
    COMPONENT_RESIZED (4,23 492x473)
    COMPONENT_MOVED (4,23 492x473)
    COMPONENT_RESIZED (0,0 492x473)
    COMPONENT_RESIZED (0,0 500x500)
    COMPONENT_MOVED (0,0 500x500)
    COMPONENT_SHOWN
    COMPONENT_MOVED (0,0 500x500)
    COMPONENT_MOVED (0,0 500x500)
    COMPONENT_RESIZED (0,0 500x500)
    COMPONENT_HIDDEN
    COMPONENT_RESIZED (0,0 494x475)
    COMPONENT_MOVED (0,0 494x475)
    

    您可以在paramString 上检查来源和事件类型。检查COMPONENT_HIDDENCOMPONENT_SHOWN 事件并根据事件更改或设置visible 属性。 它可能会帮助你。

    【讨论】:

      猜你喜欢
      • 2019-09-29
      • 1970-01-01
      • 1970-01-01
      • 2021-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-20
      • 1970-01-01
      相关资源
      最近更新 更多