RSS
热门关键字:
当前位置 : 主页>编程开发>java编程>入门>列表

Java图形用户界面设计

来源:我要研发网 作者: 时间:1970-01-01 点击:



  前言

  随着Internet飞速发展,Java技术也得到了越来越广泛应用。而无论我们是采用J2SE、J2EE还是J2ME,GUI都是不能回避问题。现在应用软件越来越要求界面友、功能强大而又使用简单。而众所周知,在Java中进行GUI设计相对于其跨平台、多线程等特性实现要复杂和麻烦许多。这也是很多Java程序员抱怨事情。但GUI已经成为程序发展方向,所以我们也必须了解JavaGUI设计方法和特点。其实,采用Java提供布局管理器接口和相应布局管理类,我们也可以做出相当漂亮界面来,当然实现起来肯定要比VB麻烦许多。本文试图通过自己开发经历介绍一些具体应用实例,希望能给那些曾经象我一样苦闷Java痴迷者一些帮助。 字串3

  Java中布局管理字串1

  为什么要使用布局

字串1

  在实际编程中,我们每设计一个窗体,都要往其中添加若干组件。为了管理这些组件布局,我们就需要使用布局管理器。比如说,设计一个简单计算器,或一个文本编辑器等等。这些组件是让JVM 自己任意安排呢?还是按照一定位置关系进行规范安排呢?当然应该选择后者。将加入到容器组件按照一定顺序和规则放置,使之看起来更美观,这就是布局。在Java中,布局由布局管理器 (LayoutManager) 来管理。那么,我们在什么时候应该使用布局管理器?应选择哪种布局管理器?又该怎样使用布局管理器呢? 字串5

  如果你写是GUI程序,在使用AWT/Swing组件时就不应硬性设置组件大小和位置,而应该使用Java布局管理器(LayoutManager)来设置和管理可视组件大小和位置,否则就有可能造成布局混乱。不信,你可以新建一个Frame(或JFrame),通过setBounds()方法往其中添加几个Button(或JButton),一旦你将窗体拉大或缩小时,你会发现组件排列完全不是按你所预想那样。为了解决这个问题,即当窗体(或容器)缩放时,组件位置也随之合理调整,我们就需要使用布局管理器。 字串1

  为此,我们首先要知道Java布局方式,Java提供API中有些什么布局管理器,它们布局特点是什么。

字串9

  Java布局方式 字串1

  我们都知道,JavaGUI界面定义是由AWT类包和Swing类包来完成。它在布局管理上采用了容器和布局管理分离方案。也就是说,容器只管将其他组件放入其中,而不管这些组件是如何放置。对于布局管理交给专门布局管理器类(LayoutManager)来完成。 字串4

  现在我们来看Java中布局管理具体实现。我们前面说过,Java中容器类(Container),它们只管加入组件(Component),也就是说,它只使用自己add()方法向自己内部加入组件。同时他记录这些加入其内部组件个数,可以通过container.getComponentCount()方法类获得组件数目,通过container.getComponent(i)来获得相应组件句柄。然后LayoutManager类就可以通过这些信息来实际布局其中组件了。

字串8


字串8

   Java已经为我们提供了几个常用布局管理器类,例如: FlowLayout、BorderLayout、GridLayout、GridBagLayout等。下面列表说明它们布局特点: 字串6

  包类特点

字串7

  java.awt CardLayout 将组件象卡片一样放置在容器中,在某一时刻只有一个组件可见 字串6

  java.awt FlowLayout 将组件按从左到右而后从上到下顺序依次排列,一行不能放完则折到下一行继续放置 字串9

  java.awt GridLayout 形似一个无框线表格,每个单元格中放一个组件 字串5

  java.awt BorderLayout 将组件按东、南、西、北、中五个区域放置,每个方向最多只能放置一个组件

字串3

  java.awt GridBagLayout 非常灵活,可指定组件放置具体位置及占用单元格数目 字串8

  Javax.swing BoxLayout 就像整齐放置一行或者一列盒子,每个盒子中一个组件 字串1

  Javax.swing SpringLayout 根据一组约束条件放置子组件 字串7

  Javax.swing ScrollPaneLayout 专用于JScrollPane,含一个Viewport,一个行头、一个列头、两个滚动条和四个角组件 字串7

  Javax.swing OverlayLayout 以彼此覆盖形式叠置组件 字串7

  Javax.swing ViewportLayout JViewport默认布局管理

字串2

  事实上,在大多数情况下,综合运用这些布局管理器已可以满足需要。当然对于特殊具体应用,我们可以通过实现LayoutManager或LayoutManager2接口来定义自己布局管理器。下面我们通过几个实例来了解几个常用布局管理使用方法。 字串3

  GUI设计应用实例 字串7

  FlowLayout/GridLayout/BorderLayout应用实例 字串7

  应用背景

