声明:本文章中介绍的内容可以在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
分享到:
相关推荐
这可以通过创建一个JMenuBar对象,然后调用`JInternalFrame.setJMenuBar(JMenuBar)`方法来实现。菜单项可以用来执行各种操作,如关闭当前内部帧,或者在内部帧之间切换。 浮动特性(浮动): `JInternalFrame`的一...
在Java中实现MDI应用,通常会利用Swing库中的JDesktopPane和JInternalFrame组件。JDesktopPane作为主容器,可以容纳多个JInternalFrame对象,每个JInternalFrame代表一个独立的文档窗口。通过这些组件,开发者可以...
Java Swing库提供了实现MDI功能的支持。在Swing中,我们主要使用`JDesktopPane`作为主容器来容纳MDI子窗口,而`JInternalFrame`则用来创建和管理这些子窗口。下面我们将详细探讨如何在Java中创建一个简单的MDI示例。...
实现MDI应用的关键步骤如下: 1. **创建JFrame**:首先,你需要创建一个JFrame作为MDI应用的主窗口。在这个窗口中,我们将放置JDesktopPane。 ```java JFrame frame = new JFrame("MDI示例"); ``` 2. **添加...
5. **编程实现**:在Windows API编程中,实现MDI应用通常涉及WM_CREATE、WM_INITMENUPOPUP、WM_MDICREATE等消息处理。开发者需要使用像CreateMDIWindow这样的函数来创建子窗口,并使用MDIClient窗口作为容器来管理...
在Java中,MDI应用程序通过使用`javax.swing.JFrame`作为主窗口,并在其中添加`JDesktopPane`来实现。MDI应用程序通常包含多个子窗口(子框架),这些子窗口可以在主窗口内自由移动和排列。关键组件和技术包括: 1....
此外,可能还会讲解如何使用JInternalFrame实现MDI(多文档界面)应用,以及如何通过JSplitPane和JTabbedPane创建复杂的用户界面。 在Swing编程中,"hack"通常指的是巧妙的解决方案或非标准的使用方式,因此这个...
3. **Java Swing/AWT**:在Java中,可以使用`JDesktopPane`和`JInternalFrame`来实现MDI效果。 4. **Python**:Python的`wxPython`库或`PyQT`框架也可以实现MDI功能。 四、模拟写字板功能 模拟写字板的实现需要...
- 在Windows编程中,可以使用Visual Studio等IDE工具,结合C++、C#或VB.NET等语言,利用Windows API或者.NET Framework的Form和TabControl控件来实现Tabbed MDI。 - 对于Qt框架,可以使用QMainWindow和QTabWidget...
JFC主要通过`JDesktopPane`和`JInternalFrame`这两个核心组件来实现MDI功能。 - **JDesktopPane**:作为MDI应用程序的核心容器,它负责管理所有的`JInternalFrame`实例。`JDesktopPane`本身不提供任何界面元素,...
本章节将探讨Java Swing中的`JDesktopPane`和`JInternalFrame`组件及其使用方式,以及它们如何构建出一个功能强大的多文档界面(MDI)。通过本章节的学习,您将了解这些组件的基本特性、如何利用它们来实现桌面应用...
JDesktopPane 和 JInternalFrame 则可以实现MDI(多文档界面)应用程序。 在“Java Swing 教程”中,通常会涵盖这些基本概念,并通过实例演示如何实现它们。学习者可以逐步理解并实践Swing 的各种组件和功能,从而...
7. **多文档界面**:为了支持同时编辑多个文件,可以实现MDI(Multiple Document Interface),使用JDesktopPane和JInternalFrame来管理多个文档。 8. **事件处理**:每个按钮和菜单项都应有一个对应的...
1. **JInternalFrame的使用** `JInternalFrame`继承自`JFrame`,它可以在JDesktopPane上浮动并可被最小化、最大化、关闭。在`InternalFrameDemo`中,开发者会创建一个或多个`JInternalFrame`对象,然后添加到`...
这个简易的Java文本编辑器通过使用Swing组件实现了基本的MDI功能。它不仅提供了文档的打开、关闭、最大化等操作,还通过调整桌面大小的方法确保所有文档窗口都能正确显示。通过深入分析这段代码,可以了解到如何在...
9. **多文档界面(MDI)**:如果需要在同一应用中打开多个文件,可以使用`JDesktopPane`和`JInternalFrame`实现MDI布局。 10. **性能优化**:对于大量文本的处理,可能需要考虑使用模型视图分离的策略,以提高响应...
Swing还提供了许多高级特性,如JDesktopPane和JInternalFrame实现MDI(多文档界面)应用,JSpinner用于数值选择,JProgressBar和JProgressBar用于进度显示,JOptionPane用于简单的对话框提示,以及JSplitPane用于...
在固定资产管理场景中,可能通过JInternalFrame实现员工借用归还的记录查看,或者展示某个特定资产的历史记录,以提供更丰富的信息展示和交互体验。 固定资产管理的核心功能包括: 1. 员工操作:员工可以添加、...
1. **多文档接口(MDI)**:允许多个文件在同一窗口内同时打开,通过JDesktopPane和JInternalFrame实现。 2. **文件I/O**:使用java.io和java.nio包进行文件读写,注意处理大文件时的性能优化。 3. **撤销/重做**...
7. **Swing工具包**:JFileChooser用于打开和保存文件,JOptionPane用于显示消息框,JDesktopPane和JInternalFrame支持MDI(多文档界面)应用。 8. **线程管理**:Swing组件的更新必须在事件分发线程(EDT,Event ...