当窗口打开?如何知道窗口在没有监听窗口事件的情况下打开?

问题描述:

以下示例允许窗口显示,隐藏,处置和关闭(通过发送事件)。当窗口打开?如何知道窗口在没有监听窗口事件的情况下打开?

示例显示,该窗口仅打开一次 - 第一组可见。即使窗户被丢弃,然后再次显示,它也不会经历“开放”事件。

为什么?

如何知道是否在不编写处理程序并跟踪此事件的情况下打开窗口?

如何关闭窗口,使其在设置可见时再次发生打开事件?即如何将窗口对象返回到初始状态?

是否有任何其他状态或事件可以具有所需的属性?

import java.awt.BorderLayout; 
import java.awt.EventQueue; 
import java.awt.FlowLayout; 
import java.awt.Toolkit; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 

import javax.swing.AbstractAction; 
import javax.swing.AbstractListModel; 
import javax.swing.ComboBoxModel; 
import javax.swing.JButton; 
import javax.swing.JComboBox; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.event.ListDataListener; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class Tester_JFrame_Closing_01 { 

    private static Logger log = LoggerFactory.getLogger(Tester_JFrame_Closing_01.class); 

    protected static Toolkit toolkit = Toolkit.getDefaultToolkit(); 
    protected static EventQueue eventQueue = toolkit.getSystemEventQueue(); 

    public static enum CloseOperation { 

     DO_NOTHING_ON_CLOSE(JFrame.DO_NOTHING_ON_CLOSE), 
     HIDE_ON_CLOSE(JFrame.HIDE_ON_CLOSE), 
     DISPOSE_ON_CLOSE(JFrame.DISPOSE_ON_CLOSE), 
     EXIT_ON_CLOSE(JFrame.EXIT_ON_CLOSE) 
     ; 

     public static ComboBoxModel newModel() { 

      return new ComboBoxModel() { 
       private CloseOperation selected = HIDE_ON_CLOSE; 

       @SuppressWarnings("serial") 
       private final AbstractListModel core = new AbstractListModel() { 

        @Override 
        public int getSize() { 
         return values().length; 
        } 

        @Override 
        public Object getElementAt(int index) { 
         return values()[index]; 
        } 

       }; 

       @Override 
       public int getSize() { 
        return core.getSize(); 
       } 

       @Override 
       public Object getElementAt(int index) { 
        return core.getElementAt(index); 
       } 

       @Override 
       public void addListDataListener(ListDataListener l) { 
        core.addListDataListener(l); 
       } 

       @Override 
       public void removeListDataListener(ListDataListener l) { 
        core.removeListDataListener(l); 
       } 

       @Override 
       public void setSelectedItem(Object anItem) { 
        selected = (CloseOperation) anItem; 
       } 

       @Override 
       public Object getSelectedItem() { 
        return selected; 
       } 

      }; 

     } 


     public final int Value; 

     private CloseOperation(int value) { 
      this.Value = value; 
     } 

     @Override 
     public String toString() { 
      switch(this) { 
      case DISPOSE_ON_CLOSE: 
       return "DISPOSE_ON_CLOSE"; 
      case HIDE_ON_CLOSE: 
       return "HIDE_ON_CLOSE"; 
      case DO_NOTHING_ON_CLOSE: 
       return "DO_NOTHING_ON_CLOSE"; 
      case EXIT_ON_CLOSE: 
       return "EXIT_ON_CLOSE"; 
      default: 
       return "<UNKNOWN>"; 
      } 
     } 
    } 

    public static void main(String[] args) { 

     WindowAdapter windowAdapter = new WindowAdapter() { 
      @Override 
      public void windowClosed(WindowEvent e) { 
       log.debug("windowClosed"); 
      } 

      @Override 
      public void windowClosing(WindowEvent e) { 
       log.debug("windowClosing"); 
      } 

      @Override 
      public void windowOpened(WindowEvent e) { 
       log.debug("windowOpened"); 
      } 

     }; 

     final JFrame frame = new JFrame("Controlled window"); 
     frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); 
     frame.addWindowListener(windowAdapter); 

     final WindowEvent closeEvent = new WindowEvent(frame, WindowEvent.WINDOW_CLOSING); 

     @SuppressWarnings("serial") 
     AbstractAction closeAction = new AbstractAction("close") { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       eventQueue.postEvent(closeEvent); 
      } 
     }; 

     @SuppressWarnings("serial") 
     AbstractAction hideAction = new AbstractAction("hide") { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       frame.setVisible(false); 
      } 
     }; 

     @SuppressWarnings("serial") 
     AbstractAction showAction = new AbstractAction("show") { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       frame.setVisible(true); 
      } 
     }; 

     @SuppressWarnings("serial") 
     AbstractAction disposeAction = new AbstractAction("dispose") { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       frame.dispose(); 
      } 
     }; 

     JButton closeButton = new JButton(closeAction); 
     JButton hideButton = new JButton(hideAction); 
     JButton showButton = new JButton(showAction); 
     JButton disposeButton = new JButton(disposeAction); 

     ComboBoxModel closeOperationModel = CloseOperation.newModel(); 

     final JComboBox closeOperationCombo = new JComboBox(closeOperationModel); 
     closeOperationCombo.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       log.debug("closeOperationCombo.actionPerformed({})", e); 
       frame.setDefaultCloseOperation(((CloseOperation)closeOperationCombo.getSelectedItem()).Value); 
      } 
     }); 

     JPanel buttonPanel = new JPanel(); 
     buttonPanel.setLayout(new FlowLayout()); 

     buttonPanel.add(showButton); 
     buttonPanel.add(hideButton); 
     buttonPanel.add(disposeButton); 
     buttonPanel.add(closeButton); 
     buttonPanel.add(closeOperationCombo); 

     JFrame controlFrame = new JFrame("Controller window"); 
     controlFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     controlFrame.setLayout(new FlowLayout()); 
     controlFrame.add(buttonPanel, BorderLayout.SOUTH); 
     controlFrame.pack(); 
     controlFrame.setLocation(100, 100); 
     controlFrame.setVisible(true); 

     frame.setBounds(100, 100 + controlFrame.getHeight(), controlFrame.getWidth(), 480); 

    } 
} 