字串7

  假设我们要编写一个简单计算器JApplet,其基本界面如下

   字串7

  解决方法

字串6

  通过其界面要求可知,我们可以通过将"BackSpace"和"Clear"JButton放置在一个JPanel(1)中,采用FlowLayout布局;将显示结果JTextField和该JPanel一起放置到另外一个JPanel(2),采用GridLayout布局;而将其它JButton则放置在另外一个JPanel(3)中,采用GridLayout布局;再将JPanel(2)和JPanel(3)加入该JApplet,即可实现界面需求。具体实现方法如下:

字串2


字串5

/**以FlowLayout布局JPanel(1)*/
JPanel p1 = new JPanel(new FlowLayout()); //默认组件从居中开始
//加入"BackSpace"和"Clear"JButton
p1.add(backButton);
p1.add(clearButton);
/**以GridLayout布局JPanel(2)*/
JPanel p2 = new JPanel(new GridLayout(2, 1)); //放置2行,每行1个组件
//加入显示结果JTextField和JPanel(1)
p2.add(displayField);
p2.add(p1);
/**以GridLayout布局JPanel(3)*/
JPanel p3 = new JPanel(new GridLayout(4, 5)); //放置4行,每行5个组件
String buttonStr = "789/A456*B123-C0.D =";
for (int i = 0; i < buttonStr.length(); i )
this.addButton(p3, buttonStr.substring(i, i 1));
//addButton方法
private void addButton(Container c, String s)
{
JButton b = new JButton(s);
if (s.equals("A"))
b.setText("sqrt");
else if (s.equals("B"))
b.setText("1/x");
else if (s.equals("C"))
b.setText("%");
else if (s.equals("D"))
b.setText(" /-"); 字串6
b.setForeground(Color.blue);
c.add(b);
b.addActionListener(this);
}
/**以BorderLayout布局JApplet*/
this.setLayout(new BorderLayout());
this.add(p2, "North");
this.add(p3, "Center");

  这样,就一切OK啦。具体实现代码可参见附件中CalculateApplet.java文件。

字串9

  带工具栏和状态栏GridLayout/BorderLayout应用实例 字串1

  实际问题 字串5

  在很多情况下我们需要动态设置工具栏和状态栏,看下面应用实例:

字串8

   字串8


字串4

  以上是在视图工具栏和状态栏都被复选时候,以下分别为某一个没选或都未选情况。

字串7

  

字串7

  解决方法
字串3

  /**工具栏JToolBar采用从左开始FlowLayout布局*/
JToolBar toolBar = new JToolBar();
toolBar.setBorderPainted(false); //不画边界
toolBar.setLayout(new FlowLayout(FlowLayout.LEFT));
/**窗体采用动态BorderLayout布局,通过获取工具栏或状态栏复选标记进行界面动态调整*/
JSplitPane splitPane = new JSplitPane();
splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); //设置统计窗口分隔条方向
splitPane.setDividerLocation(300); //设置分隔条位置
splitPane.setOneTouchExpandable(true);
JCheckBoxMenuItem toolBarItem = new JCheckBoxMenuItem("工具栏(T)", true);
JLabel statusLabel = new JLabel("当前统计目标:");
JCheckBoxMenuItem statusBarItem = new JCheckBoxMenuItem("状态栏(S)", true);

字串5


  /**设置系统窗体布局并动态设置工具栏和状态栏*/
