2009-05-06 10 views
3

私はthis guideのアプローチ2に従ったので、今度は私が望むように他のフレームへの入力をブロックするModalInternalFrameを持っています。しかし、私はこの例から1つの変更を加えましたが、今は2つの問題があります。モーダルJInternalFrameを閉じる

変更

全体のポイントは、自分のペインを表示することですので、私は、JOptionPaneのを削除しました。閉じるには、closeabletrueに設定し、JOptionPaneのリスナーと同じコードを持つInternalFrameListenerを追加しました。それはうまくいかないので、doDefaultCloseActionの最後にコードを追加しました。

問題

  1. ModalInternal枠が消えることはありません。私はいくつかの例外がスローされていると思うが、...
  2. 私は投げられた例外を見ることができず、彼らはどこに行くのか分からない。通常、デバッグモードでは、例外がUncaughtExceptionHandlerに渡される直前にEclipseは停止しますが、この場合は発生しません。

コード

問題の私の説明が解決しない場合は、ここでModalInternalFrameの私のバージョンです。より多くのコードが必要な場合は、同様に投稿することができます。申し訳ありませんが、私はできるだけ簡潔にしようとしました。

public class ModalInternalFrame extends JInternalFrame { 
    public ModalInternalFrame(String title, JRootPane rootPane, 
      Component desktop) { 
     super(title, false, true, false, false); 

     // create opaque glass pane 
     final JPanel glass = new JPanel(); 
     glass.setOpaque(false); 

     // Attach mouse listeners 
     MouseInputAdapter adapter = new MouseInputAdapter() { }; 
     glass.addMouseListener(adapter); 
     glass.addMouseMotionListener(adapter); 

     this.addInternalFrameListener(new InternalFrameListenerAdapter() { 
      public void internalFrameClosed(InternalFrameEvent e) { close(); } 
      public void internalFrameClosing(InternalFrameEvent e){ close(); } 
     }); 

     // Change frame border 
     putClientProperty("JInternalFrame.frameType", "optionDialog"); 

     // Size frame 
     Dimension size = getPreferredSize(); 
     Dimension rootSize = desktop.getSize(); 

     setBounds((rootSize.width - size.width)/2, 
       (rootSize.height - size.height)/2, size.width, size.height); 
     desktop.validate(); 
     try { setSelected(true); } 
     catch (PropertyVetoException ignored) { } 

     glass.add(this);    // Add modal internal frame to glass pane 
     rootPane.setGlassPane(glass); // Change glass pane to our panel 
     glass.setVisible(true);  // Show glass pane, then modal dialog 
    } 

    private void close(){ 
     if (isVisible()) { 
      try { setClosed(true); } 
      catch (PropertyVetoException ignored) { } 
      setVisible(false); 
      rootPane.getGlassPane().setVisible(false); 
     } 
    } 

    @Override public void doDefaultCloseAction() { 
     super.doDefaultCloseAction(); 
     close(); 
    } 

    @Override public void setVisible(boolean flag) { 
     super.setVisible(flag); 
     if (flag) startModal(); 
     else stopModal(); 
    } 

    private synchronized void startModal() { 
     try { 
      if (SwingUtilities.isEventDispatchThread()) { 
       EventQueue theQueue = getToolkit().getSystemEventQueue(); 
       while (isVisible()) { 
        AWTEvent event = theQueue.getNextEvent(); 
        Object source = event.getSource(); 
        if (event instanceof ActiveEvent) { 
         ((ActiveEvent) event).dispatch(); 
        } else if (source instanceof Component) { 
         ((Component) source).dispatchEvent(event); 
        } else if (source instanceof MenuComponent) { 
         ((MenuComponent) source).dispatchEvent(event); 
        } else { 
         System.err.println("Unable to dispatch: " + event); 
        } 
       } 
      } else { while (isVisible()) { wait(); } } 
     } catch (InterruptedException ignored) { 
     } 

    } 

    private synchronized void stopModal() { notifyAll(); } 

} 

アップデート:私はモーダルダイアログボックスが細かい私のニーズに合わせたが、誰もがアイデアを持っていない場合、私はそれを聞いて喜んでいるだろうことを発見しました。私が試していないことの1つは、try {} catch(Exception e){}にすべてのメソッドをラップすることです。

+0

コンストラクタでsetClosable(true);を追加することができます:私はJInternalフレーム上のウェビーITのブログ記事からそれを得ました。 – Pool

+0

