2013-03-06 138 views
1

以下示例允許窗口顯示,隱藏,處置和關閉(通過發送事件)。當窗口打開?如何知道窗口在沒有監聽窗口事件的情況下打開?

示例顯示,該窗口僅打開一次 - 第一組可見。即使窗戶被丟棄,然後再次顯示,它也不會經歷「開放」事件。

爲什麼?

如何知道是否在不編寫處理程序並跟蹤此事件的情況下打開窗口?

如何關閉窗口,使其在設置可見時再次發生打開事件?即如何將窗口對象返回到初始狀態?

是否有任何其他狀態或事件可以具有所需的屬性?

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

回答

1

您可以使用此

查找活動窗口(不論是一幀或一個對話框),你可以用下面的遞歸方法的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

2

如何將窗口對象返回初始狀態?

如果你想返回變量和組件到初始狀態,那麼我認爲你需要重新創建窗口。

如何關閉窗口,使其在設置可見時再次發生打開事件?

你可以自己做類似跟蹤窗口的關閉/打開:

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