private void setLayout()
{
if (toolBarItem.getState() &&am;' statusBarItem.getState())
{
this.getContentPane().add(BorderLayout.NORTH, toolBar);
this.getContentPane().add(BorderLayout.CENTER, splitPane);
this.getContentPane().add(BorderLayout.SOUTH, statusLabel);
}
else if (toolBarItem.getState() && !statusBarItem.getState())
{
this.getContentPane().add(BorderLayout.NORTH, toolBar);
this.getContentPane().remove(statusLabel);
}
else if (statusBarItem.getState() && !toolBarItem.getState())
{
this.getContentPane().add(BorderLayout.SOUTH, statusLabel);
this.getContentPane().remove(toolBar);
}
else if (!toolBarItem.getState() && !statusBarItem.getState())
{
this.getContentPane().remove(toolBar);
this.getContentPane().remove(statusLabel);
}
this.show(); //添加或移去组件后刷新界面
}
  通过该方法即可实现界面动态刷新与调整。 字串4


字串4

  GridBagLayout应用实例 字串5

  实际问题 字串3

  GridBagLayout是Java API提供一个较复杂布局管理器,利用它可以解决许多实际编程令人烦恼界面设计问题。看下面界面应用实例:

  

字串8

  解决方法 字串7

  这个界面设计比较复杂,涉及多个标签域(JLabel)、文本域(JTextField、JTextArea),且标签域大小还不一样,如附件标签;并当窗体缩放时,标签域大小应不改变,而文本域则必须自适应缩放。如何来实现呢?请看下面代码:(工具栏实现不再赘述) 字串7

    /**系统界面布局实现*/
GridBagConstraints gridBag = new GridBagConstraints();
gridBag.fill = GridBagConstraints.HORIZONTAL; //以水平填充方式布局
gridBag.weightx = 0; //行长不变
gridBag.weighty = 0; //列高不变
fromLabel.setForeground(Color.blue);
fromLabel.setFont(new Font("Alias", Font.BOLD, 16));
this.add(fromLabel, gridBag, 0, 1, 1, 1); //指定发信人标签位置
receiveLabel.setForeground(Color.blue);
receiveLabel.setFont(new Font("Alias", Font.BOLD, 16));
this.add(receiveLabel, gridBag, 0, 2, 1, 1); //指定收信人标签位置及大小
ccLabel.setForeground(Color.blue);
ccLabel.setFont(new Font("Alias", Font.BOLD, 16));
this.add(ccLabel, gridBag, 0, 3, 1, 1); //指定抄送人标签位置及大小
subjectLabel.setForeground(Color.blue);
subjectLabel.setFont(new Font("Alias", Font.BOLD, 16));
his.add(subjectLabel, gridBag, 0, 4, 1, 1); //指定主题标签位置及大小
accessoryLabel.setForeground(Color.blue); 字串1
accessoryLabel.setFont(new Font("Alias", Font.BOLD, 16));
this.add(accessoryLabel, gridBag, 0, 5, 1, 1); //指定附件标签位置及大小
  gridBag.weightx = 100; //行自适应缩放
gridBag.weighty = 0;//列高不变
fromField.setText("admin@watermelon.com");
this.add(fromField, gridBag, 1, 1, 2, 1); //指定发信人文本域(JTextField)位置及大小
this.add(receiveField, gridBag, 1, 2, 2, 1); //指定收信人文本域(JTextField)位置及大小
this.add(ccField, gridBag, 1, 3, 2, 1); //指定抄送人文本域(JTextField)位置及大小
this.add(subjectField, gridBag, 1, 4, 2, 1); //指定主题文本域(JTextField)位置及大小
accessoryArea.setEditable(false);
//设置不显示水平滚动条(该JTextArea置于JScrollPane中)
accessoryScroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
this.add(accessoryScroll, gridBag, 1, 5, 2, 1); //指定附件文本区(JTextArea)位置及大小
  gridBag.fill = GridBagConstraints.BOTH;//采用全填充方式布局
gridBag.weightx = 100;//行自适应缩放 字串3
gridBag.weighty = 100;//列自适应缩放
mailArea.setBackground(Color.blue);
mailArea.setForeground(Color.yellow);
mailArea.setTabSize(4);
//指定信件主体区(JTextArea)位置及大小。(该JTextArea也置于JScrollPane中)
this.add(scroll, gridBag, 0, 6, 3, 1);
  在上面用到一个方法add(),这个方法是自己定义
private void add(Component c, GridBagConstraints gbc, int x, int y, int w, int h)
{
gbc.gridx = x;
gbc.gridy = y;
gbc.gridheight = h;
gbc.gridwidth = w;
this.getContentPane().add(c, gbc);
}

  在用到GridBagLayout布局管理组件添加方法中,都可以重用它。事实上,你还可以在方法最前面加一个参数Container cn,而将方法中this相应改为cn,就可以通用于所有需要使用GridBagLayout进行布局管理容器中。在下面复杂例程中我们就会用到。 字串8


字串6

  综合多个布局复杂应用实例

字串9

  实际问题 字串3

  请看下面实际应用界面要求:

字串7

   字串2

  (图3.4-1)

字串6

  

字串9

  (图3.4-2) 字串8

   字串9

  (图3.4-3)

字串1

  在这个具体应用中,底部JButton组是确定,但JTabbedPane每一个选项都不同,如何实现呢?

字串6

  解决方案

字串6

  首先我们可以采用BorderLayout确定主题对话框布局方式,实现方法如下: 字串4

  JTabbedPane dbTabPane = new JTabbedPane();
…… //下面需要用到JButton等组件变量定义(或声明)
private void initLayout()
{
initDBTabPane();//初始化JTabbedPane:DBTabPane组件
this.getContentPane().add(BorderLayout.CENTER, dbTabPane);
//将JTabbedPane组件:dbTabPane布局于JDialog对话框中间
initButtonPanel();//初始化JPanel:ButtonPanel组件
this.getContentPane().add(BorderLayout.SOUTH, buttonPanel);
//将JPanel组件:buttonPanel布局于JDialog对话框底部(南面)
}
  private void initDBTabPane()
{
JPanel loginPanel = new JPanel(new GridLayout(10, 1));
//为保证两个JCheckBox组件位于顶端,设置为共10行,每行一个组件布局,但只
//放置界面要求两个组件,这样就保持了界面美观,否则如定义为 字串3
//Gridlayout(2,1)则会使两个组件居中,而且中间会隔开较长距离。
pwdBox.setMnemonic('P');
loginPanel.add(pwdBox);
dspBox.setMnemonic('D');
loginPanel.add(dspBox);
dbTabPane.add("Login", loginPanel); //设置"Login"JPanel(图3.4-1)布局
needRadio.setMnemonic('N');
allRadio.setMnemonic('A');
cacheRadio.setMnemonic('U');
radioPanel.setBorder(new TitledBorder("Load Option"));//加上边界标题
radioPanel.add(needRadio);
radioPanel.add(allRadio);
radioPanel.add(cacheRadio);
//以上为加入需要JRadioButton组件到指定JPanel: radioPanel
queryPanel.add(radioPanel);//加入含JRadioButton组JPanel到queryPanel
reqBox.setMnemonic('R');
boxPanel.add(reqBox); 字串8
saveBox.setMnemonic('S');
boxPanel.add(saveBox);
autoBox.setMnemonic('t');
boxPanel.add(autoBox);
//以上为加入需要JCheckBox组到指定JPanel:boxPanel
queryPanel.add(boxPanel); //加入含JCheckBox组JPanel到queryPanel
dbTabPane.add("Query", queryPanel);//设置"Query"JPanel(图3.4-2)布局
initDrvPanel();
}
  /**设置"Drivers"JPanel(图3.4-3)布局*/
private void initDrvPanel()
{
gridBag.fill = GridBagConstraints.HORIZONTAL;
gridBag.weightx = 100;
gridBag.weighty = 0;
tipLabel.setForeground(Color.black);
this.add(drvPanel, tipLabel, gridBag, 0, 0, 4, 1);
urlLabel.setForeground(Color.black);
this.add(drvPanel, urlLabel, gridBag, 0, 5, 4, 1);
urlField.setEditable(false);

字串7


this.add(drvPanel, urlField, gridBag, 0, 6, 4, 1);
gridBag.weightx = 0;
gridBag.weighty = 0;
addButton.setMnemonic('A');
this.add(drvPanel, addButton, gridBag, 3, 1, 1, 1);
editButton.setMnemonic('E');
this.add(drvPanel, editButton, gridBag, 3, 2, 1, 1);
removeButton.setMnemonic('R');
this.add(drvPanel, removeButton, gridBag, 3, 3, 1, 1);
gridBag.fill = GridBagConstraints.BOTH;
gridBag.weightx = 100;
gridBag.weighty = 100;
//设置JTable组件:drvTable从0到7行第0列
for (int i = 0; i < 8; i )
drvTable.setValueAt(drvStrs[i],i,0);
//设置JTable列头
drvTable.getColumn(drvTable.getColumnName(0)).setHeaderValue("All Drivers");
drvTable.setShowGrid(false);//设置不显示网格线
this.add(drvPanel, drvScroll, gridBag, 0, 1, 3, 4);
dbTabPane.add("Drivers", drvPanel);
字串1

}
  /**初始化底部JButton组布局*/
private void initButtonPanel()
{
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
//从右边开始进行FlowLayout布局
okButton.setMnemonic('O');
buttonPanel.add(okButton);
cancelButton.setMnemonic('C');
buttonPanel.add(cancelButton);
helpButton.setMnemonic('H');
buttonPanel.add(helpButton);
}
  /**给指定容器cn在指定(x,y)位置放置指定大小(宽度=w,高度=h)组件c*/
private void add(Container cn, Component c, GridBagConstraints gbc, int x, int y, int w, int h)
{
gbc.gridx = x;
gbc.gridy = y;
gbc.gridwidth = w;
gbc.gridheight = h;
cn.add(c, gbc);
}

  结束语

字串5


字串4

  以上是本人在两年多J2EE应用开发中,总结关于用Java进行GUI设计一些经验,希望能给曾经象我一样迷惘,但依旧对Java一往情深,至今仍在摸索探求Java GUI设计捷径朋友一些启示。更希望借此机会抛砖引玉,与更多朋友进行交流与探讨。其实,在Java中所有布局管理器都要实现一个接口,即LayoutManager Inerface或者是它一个子接口LayoutManager2 Interface,后者用于更复杂布局管理。如果在实际应用中,觉得Java API提供这些布局管理器仍不够用,你完全可以自己来实现其中某一个接口方法,从而为你自己具体GUI应用设计提供更布局管理

字串1

字串2

最新评论共有 0 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册
相关文章