INCREDIBLE

他们有一个字段中指定Window.state他们甚至不初始化(因此它是零),那么他们测试它在show()方法一次并将其设置为1,如果它是0。这是唯一的地方state被使用,这里windowOpened被解雇。没有任何代码将state返回到0任何地方。而且,他们在Frame子类中放弃了这个state变量,并用新名称覆盖它,并且新名称按住了一些新的状态,包括图标化和类似,并忘记了已打开的位!凉!

+0

'eventQueue.postEvent(closeEvent);'为什么? – MadProgrammer 2013-03-06 23:40:59

+0

@MadProgrammer,而不是直接调用'setVisible(false)'或'dispose()',这就像用户点击框架的关闭按钮。然后将执行默认关闭操作。 – camickr 2013-03-07 04:13:21

+0

@camickr好吧,我还是抓我头:P – MadProgrammer 2013-03-07 04:45:29

您可以使用此

查找活动窗口(不论是一帧或一个对话框),你可以用下面的递归方法的Java Swing应用程序:

Window getSelectedWindow(Window[] windows) { 
    Window result = null; 
    for (int i = 0; i < windows.length; i++) { 
     Window window = windows[i]; 
     if (window.isActive()) { 
      result = window; 
     } else { 
      Window[] ownedWindows = window.getOwnedWindows(); 
      if (ownedWindows != null) { 
       result = getSelectedWindow(ownedWindows); 
      } 
     } 
    } 
    return result; 
} 

参考这篇文章 Get current active window's title in Java

+0

我可能在这里错过了一些东西,但是这与这个问题有什么关系? – MadProgrammer 2013-03-06 23:49:26

+0

他说,他想知道什么窗口是活动的,而不使用事件处理程序。这将返回活动窗口。 – 2013-03-06 23:51:49

+1

嗯,这是一个小边界线,但我想我可以忍受那个;) – MadProgrammer 2013-03-06 23:53:02

如何将窗口对象返回初始状态?

如果你想返回变量和组件到初始状态,那么我认为你需要重新创建窗口。

如何关闭窗口,使其在设置可见时再次发生打开事件?

你可以自己做类似跟踪窗口的关闭/打开:

WindowAdapter windowAdapter = new WindowAdapter() 
    { 
     boolean closed = false; 

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

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

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

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

      if (closed) 
       windowOpened(e); 

     } 
    }; 

为了“关闭”按钮来工作,你也会需要使用:

frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
+0

通过处理'windowActivated'并从其中调用'windowOpened',你正在使用坏技巧。这并不意味着subsytem会称之为。问题是关于子系统:它为什么要多次关闭并打开一次? – 2013-03-07 13:57:32

+0

P.S. 'setDefaultCloseOperation'方法只是通过在窗口角中按十字按钮来定义当用户“关闭”窗口时发生的事情。 – 2013-03-07 14:17:39

+0

这就是它的设计方式,因为我建议我不认为你可以对此做任何事情。是的,当您点击窗口的关闭按钮时,setDefaultCloseOperation()适用。如果将其保留在“隐藏”位置,那么windowClosed事件将永远不会被触发。我也相信,无论您单击“关闭”菜单项还是“关闭”按钮,逻辑应该与用户单击窗口上的“关闭”按钮相同,这就是为什么您应该适当地设置默认关闭操作。查看我的“关闭应用程序”链接,对您的问题发表评论。 – camickr 2013-03-07 16:38:16