David Molesのソリューションはあなたのために機能しましたか?もしそうなら、あなたはそれを受け入れるべきです、この質問はまだ開いています。 – BoffinbraiN

+0

@BoffinbraiN実際に、私はDavidのソリューションを試してみる前に、モーダル内部フレームアプローチを放棄しました。私はそれを受け入れたいと思いますが、私はそれが動作するという独立した確認がある場合にのみ、私はそれを自分で試す時間がありません。 –

答えて

0
 public void internalFrameClosing(InternalFrameEvent e){ close(); } 

close()を呼び出すと、スタックがオーバーフローするまでinternalFrameClosing()が再び呼び出されます。

そのリスナーを完全に削除してみます。

+0

ありがとう、私はチャンスを得るときにこれを試してみます。私はモーダルのJInternalFramesに代わるものを見つけましたが、私はまだこの作品を見たいと思っています。 –

1

私はコードを実行することはできませんが、ここではSunの例に基づいてより簡単なバージョンが動作します。メインフレームにはボタンがあります(利用可能なすべてのスペースを占有します)。ボタンをクリックすると、内部フレームが閉じられるまでブロックされます。

あなたが見ることができるのは、自分自身のフレームにnew JOptionPane().createInternalFrame()のビジネスを置き換えたということです。私の推測では、あなた自身のイベントの発送をしようとすると、あなたはものを過度に複製しているということです。

何か不足していますか?

public class Foo { 

    public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    frame.setSize(600, 400); 
    frame.setLocationByPlatform(true); 

    JButton desktop = new JButton(new AbstractAction("Click me if you can") { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
     System.out.println("I have been clicked"); 
     } 
    }); 
    frame.getContentPane().add(desktop); 

    frame.setVisible(true); 

    JInternalFrame modal = 
     new JInternalFrame("Modal Popup", false, true, false, false); 
    JLabel popupContent = new JLabel("I am the popup"); 
    popupContent.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); 
    modal.add(popupContent); 
    modal.pack(); 

    JPanel glass = new JPanel(); 
    glass.setOpaque(false); 
    glass.add(modal); 
    frame.setGlassPane(glass); 
    glass.setVisible(true); 
    modal.setVisible(true); 

    modal.addInternalFrameListener(new ModalAdapter(glass)); 
    } 
} 

class ModalAdapter extends InternalFrameAdapter { 
    Component glass; 

    public ModalAdapter(Component glass) { 
    this.glass = glass; 

    // Associate dummy mouse listeners 
    // Otherwise mouse events pass through 
    MouseInputAdapter adapter = new MouseInputAdapter() { 
    }; 
    glass.addMouseListener(adapter); 
    glass.addMouseMotionListener(adapter); 
    } 

    public void internalFrameClosed(InternalFrameEvent e) { 
    glass.setVisible(false); 
    } 
} 
1

私はちょうどプロジェクトのためにこのことをしなければなりませんでした。私がしたことはすべて、メインウィンドウのオブジェクトをJinternalframeに渡しました。メインオブジェクトには、モーダルがロックされているかどうかを追跡するセマフォがあります。 Jinternalframe(拡張)を閉じると、メインオブジェクトのセマフォが呼び出されます。非常に簡単です。 これはメインのコードではありませんが、あなたのアイデアを得る:

アプリケーションのコードは、私が続く

//calling frame  
CalledFrame cf=new CalledFrame(); 
cf.setParent(this); 
cf.setVisible(true); 
modalLoacked=true; 
private void jLabel1MouseReleased(java.awt.event.MouseEvent evt) { 
    if (modalLocked) 
    return; 
    else// (do your things) 
    } 

から始まるので、internalframesを呼び出すために画像の部分とラベルを使用しています私の場合

//called frame 
public CallingFrame parent; 
public void setParent(CallingFrame parent_){ 
    this.parent=parent_; 
} 
private void frameClosed(javax.swing.event.InternalFrameEvent evt) { 
    parent.modalLocked=false; 
} 

チュートリアルですが、ほとんどのものは、1つのセマフォが1つの呼び出されたフレームが閉じられていない間に、どの領域もクリックしないようにするトリックを行うと、オーバーコンプリートします。

2

これを試してください。 http://webbyit.blogspot.com/2011/03/managing-jinternalframes-within.html

import java.awt.*; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyVetoException; 
import java.beans.VetoableChangeListener; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.*; 
import javax.swing.event.InternalFrameAdapter; 
import javax.swing.event.InternalFrameEvent; 

