[转] 使用JInternalFrame实现MDI

声明:本文章中介绍的内容可以在GPF项目中找到相应的实现。
 
GPF计划使用MDI的处理模式,Java的JDesktopPane和JInternalFrame已经为我们实现了这样的功能。但是,在将JInternalFrame最大化的时候,JDesktopPane和我们熟知的其他软件,如Word等,具有不同的处理方式。此时可以通过这里介绍的内容弥补这一缺点,使Swing的程序更类似于本地实现。
 
首先先看一下怎么使用JDesktopPane和JInternalFrame实现MDI。其实实现的方式很简单,就是在一个窗口中添加JDesktopPane,然后使用JDesktopPane的add方法,添加JInternalFrame的实例即可。具体的代码片段如下所示:
 
//... 
final JDesktopPane desktopPane = new JDesktopPane(); 
//... 
Container content = getContentPane(); 
content.add(desktopPane, BorderLayout.CENTER); 
//... 
InnerFrame iFrame = new InnerFrame(); 
iFrame.setVisible(true); 
desktopPane.add(iFrame); 
//... 
 
 
由此即可按照Java提供的方式添加MDI的实现。我们可以看到它的运行截图如下所示:
 
 
可以看到,当JInternalFrame最大化的时候,仅仅是充满了整个JDesktopPane,并不会像一般的MDI程序一样,将最大化最小化的按钮显示在菜单栏。这是因为JInternalFrame是一个轻量级组件,必须依附在容器之中,因此它的大小不可能超出JDesktopPane。为了获得我们想要的效果,我们对JInternalFrame的UI进行改写:
 
class InnerFrame extends JInternalFrame { 
   
  /** The is hidden. */ 
  boolean isHidden = false; 
   
  /** The old ui. */ 
  BasicInternalFrameUI oldUi = null; 
   
  /** 
   * Instantiates a new inner frame. 
   */ 
  public InnerFrame() { 
      oldUi = (BasicInternalFrameUI)getUI(); 
      setSize(200, 200); 
      maximizable = true; 
      closable = true; 
      addComponentListener(new ComponentAdapter() { 
         public void componentResized(ComponentEvent e) { 
            InnerFrame selectedFrame = (InnerFrame)e.getSource(); 
            if(selectedFrame.isMaximum()){ 
              selectedFrame.hideNorthPanel(); 
              opPane.setVisible(true); 
              try { 
                 selectedFrame.setMaximum(true); 
              } catch (PropertyVetoException ex) { 
                 ex.printStackTrace(); 
              } 
          } 
      } 
    }); 
  } 
   
  /** 
   * Hide north panel. 
   */ 
  public void hideNorthPanel(){ 
      ((BasicInternalFrameUI) this.getUI()).setNorthPane(null); 
      this.putClientProperty("JInternalFrame.isPalette", Boolean.TRUE); 
      isHidden = true; 
  } 
   
  /** 
   * Show north panel. 
   */ 
  public void showNorthPanel() { 
      this.setUI(oldUi); 
      this.putClientProperty("JInternalFrame.isPalette", Boolean.FALSE); 
      isHidden = false; 
  } 
   
  /* (non-Javadoc) 
   * @see javax.swing.JInternalFrame#updateUI() 
   */ 
  public void updateUI() { 
      super.updateUI(); 
      if (isHidden) { 
        hideNorthPanel(); 
      } 
  } 
}
 
 
InnerFrame类继承自JInternalFrame,由于JInternalFrame没有对于窗口最大化事件的监听。所以,我们把它添加了一个ComponentListener。当组件大小改变时,调用componentResized方法,然后在这里判断如果组件大小是isMaximum()的,则将NorthPane隐藏掉。这里的JInternalFrame的NorthPane就是绘有关闭按钮的那一条面板。由于定义了hideNorthPane()和showNorthPane()这两个方法,是得我们对于InnerFrame的控制加强了。
 
修改后的完整代码如下所示:
 
import java.awt.BorderLayout; 
import java.awt.Container; 
import java.awt.Dimension; 
import java.awt.FlowLayout; 
import java.awt.Insets; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.ComponentAdapter; 
import java.awt.event.ComponentEvent; 
import java.beans.PropertyVetoException; 

import javax.swing.JButton; 
import javax.swing.JDesktopPane; 
import javax.swing.JFrame; 
import javax.swing.JInternalFrame; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.plaf.basic.BasicInternalFrameUI; 

/** 
* MDIFrame is a frame using JInternalFrame to implements MDI as Word on Windows. 
*  
* @author Cheng 
* @version 1.0.0 for GPF MDI test 
*/ 
@SuppressWarnings("serial") 
public class MDIFrame extends JFrame { 
  
