Swing/ModalInternalFrame のバックアップソース(No.15)
- バックアップ一覧
- 差分 を表示
- 現在との差分 を表示
- 現在との差分 - Visual を表示
- バックアップ を表示
- Swing/ModalInternalFrame へ行く。
- 1 (2008-01-25 (金) 23:38:26)
- 2 (2008-01-29 (火) 21:34:57)
- 3 (2008-03-12 (水) 19:36:45)
- 4 (2008-03-14 (金) 21:44:03)
- 5 (2008-04-15 (火) 17:15:50)
- 6 (2008-04-25 (金) 19:33:36)
- 7 (2008-04-25 (金) 20:51:49)
- 8 (2008-05-14 (水) 13:45:47)
- 9 (2008-11-10 (月) 20:32:17)
- 10 (2011-04-20 (水) 18:41:16)
- 11 (2012-03-24 (土) 16:18:24)
- 12 (2013-01-30 (水) 23:42:27)
- 13 (2013-04-06 (土) 05:06:50)
- 14 (2013-05-09 (木) 11:37:00)
- 15 (2013-05-09 (木) 12:37:40)
- 16 (2013-05-26 (日) 05:34:28)
- 17 (2013-05-26 (日) 06:50:22)
- 18 (2013-07-26 (金) 01:38:05)
- 19 (2013-09-06 (金) 11:39:25)
- 20 (2013-09-21 (土) 20:44:23)
- 21 (2014-11-26 (水) 18:40:24)
- 22 (2014-11-28 (金) 16:29:51)
- 23 (2015-01-03 (土) 06:24:11)
- 24 (2015-03-24 (火) 21:23:15)
- 25 (2015-05-20 (水) 17:58:03)
- 26 (2015-12-08 (火) 15:15:47)
- 27 (2016-01-28 (木) 13:06:44)
- 28 (2016-09-02 (金) 12:34:08)
- 29 (2017-03-28 (火) 19:41:02)
- 30 (2017-03-29 (水) 13:52:49)
- 31 (2017-04-04 (火) 14:17:08)
- 32 (2017-06-07 (水) 15:35:06)
- 33 (2017-11-02 (木) 15:32:16)
- 34 (2018-02-09 (金) 19:19:55)
- 35 (2018-02-24 (土) 19:51:30)
- 36 (2018-02-27 (火) 14:23:21)
- 37 (2018-07-30 (月) 16:15:22)
- 38 (2019-05-28 (火) 20:30:42)
- 39 (2019-05-28 (火) 23:01:52)
- 40 (2021-02-18 (木) 06:58:08)
- 41 (2022-08-20 (土) 22:15:25)
- 42 (2024-02-03 (土) 13:51:56)
TITLE:JInternalFrameをModalにする #navi(../) #tags(JInternalFrame, GlassPane, Mnemonic, JDesktopPane, JToolTip, JLayeredPane) RIGHT:Posted by &author(aterai); at 2007-10-15 *JInternalFrameをModalにする [#le7c13f6] ``JInternalFrame``を``Modal``にして、他の``JInternalFrame``などを操作できないようにブロックします。 -&jnlp; -&jar; -&zip; //#screenshot #ref(http://lh6.ggpht.com/_9Z4BYR88imo/TQTP9wW-lJI/AAAAAAAAAe0/xQ9vJrX3MuQ/s800/ModalInternalFrame.png) **サンプルコード [#d9d01b15] #code(link){{ //menuItem.setMnemonic(KeyEvent.VK_1); class ModalInternalFrameAction1 extends AbstractAction { public ModalInternalFrameAction1(String label) { super(label); } @Override public void actionPerformed(ActionEvent e) { setJMenuEnabled(false); JOptionPane.showInternalMessageDialog( desktop, "information", "modal1", JOptionPane.INFORMATION_MESSAGE); setJMenuEnabled(true); } } }} #code{{ //menuItem.setMnemonic(KeyEvent.VK_2); class ModalInternalFrameAction2 extends AbstractAction { private final JPanel glass = new MyGlassPane(); public ModalInternalFrameAction2(String label) { super(label); Rectangle screen = frame.getGraphicsConfiguration().getBounds(); glass.setBorder(BorderFactory.createEmptyBorder()); glass.setLocation(0,0); glass.setSize(screen.width, screen.height); glass.setOpaque(false); glass.setVisible(false); desktop.add(glass, JLayeredPane.MODAL_LAYER); } @Override public void actionPerformed(ActionEvent e) { setJMenuEnabled(false); glass.setVisible(true); JOptionPane.showInternalMessageDialog( desktop, "information", "modal2", JOptionPane.INFORMATION_MESSAGE); glass.setVisible(false); setJMenuEnabled(true); } } }} #code{{ //menuItem.setMnemonic(KeyEvent.VK_3); //Creating Modal Internal Frames -- Approach 1 and Approach 2 //http://java.sun.com/developer/JDCTechTips/2001/tt1220.html class ModalInternalFrameAction3 extends AbstractAction { private final Component orgGlassPane; private final JPanel glass = new PrintGlassPane(); public ModalInternalFrameAction3(String label) { super(label); orgGlassPane = frame.getGlassPane(); glass.setVisible(false); } @Override public void actionPerformed(ActionEvent e) { JOptionPane optionPane = new JOptionPane(); optionPane.setMessage("Hello, World"); optionPane.setMessageType(JOptionPane.INFORMATION_MESSAGE); JInternalFrame modal = optionPane.createInternalFrame(desktop, "modal3"); removeSystemMenuListener(modal); modal.addInternalFrameListener(new InternalFrameAdapter() { @Override public void internalFrameClosed(InternalFrameEvent e) { glass.setVisible(false); frame.setGlassPane(orgGlassPane); } }); glass.add(modal); //Rectangle screen = desktop.getBounds(); //modal.setLocation(screen.x + screen.width/2 - modal.getSize().width/2, // screen.y + screen.height/2 - modal.getSize().height/2); frame.setGlassPane(glass); glass.setVisible(true); modal.setVisible(true); try{ modal.setSelected(true); }catch(java.beans.PropertyVetoException ex) {} } } }} **解説 [#v497998b] -``Alt+1``: ``JOptionPane.showInternalMessageDialog``メソッドを使用して、簡単なメッセージを表示する``Modal``な``Dialog``を``JDeskTopPane``内に表示 -- ``JButton``のマウスクリックは無効になるが、``Mnemonic``が無効にならない --- ``Alt+B``でボタンを押すことが出来てしまう --- ``Mnemonic``を設定したコンポーネントは``setEnabled(false)``とする必要がある -- ``Mnemonic``を``JMenu``に設定していると``setEnabled(false)``としても、``Alt``キーに反応する --- これは``WindowsLookAndFeel``だけ? --- この``InternalMessageDialog``を表示している間は、``JMenuBar``をダミーと入れ替えて無効化 -- この``InternalMessageDialog``を閉じない限り、アプリケーションを``Alt+F4``などで閉じることは出来ない -- ``InternalMessageDialog``のシステムメニュー(左上のアイコンをクリックすると表示される)がマウスで操作不可能 -- ``JTooltip``は正常 --- ``showInternalMessageDialog(...)``メソッド内で、``pane.putClientProperty(PopupFactory_FORCE_HEAVYWEIGHT_POPUP, Boolean.TRUE)``(``JDK 1.6.0``の場合の``Key``は、``PopupFactory.forceHeavyWeightPopupKey``) されているため、``JComboBox``などのドロップダウンメニューも正常 -``Alt+2``: ``Alt+1``と同様に``JOptionPane.showInternalMessageDialog``メソッドを使用し、かつ半透明な``GlassPane``を``JLayeredPane.MODAL_LAYER``に追加 -- 動作、制限などは、``Alt+1``の``InternalMessageDialog``と同じ -- ``JDeskTop``内にマスクが掛かる -``Alt+3``: ``JFrame``に半透明な``GlassPane``を追加し、そこに``JInternalFrame``を追加することで``Modal``に設定 -- ``JFrame``内全体(``JMenuBar``なども含む)にマスクが掛かる -- ``InternalMessageDialog``のシステムメニューが自身のレイヤーより奥に表示されるため、アイコン(``JLabel``)をクリックしても反応しないようにリスナーを除去 -- ``JComboBox``を``InternalMessageDialog``に追加すると、そのドロップダウンメニューが裏に表示される -- この``InternalMessageDialog``を開いていても、アプリケーションを``Alt+F4``などで閉じることが出来てしまう ---- - ``Alt+3``の方法で、``InternalOptionDialog``に``JComboBox``を追加する場合、ドロップダウンメニューを正しく表示させるには、リフレクションを使って``ClientProperty``を設定するしかない? -- ``JInternalFrame#putClientProperty(PopupFactory_FORCE_HEAVYWEIGHT_POPUP, Boolean.TRUE)``とすれば、システムメニューも正常に表示されるが、``JOptionPane.showInternalXXXDialog``では、なぜか``JOptionPane``に設定するようになっている(``JInternalFrame``は使い回ししているから?) #code{{ JInternalFrame modal = optionPane.createInternalFrame(desktop, "modal3"); JComboBox combo = new JComboBox(new String[] {"Banana", "Apple", "Pear", "Grape"}); combo.setEditable(true); try{ Field field; if(System.getProperty("java.version").startsWith("1.6.0")) { Class clazz = Class.forName("javax.swing.PopupFactory"); field = clazz.getDeclaredField("forceHeavyWeightPopupKey"); }else{ //1.7.0, 1.8.0 Class clazz = Class.forName("javax.swing.ClientPropertyKey"); field = clazz.getDeclaredField("PopupFactory_FORCE_HEAVYWEIGHT_POPUP"); } field.setAccessible(true); modal.putClientProperty(field.get(null), Boolean.TRUE); }catch(Exception ex) { ex.printStackTrace(); } optionPane.setMessage(combo); optionPane.setMessageType(JOptionPane.QUESTION_MESSAGE); }} ---- [http://weblogs.java.net/blog/alexfromsun/archive/2008/01/ Alexander Potochkin's Blog: Disabling Swing Containers, the final solution?]を参考に(``paint``ではなく、``print``が使用されている)して、``GlassPane``を以下のように修正すると、上記のサンプルの``Alt+3``(``Alt+2``の場合は、描画が乱れる)は、``Mnemonic``もうまくブロックできるようです。 - ``JFrame``のメニューバーの``Mnemonic``もブロックできる - ``JFrame``のシステムメニューはブロックできない - モーダルにした``JInternalFrame``のシステムメニューは表示されない -- ただし表示されないだけで、クリックしてからカーソル移動やダブルクリックなどが動いてしまう - モーダルにした``JInternalFrame``の右上の閉じるボタンの``JToolTip``が``JDesktopPane``内で表示される場合、空白になる %%``JDK 6``では``JToolTip``は表示されない%% #code{{ class PrintGlassPane extends JPanel { TexturePaint texture = TextureFactory.createCheckerTexture(4); public PrintGlassPane() { super((LayoutManager)null); setOpaque(false); } @Override public void setVisible(boolean isVisible) { boolean oldVisible = isVisible(); super.setVisible(isVisible); JRootPane rootPane = SwingUtilities.getRootPane(this); if(rootPane!=null && isVisible()!=oldVisible) { rootPane.getLayeredPane().setVisible(!isVisible); } } @Override public void paintComponent(Graphics g) { JRootPane rootPane = SwingUtilities.getRootPane(this); if(rootPane!=null) { //http://weblogs.java.net/blog/alexfromsun/archive/2008/01/ // it is important to call print() instead of paint() here // because print() doesn't affect the frame's double buffer rootPane.getLayeredPane().print(g); } Graphics2D g2 = (Graphics2D) g; g2.setPaint(texture); g2.fillRect(0,0,getWidth(),getHeight()); } } }} ---- ``JDK 6``の場合、[http://tips4java.wordpress.com/2008/11/07/disabled-glass-pane/ Disabled Glass Pane « Java Tips Weblog]のようにキー入力を無効にするキーリスナーを追加する方法もあります。 この方法は、``JDK 5``などの場合、``WindowsLookAndFeel``で、``Alt``キーを押すとメニューバーにフォーカスが移ることがあります。 **参考リンク [#n6c5a455] -[http://java.sun.com/developer/JDCTechTips/2001/tt1220.html Creating Modal Internal Frames -- Approach 1 and Approach 2] -[http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html How to Use Root Panes] -[http://weblogs.java.net/blog/alexfromsun/archive/2008/01/ Disabling Swing Containers, the final solution?] --[[Cursorを砂時計に変更>Swing/WaitCursor]] **コメント [#h8218ae6] - %%[[JInternalFrameを半透明にする>Swing/TransparentFrame]]と、同様に``GlassPane``が``Ubuntu``(``GNOME``)などで半透明にならない場合があります。%% -- [[aterai]] &new{2007-10-15 (月) 13:16:07}; -- ``Alt+2``で開いた場合、``JInternalFrame``に``GlassPane``を乗せるのではなく、直接``JDeskTopPane``の``JLayeredPane.MODAL_LAYER``に追加するように変更しました。 -- [[aterai]] &new{2007-10-16 (火) 17:31:50}; - メモ: [http://weblogs.java.net/blog/alexfromsun/archive/2008/01/ Alexander Potochkin's Blog: Disabling Swing Containers, the final solution?]のサンプルでは、``Mnemonic``もちゃんとブロックできているようなので、「あとで調べる & 参考にする」こと。 -- [[aterai]] &new{2008-01-25 (金) 17:28:21}; - ``Mnemonic``を数字(``1``-``3``)に変更 -- [[aterai]] &new{2008-04-25 (金) 20:51:49}; - すべての``Mnemonic``を一時的に無効化したい場合に、``UIManager.java``の``private static final String disableMnemonicKey = "swing.disablenavaids";``は使えない? 以下のように、``KeyboardFocusManager.setCurrentKeyboardFocusManager(...)``で、``Alt``キーなどを無視する方法もあるが…、もっと簡単な方法を調査中。 -- [[aterai]] &new{2013-05-09 (木) 11:46:38}; #code{{ KeyboardFocusManager manager = KeyboardFocusManager.getCurrentKeyboardFocusManager(); KeyboardFocusManager.setCurrentKeyboardFocusManager(new DefaultKeyboardFocusManager() { @Override public boolean dispatchEvent(AWTEvent e) { if(e instanceof KeyEvent) { KeyEvent ke = (KeyEvent)e; if((ke.getModifiers() & InputEvent.ALT_MASK) != 0) { System.out.println("----\n"+ke); return false; } } return super.dispatchEvent(e); } }); JComboBox<String> combo = new JComboBox<>(new String[] {"Banana", "Apple", "Pear", "Grape"}); combo.setEditable(true); JOptionPane.showInternalMessageDialog( desktop, combo, "modal1", JOptionPane.INFORMATION_MESSAGE); KeyboardFocusManager.setCurrentKeyboardFocusManager(manager); }} #comment