/** 
* An extended <code>JInternalFrame</code> that provides modality in a child/parent hierarchy. 
* <a href="From http://webbyit.blogspot.com/2011/03/managing-jinternalframes-within.html">source: webby it internal frames blog post</a> 
* 
* @author webbyit 
*/ 
public class ModalityInternalFrame extends JInternalFrame { 

    protected JDesktopPane desktopPane; 
    protected JComponent parent; 
    protected ModalityInternalFrame childFrame; 
    protected JComponent focusOwner; 
    private boolean wasCloseable; 

    public ModalityInternalFrame() { 
     init(); // here to allow netbeans to use class in gui builder 
    } 

    public ModalityInternalFrame(JComponent parent) { 
     this(parent, null); 
    } 

    public ModalityInternalFrame(JComponent parent, String title) { 
     this(parent, title, false); 
    } 

    public ModalityInternalFrame(JComponent parent, String title, boolean resizable) { 
     this(parent, title, resizable, false); 
    } 

    public ModalityInternalFrame(JComponent parent, String title, boolean resizable, boolean closeable) { 
     this(parent, title, resizable, closeable, false); 
    } 

    public ModalityInternalFrame(JComponent parent, String title, boolean resizable, boolean closeable, 
      boolean maximizable) { 
     this(parent, title, resizable, closeable, maximizable, false); 
    } 

    public ModalityInternalFrame(JComponent parent, String title, boolean resizable, boolean closeable, 
      boolean maximizable, 
      boolean iconifiable) { 
     super(title, resizable, closeable, maximizable, iconifiable); 
     setParentFrame(parent); 
     //setFocusTraversalKeysEnabled(false); 
     if (parent != null && parent instanceof ModalityInternalFrame) { 
      ((ModalityInternalFrame) parent).setChildFrame(ModalityInternalFrame.this); 

      /* 
      * set focus to the new frame and show the frame Code added by Jasir 
      */ 
      try { 
       ((ModalityInternalFrame) parent).setSelected(false); 
       setSelected(true); 
       setVisible(true); 
      } catch (PropertyVetoException ex) { 
       Logger.getLogger(ModalityInternalFrame.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 

     // Add glass pane 
     ModalityInternalGlassPane glassPane = new ModalityInternalGlassPane(this); 
     setGlassPane(glassPane); 


     // Add frame listeners 
     addFrameListener(); 

     // Add frame veto listenr 
     addFrameVetoListener(); 

     init(); 


     // calculate size and position 


    } 

    private void setParentFrame(JComponent parent) { 
     desktopPane = JOptionPane.getDesktopPaneForComponent(parent); 
     this.parent = parent == null ? JOptionPane.getDesktopPaneForComponent(parent) : parent; // default to desktop if no parent given 
    } 

    public JComponent getParentFrame() { 
     return parent; 
    } 

    public void setChildFrame(ModalityInternalFrame childFrame) { 
     this.childFrame = childFrame; 
    } 

    public ModalityInternalFrame getChildFrame() { 
     return childFrame; 
    } 

    public boolean hasChildFrame() { 
     return (childFrame != null); 
    } 

    protected void addFrameVetoListener() { 
     addVetoableChangeListener(new VetoableChangeListener() { 

      public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException { 
       if (evt.getPropertyName().equals(JInternalFrame.IS_SELECTED_PROPERTY) 
         && evt.getNewValue().equals(Boolean.TRUE)) { 
        if (hasChildFrame()) { 
         //childFrame.setSelected(true); 
         if (childFrame.isIcon()) { 
          childFrame.setIcon(false); 
         } 
         throw new PropertyVetoException("no!", evt); 
        } 
       } 
      } 
     }); 
    } 

    /** 
    * Method to control the display of the glass pane, dependant on the frame 
    * being active or not 
    */ 
    protected synchronized void addFrameListener() { 
     addInternalFrameListener(new InternalFrameAdapter() { 

      @Override 
      public void internalFrameActivated(InternalFrameEvent e) { 
       if (hasChildFrame() == true) { 
        getGlassPane().setVisible(true); 
        grabFocus(); 
       } else { 
        getGlassPane().setVisible(false); 
       } 
      } 

      @Override 
      public void internalFrameOpened(InternalFrameEvent e) { 
       getGlassPane().setVisible(false); 
       try { 
        setSelected(true); 
       } catch (PropertyVetoException ex) { 
        Logger.getLogger(ModalityInternalFrame.class.getName()).log(Level.SEVERE, null, ex); 
       } 
      } 

      @Override 
      public void internalFrameClosing(InternalFrameEvent e) { 
       if (parent != null && parent instanceof ModalityInternalFrame) { 
        ((ModalityInternalFrame) parent).childClosing(); 
       } 
      } 
     }); 
    } 

    /** 
    * Method to handle child frame closing and make this frame available for 
    * user input again with no glass pane visible 
    */ 
    protected void childClosing() { 
     setClosable(wasCloseable); 
     getGlassPane().setVisible(false); 
     if (focusOwner != null) { 
      java.awt.EventQueue.invokeLater(new Runnable() { 

       @Override 
       public void run() { 
        try { 
         moveToFront(); 
         setSelected(true); 
         focusOwner.grabFocus(); 
        } catch (PropertyVetoException ex) { 
        } 
       } 
      }); 
      focusOwner.grabFocus(); 
     } 
     getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 
     setChildFrame(null); 
     getDesktopPane().setSelectedFrame(this); 
     System.out.println(getDesktopPane().getSelectedFrame()); 
    } 

    /* 
    * Method to handle child opening and becoming visible. 
    */ 
    protected void childOpening() { 
     // record the present focused component 
     wasCloseable = isClosable(); 
     setClosable(false); 
     focusOwner = (JComponent) getMostRecentFocusOwner(); 
     grabFocus(); 
     getGlassPane().setVisible(true); 
     getGlassPane().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); 
    } 

    @Override 
    public void show() { 
     if (parent != null && parent instanceof ModalityInternalFrame) { 
      // Need to inform parent its about to lose its focus due 
      // to child opening 
      ((ModalityInternalFrame) parent).childOpening(); 
     } 
     calculateBounds(); 
     super.show(); 
    } 

    protected void init() { 
     javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); 
     getContentPane().setLayout(layout); 
     layout.setHorizontalGroup(
       layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 394, Short.MAX_VALUE)); 
     layout.setVerticalGroup(
       layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 274, Short.MAX_VALUE)); 