    /** The desktop pane. */ 
    final JDesktopPane desktopPane = new JDesktopPane(); 
  
    /** The operation pane with restore and close buttons. */ 
    final JPanel opPane = new JPanel(); 
  
    /** 
     * Instantiates a new mDI frame. 
     */ 
    public MDIFrame(){ 
      setTitle("MDI Frame"); 
      setSize(600, 550); 
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
   
      final JMenuBar bar = new JMenuBar(); 
      JMenuItem exit = new JMenuItem("Exit"); 
          exit.addActionListener(new ActionListener(){ 

              @Override 
              public void actionPerformed(ActionEvent e) { 
                   System.exit(0); 
              } 
    
      }); 
      bar.add(exit); 
      // operation pane with two button, set invisible at first 
      opPane.setLayout(new FlowLayout(FlowLayout.TRAILING)); 
      JButton restore = new JButton("#"); 
      restore.setMargin(new Insets(0, 0, 0, 0)); 
      restore.setPreferredSize(new Dimension(15, 15)); 
      restore.addActionListener(new ActionListener(){ 

      @Override 
      public void actionPerformed(ActionEvent e) { 
            InnerFrame i = (InnerFrame)desktopPane.getSelectedFrame(); 
            try { 
                // notice this method, when JInternalFrame set maximun false
                // this internal frame will be set as old size 
                i.setMaximum(false); 
            } catch (PropertyVetoException ex) { 
                ex.printStackTrace(); 
            } 
            i.showNorthPanel(); 
            opPane.setVisible(false); 
          } 
    
      }); 
      opPane.add(restore); 
      JButton close = new JButton("X"); 
      close.setMargin(new Insets(0, 0, 0, 0)); 
      close.setPreferredSize(new Dimension(15, 15)); 
      close.addActionListener(new ActionListener(){ 

          @Override 
          public void actionPerformed(ActionEvent e) { 
            JInternalFrame i = desktopPane.getSelectedFrame(); 
            i.dispose(); 
            opPane.setVisible(false); 
          } 
    
      }); 
      opPane.add(close); 
      bar.add(opPane); 
      opPane.setVisible(false); 
      setJMenuBar(bar); 
   
      Container content = getContentPane(); 
      content.add(desktopPane, BorderLayout.CENTER); 
      final JPanel ctrlPane = new JPanel(); 
      JButton add = new JButton("add"); 
      add.addActionListener(new ActionListener(){ 

          @Override 
          public void actionPerformed(ActionEvent e) { 
              InnerFrame iFrame = new InnerFrame(); 
              iFrame.setVisible(true); 
              desktopPane.add(iFrame); 
          } 
    
      }); 
      ctrlPane.add(add); 
      content.add(ctrlPane, BorderLayout.SOUTH); 
      setVisible(true); 
    } 
  
    /** 
     * The Class InnerFrame. 
     */ 
    class InnerFrame extends JInternalFrame { 
   
      /** The is hidden. */ 
      boolean isHidden = false; 
   
      /** The old ui. */ 
      BasicInternalFrameUI oldUi = null; 
   
      /** 
       * Instantiates a new inner frame. 
       */ 
      public InnerFrame() { 
          oldUi = (BasicInternalFrameUI)getUI(); 
          setSize(200, 200); 
          maximizable = true; 
          closable = true; 
          addComponentListener(new ComponentAdapter() { 
              public void componentResized(ComponentEvent e) { 
                  InnerFrame selectedFrame = (InnerFrame)e.getSource(); 
                  if(selectedFrame.isMaximum()){ 
                      selectedFrame.hideNorthPanel(); 
                      opPane.setVisible(true); 
                      try { 
                           selectedFrame.setMaximum(true); 
                      } catch (PropertyVetoException ex) { 
                           ex.printStackTrace(); 
                       } 
                   } 
               } 
          }); 
      } 
   
      /** 
       * Hide north panel. 
       */ 
      public void hideNorthPanel(){ 
          ((BasicInternalFrameUI) this.getUI()).setNorthPane(null); 
          this.putClientProperty("JInternalFrame.isPalette", Boolean.TRUE); 
          isHidden = true; 
      } 
   
      /** 
       * Show north panel. 
       */ 
      public void showNorthPanel() { 
          this.setUI(oldUi); 
          this.putClientProperty("JInternalFrame.isPalette", Boolean.FALSE); 
          isHidden = false; 
      } 
   
      /* (non-Javadoc) 
       * @see javax.swing.JInternalFrame#updateUI() 
       */ 
      public void updateUI() { 
          super.updateUI(); 
          if (isHidden) { 
              hideNorthPanel(); 
          } 
       } 
    } 
  
    /** 
     * The main method. 
     *  
     * @param args the arguments 
     */ 
    public static void main(String[] args) { 
          SwingUtilities.invokeLater(new Runnable(){ 

              @Override 
              public void run() { 
                   new MDIFrame(); 
              } 
    
          }); 
     } 
} 
 
 
修改之后的最大化可以是如图样子:
 
 
当然,按钮之类的很难看,不过修改那个的话就是很容易的了,在这里不再赘述。
 
本程序代码在Java 6 下编译通过。由于Java文件不允许上传,所以将后缀名改为txt,编译时请将文件名改为MDIFrame.java即可。

本文出自 “豆子空间” 博客,请务必保留此出处http://devbean.blog.51cto.com/448512/92426

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 可能是因为以下原因导致jinternalframe窗口不显示: 1. 没有将jinternalframe添加到JDesktopPane中。 2. jinternalframe的setVisible属性设置为false。 3. jinternalframe的大小设置为或者太小。 4. jinternalframe的位置设置在屏幕外。 5. jinternalframe的内容为空或者没有添加组件。 6. jinternalframe的背景色与父容器相同,导致看不到。 7. jinternalframe的层级设置不正确,被其他组件遮挡。 需要检查以上问题,才能解决jinternalframe窗口不显示的问题。 ### 回答2: jInternalFrameJava Swing框架中的一个内部窗口,用于在应用程序的主窗口中创建一个独立的子界面。如果jInternalFrame窗口没有显示出来,可能是由于以下原因: 1. 必须将jInternalFrame对象添加到JDesktopPane窗口中。JDesktopPane是用于管理内部窗口的容器。要显示jInternalFrame,请确保将其添加到JDesktopPane中。 2. 在添加jInternalFrame到JDesktopPane之前,必须先将其设置为可见。只有当jInternalFrame可见时,才能被正确地添加到JDesktopPane中。 3. 可能是由于jInternalFrame设置了错误的大小或位置导致无法显示。请检查其大小和位置属性,并确保它们与容器对齐。 4. 可能是由于jInternalFrame的默认的关闭操作设置有误。如果默认操作设置为HIDE_ON_CLOSE,那么当用户关闭jInternalFrame时,它将被隐藏而不是销毁。要完全销毁jInternalFrame,请将默认关闭操作设置为DISPOSE_ON_CLOSE。 5. 可能是由于jInternalFrame被添加到了错误的父容器中。jInternalFrame只能被添加到JDesktopPane中,如果被添加到其他容器中将无法正常显示。 综上所述,jInternalFrame窗口不显示可能是由于容器的设置问题,可见性属性设置问题,大小、位置属性设置问题或默认关闭操作设置问题。要解决这些问题,请仔细检查代码并进行调试,在错误得到修复之前,请勿放弃,像解决其他问题一样,持之以恒! ### 回答3: JInternalFrameJava Swing中的内部窗口,它可以在应用程序的主窗口中创建子窗口来显示一些弹出式的交互窗口内容。但是,在一些情况下,我们可能会发现JInternalFrame窗口并没有显示出来。 首先,我们需要确定JInternalFrame对象已经正确创建并添加到JDesktopPane中。如果这一步骤都没有问题,那么我们需要检查一些可能导致JInternalFrame不显示的原因。 首先,我们需要检查JInternalFrame的可见性。在默认情况下,JInternalFrame是不可见的。所以,我们需要通过设置JInternalFrame的setVisible(true)方法来确保它是可见的。 其次,我们需要设置JInternalFrame的大小和位置。在默认情况下,JInternalFrame的大小会根据内容自动调整大小,但它并不一定满足我们的要求。因此,我们需要调用setBounds(x, y, width, height)方法来设置JInternalFrame的大小和位置。 还有一个处理JInternalFrame不显示的问题的方法是检查是否已经将JInternalFrame添加到正确的容器中。我们需要将JInternalFrame添加到JDesktopPane中以便显示,在这种情况下,我们需要确保JInternalFrame已经被正确添加到JDesktopPane中。 最后,我们还要检查我们的代码是否有错误。当我们使用函数或者方法时,我们需要确保这些函数和方法调用没有错误或异常。这是最基本的调试流程。通常来说,错误和异常总是能暴露问题的原因。 总之,当我们使用JInternalFrame时,我们需要确保它被设置为可见,大小和位置也被设置为正确,以及已经添加到正确的容器中。同时,我们还要注意不断查找代码中可能导致这一问题的错误或异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值