     pack(); 
    } 

    public void calculateBounds() { 
     Dimension frameSize = getPreferredSize(); 
     Dimension parentSize = new Dimension(); 
     Dimension rootSize = new Dimension(); // size of desktop 
     Point frameCoord = new Point(); 

     if (desktopPane != null) { 
      rootSize = desktopPane.getSize(); // size of desktop 
      frameCoord = SwingUtilities.convertPoint(parent, 0, 0, desktopPane); 
      parentSize = parent.getSize(); 
     } 

     //setBounds((rootSize.width - frameSize.width)/2, (rootSize.height - frameSize.height)/2, frameSize.width, frameSize.height); 

     // We want dialog centered relative to its parent component 
     int x = (parentSize.width - frameSize.width)/2 + frameCoord.x; 
     int y = (parentSize.height - frameSize.height)/2 + frameCoord.y; 

     // If possible, dialog should be fully visible 
     int ovrx = x + frameSize.width - rootSize.width; 
     int ovry = y + frameSize.height - rootSize.height; 
     x = Math.max((ovrx > 0 ? x - ovrx : x), 0); 
     y = Math.max((ovry > 0 ? y - ovry : y), 0); 
     setBounds(x, y, frameSize.width, frameSize.height); 
    } 

    /** 
    * Glass pane to overlay. Listens for mouse clicks and sets selected on 
    * associated modal frame. Also if modal frame has no children make class 
    * pane invisible 
    */ 
    class ModalityInternalGlassPane extends JComponent { 

     private ModalityInternalFrame modalFrame; 

     public ModalityInternalGlassPane(ModalityInternalFrame frame) { 
      modalFrame = frame; 
      addMouseListener(new MouseAdapter() { 

       @Override 
       public void mouseClicked(MouseEvent e) { 
        if (modalFrame.isSelected() == false) { 
         try { 
          modalFrame.setSelected(true); 
          if (modalFrame.hasChildFrame() == false) { 
           setVisible(false); 
          } 
         } catch (PropertyVetoException e1) { 
          //e1.printStackTrace(); 
         } 
        } 
       } 
      }); 
     } 

     @Override 
     public void paint(Graphics g) { 
      super.paint(g); 
      g.setColor(new Color(255, 255, 255, 100)); 
      g.fillRect(0, 0, getWidth(), getHeight()); 
     } 
    } 
} 
-2

あなただけのデバッグが失敗する場合、少なくとも/現在は無視catchブロックへのを誤るシステムを追加

関連する問題