实验十四 Swing图形界面组件
实验时间 20178-11-29
一、知识部分
1.模型-视图-控制器模式 模型:储存内容 视图:显示内容 控制器:处理用户输入
2.布局管理 2-1.流布局管理器(FlowLayout) JPanel对象的默认布局管理器为FlowLayout,组件加入JPanel中总是处于中央,一行可以排列多个组件,如果一行的空间容纳不下所有的组件则换行。当顶层窗口缩放时,JPanel中组件的大小不会随之缩放。 2-2.边框布局管理器(BorderLayout) 是JFrame的内容窗格的默认布局管理器,可以选择将空间放在内容窗格的东、南、西、北、中。 且将组件加入其中时,组件会充满其对应的整个区域,如果在这个方位再加入一个组件,会覆盖原本存在的组件。当顶层窗口缩放时,东南西北的组件不会随之变化,中部的组件会等比例变化。 如果要在某方法并排加入几个组件,则可以先将组件加入JPanel中,再放入边框布局管理器。 BorderLayout的常量定义为字符串
frame.add(new JButton("Yes"),BorderLayout.SOUTH); 2-3.网格布局(Grid Layout) 布局类似于表格,每个单元大小一致,当顶层窗口缩放时组件大小也随之变化,但是尺寸比例保持一致。
frame.SetLayout(new GridLayout(4,4));//形成4x4的网格 frame.add(new JButton("1")); GridLayout(int r,int c) 参数之一可以为0,但是不能同时为0 GridLayout(int r,int c,int hgap,int vgap) hgap表示单元之间的水平间距,vgap表示单元之间的垂直间距
3.文本输入 3-1.扩展于JTextComponent的JTextField和JTextArea JTextField和JTextArea都用于文本输入,其中JTextField接收单行文本的输入,而JTextArea可接收多行文本的输入。
列数为文本域的宽度,如果希望文本域最多能输入N个字符,则将宽度设置为N
JTextField text = new JTextField("Input Here",20);
第二个构造函数可以指定文本区显示的行数和列数。如果需要设置滚动条,则需要将文本区加入JScrollPane中,再讲JScrollPane插入容器。
JTextArea area = new TextArea(4,10); JScrollPane pane = new JScrollPane(area); panel.add(pane); 3-2.扩展于JTextField的JPasswordField 接受单行输入,输入字符被特殊字符掩盖
3-3.JLabel 没有任何修饰,不能响应用户输入,只是容纳文本的组件。可以设置标签的显示文字、图标以及对其方式
其中对其方式是SwingConstants里的常量,如LEFT/RIGHT/CENTER等
JLabel label = new JLabel("User Name:",SwingConstants.RIGHT); 4.选择组件 4-1.JCheckBox 复选框自动带有标签和图标,在构造时可以提供,当用户选中复选框时会触发动作事件。
JCheckBox box = new JCheckBox("Bold"); box.setSelected(true); 4-2.单选钮(JRadioButton) 自带标签和图标。单选钮只能多选其一,要打到这种效果需要把所有的单选钮加入ButtonGroup的对象里,从而使得新按钮被按下时,取消前一个选中的按钮的状态。ButtonGroup直接扩展于Object类,所以单选钮需加入容器中进行布局,ButtonGroup和容器(如JPanel)是相互独立的。 选中时触发动作事件。 4-3.边框(Border) 任何继承自JComponent的组件都可以使用边框(void setBorder(Border b))。常用的方法是将组件放入容器中,然后容器使用边框。是通过调用BorderFactory的静态方法构建边框。 同时可以为边框设置标题:
Border etch = BorderFactory.createEtchedBorder(); Border title = BorderFactory.createTitleBorder(etch,"Title"); panel.setBorder(title); 4-4.组合框 JComboBox< T>是泛型类,构建时需注意。 组合框不仅有下拉选择的功能,还具有文本框编辑的功能。 获得当前选中内容:
combo.getItemAt(combo.getSelectedIndex()); //Object getItemAt(int index) 当用户从组合框中选中一个选项时,组合框就会产生一个动作事件。
4-5.滑动条(JSlider) 滑动条在构造时默认是横向,如果需要纵向滑动条:
JSlider s = new JSlider(SwingConstants.VERTICAL,min,max,initialValue); 当滑动条滑动时,会触发ChangeEvent,需要调用addChangeListener()并且安装一个实现了ChangeListener接口的对象。这个接口只有一个StateChanged方法
//得到滑动条的当前值 ChangeListener listen = event ->{ JSlider s = (JSlider)event.getSource(); int val = s.getValue(); ... }; 如果需要显示滑动条的刻度,则setPaintTicks(true); 如果要将滑动条强制对准刻度,则setSnapToTicks(true); 如果要为滑动条设置标签,则需要先构建一个Hashtable< Integer,Component>,将数字与标签对应起来,再调用setLabelTable(Dictionary label);
5.复杂的布局管理 5-1.GridBagLayout(网格组布局) 即没有限制的网格布局,行和列的尺寸可以改变,且单元格可以合并 过程: 1)建议一个GridBagLayout对象,不需要指定行列数 2)将容器setLayout为GBL对象 3)为每个组件建立GridBagConstraints对象,即约束组件的大小以及排放方式 4)通过add(component,constraints)增加组件 使用帮助类来管理约束会方便很多。 5-2.不使用布局管理器
frame.setLayout(null); JButton btn = new JButton("Yes"); frame.add(btn); btn.setBounds(10,10,100,30); //void setBounds(int x,int y,int width,int height)//x,y表示左上角的坐标,width/height表示组件宽和高,Component类的方法 5-3.组件的遍历顺序(焦点的顺序):从左至右从上到下
component.setFocusable(false);//组件不设置焦点 6.菜单 分为JMenuBar/JMenu/JMenuItem,当选择菜单项时会触发一个动作事件,需要注册监听器监听
7.对话框 对话框分为模式对话框和无模对话框,模式对话框就是未处理此对话框之前不允许与其他窗口交互。 7-1.JOptionPane 提供了四个用静态方法(showxxxx)显示的对话框: 构造对话框的步骤: 1)选择对话框类型(消息、确认、选择、输入) 2)选择消息类型(String/Icon/Component/Object[]/任何其他对象) 3)选择图标(ERROR_MESSAGE/INFORMATION_MESSAGE/WARNING_MESSAGE/QUESTION_MESSAGE/PLAIN_MESSAGE) 4)对于确认对话框,选择按钮类型(DEFAULT_OPTION/YES_NO_OPTION/YES_NO_CANCEL_OPTION/OK_CANCEL_OPTION) 5)对于选项对话框,选择选项(String/Icon/Component) 6)对于输入对话框,选择文本框或组合框 确认对话框和选择对话框调用后会返回按钮值或被选的选项的索引值 7-2.JDialog类 可以自己创建对话框,需调用超类JDialog类的构造器
public aboutD extends JDialog { public aboutD(JFrame owner) { super(owner,"About Text",true); .... } } 构造JDialog类后需要setVisible才能时窗口可见
if(dialog == null) dialog = new JDialog(); dialog.setVisible(true); 7-3.文件对话框(JFileChooser类) 7-4.颜色对话框(JColorChooser类)
二、实验部分
1、实验目的与要求
(1) 掌握GUI布局管理器用法;
(2) 掌握各类Java Swing组件用途及常用API;
2、实验内容和步骤
实验1: 导入第12章示例程序,测试程序并进行组内讨论。
测试程序1
l 在elipse IDE中运行教材479页程序12-1,结合运行结果理解程序;
l 掌握各种布局管理器的用法;
l 理解GUI界面中事件处理技术的用途。
l 在布局管理应用代码处添加注释;
测试程序2
l 在elipse IDE中调试运行教材486页程序12-2,结合运行结果理解程序;
l 掌握各种文本组件的用法;
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序3
l 在elipse IDE中调试运行教材489页程序12-3,结合运行结果理解程序;
l 掌握复选框组件的用法;
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序4
l 在elipse IDE中调试运行教材491页程序12-4,运行结果理解程序;
l 掌握单选按钮组件的用法;
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序5
l 在elipse IDE中调试运行教材494页程序12-5,结合运行结果理解程序;
l 掌握边框的用法;
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序6
l 在elipse IDE中调试运行教材498页程序12-6,结合运行结果理解程序;
l 掌握组合框组件的用法;
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序7
l 在elipse IDE中调试运行教材501页程序12-7,结合运行结果理解程序;
l 掌握滑动条组件的用法;
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序8
l 在elipse IDE中调试运行教材512页程序12-8,结合运行结果理解程序;
l 掌握菜单的创建、菜单事件监听器、复选框和单选按钮菜单项、弹出菜单以及快捷键和加速器的用法。
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序9
l 在elipse IDE中调试运行教材517页程序12-9,结合运行结果理解程序;
l 掌握工具栏和工具提示的用法;
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序10
l 在elipse IDE中调试运行教材524页程序12-10、12-11,结合运行结果理解程序,了解GridbagLayout的用法。
l 在elipse IDE中调试运行教材533页程序12-12,结合程序运行结果理解程序,了解GroupLayout的用法。
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序11
l 在elipse IDE中调试运行教材539页程序12-13、12-14,结合运行结果理解程序;
l 掌握定制布局管理器的用法。
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序12
l 在elipse IDE中调试运行教材544页程序12-15、12-16,结合运行结果理解程序;
l 掌握选项对话框的用法。
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序13
l 在elipse IDE中调试运行教材552页程序12-17、12-18,结合运行结果理解程序;
l 掌握对话框的创建方法;
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序14
l 在elipse IDE中调试运行教材556页程序12-19、12-20,结合运行结果理解程序;
l 掌握对话框的数据交换用法;
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序15
l 在elipse IDE中调试运行教材556页程序12-21、12-2212-23,结合程序运行结果理解程序;
l 掌握文件对话框的用法;
l 记录示例代码阅读理解中存在的问题与疑惑。
测试程序16
l 在elipse IDE中调试运行教材570页程序12-24,结合运行结果理解程序;
l 了解颜色选择器的用法。
l 记录示例代码阅读理解中存在的问题与疑惑。
实验2:组内讨论反思本组负责程序,理解程序总体结构,梳理程序GUI设计中应用的相关组件,整理相关组件的API,对程序中组件应用的相关代码添加注释。
实验:
本组负责的是第十二个实验,即optionDialog(选项对话框),该测试程序中GUI设计中应用的相关组件有:
LayoutManager: 布局接口,各种布局类均为其子类
frame.setLayout(布局对象) //设置窗口布局
null:不使用布局,此时可以容器内的组件可以调用方法,通过坐标以及尺寸进行组件定位:
组件定位方法为void setBounds(int x轴,int y轴,int 宽度,int 高度)
Jframe:创建该组件即创建了一个窗口。窗口是一个容器组件,所有内容均可以放入其中。
JPanel:创建一个可加入到JFrame窗口的容器。
JButtton:创建一个按钮。
JRadioButton:实现一个单选按钮,此按钮项可被选择或取消选择,并可为用户显示其状态。与 ButtonGroup 对象配合使用可创建一组按钮,一次只能选择其中的一个按钮。
JLabel:用于短文本字符串或图像或二者的显示区。
实验代码:
package optionDialog;
import javax.swing.*;
/**
* A panel with radio buttons inside a titled border.
*/
public class ButtonPanel extends JPanel
//创建一个可加入到JFrame窗体的容器//
{
private ButtonGroup group;
/**
* Constructs a button panel.
* @param title the title shown in the border
* @param options an array of radio button labels
*/
public ButtonPanel(String title, String... options)
{
setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title));
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
group = new ButtonGroup();
//加入到ButtonGroup中的JRdioButton只有一个可以被选中,而每个JRadioButton独享一个监听器,当其被选中时执行监听器中处理方法。//
// make one radio button for each option
for (String option : options)
{
JRadioButton b = new JRadioButton(option);
//实现一个单选按钮,此按钮项可被选择或取消选择,并可为用户显示其状态。与 ButtonGroup 对象配合使用可创建一组按钮,一次只能选择其中的一个按钮。//
b.setActionCommand(option);
add(b);
group.add(b);
b.setSelected(option == options[0]);
}
}
/**
* Gets the currently selected option.
* @return the label of the currently selected radio button.
*/
public String getSelection()
{
return group.getSelection().getActionCommand();
}
}
package optionDialog;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
/**
* A frame that contains settings for selecting various option dialogs.
*/
public class OptionDialogFrame extends JFrame
//Jframe是窗体组件。创建该组件即创建了一个窗口//
{
private ButtonPanel typePanel;
private ButtonPanel messagePanel;
private ButtonPanel messageTypePanel;
private ButtonPanel optionTypePanel;
private ButtonPanel optionsPanel;
private ButtonPanel inputPanel;
private String messageString = "Message";
private Icon messageIcon = new ImageIcon("blue-ball.gif");
private Object messageObject = new Date();
private Component messageComponent = new SampleComponent();
public OptionDialogFrame()
{
JPanel gridPanel = new JPanel();
//创建一个可加入到JFrame窗体的容器//
gridPanel.setLayout(new GridLayout(2, 3));
//设置窗口布局//
typePanel = new ButtonPanel("Type", "Message", "Confirm", "Option", "Input");
messageTypePanel = new ButtonPanel("Message Type", "ERROR_MESSAGE", "INFORMATION_MESSAGE",
"WARNING_MESSAGE", "QUESTION_MESSAGE", "PLAIN_MESSAGE");
messagePanel = new ButtonPanel("Message", "String", "Icon", "Component", "Other",
"Object[]");
optionTypePanel = new ButtonPanel("Confirm", "DEFAULT_OPTION", "YES_NO_OPTION",
"YES_NO_CANCEL_OPTION", "OK_CANCEL_OPTION");
optionsPanel = new ButtonPanel("Option", "String[]", "Icon[]", "Object[]");
inputPanel = new ButtonPanel("Input", "Text field", "Combo box");
gridPanel.add(typePanel);
gridPanel.add(messageTypePanel);
gridPanel.add(messagePanel);
gridPanel.add(optionTypePanel);
gridPanel.add(optionsPanel);
gridPanel.add(inputPanel);
// add a panel with a Show button
JPanel showPanel = new JPanel();
//创建一个可加入到JFrame窗体的容器//
JButton showButton = new JButton("Show");
// 创建一个显示为“show”的按钮”//
showButton.addActionListener(new ShowAction());
showPanel.add(showButton);
add(gridPanel, BorderLayout.CENTER);
add(showPanel, BorderLayout.SOUTH);
pack();
}
/**
* Gets the currently selected message.
* @return a string, icon, component, or object array, depending on the Message panel selection
*/
public Object getMessage()
{
String s = messagePanel.getSelection();
if (s.equals("String")) return messageString;
else if (s.equals("Icon")) return messageIcon;
else if (s.equals("Component")) return messageComponent;
else if (s.equals("Object[]")) return new Object[] { messageString, messageIcon,
messageComponent, messageObject };
else if (s.equals("Other")) return messageObject;
else return null;
}
/**
* Gets the currently selected options.
* @return an array of strings, icons, or objects, depending on the Option panel selection
*/
public Object[] getOptions()
{
String s = optionsPanel.getSelection();
if (s.equals("String[]")) return new String[] { "Yellow", "Blue", "Red" };
else if (s.equals("Icon[]")) return new Icon[] { new ImageIcon("yellow-ball.gif"),
new ImageIcon("blue-ball.gif"), new ImageIcon("red-ball.gif") };
else if (s.equals("Object[]")) return new Object[] { messageString, messageIcon,
messageComponent, messageObject };
else return null;
}
/**
* Gets the selected message or option type
* @param panel the Message Type or Confirm panel
* @return the selected XXX_MESSAGE or XXX_OPTION constant from the JOptionPane class
*/
public int getType(ButtonPanel panel)
{
String s = panel.getSelection();
try
{
return JOptionPane.class.getField(s).getInt(null);
}
catch (Exception e)
{
return -1;
}
}
/**
* The action listener for the Show button shows a Confirm, Input, Message, or Option dialog
* depending on the Type panel selection.
*/
private class ShowAction implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
if (typePanel.getSelection().equals("Confirm")) JOptionPane.showConfirmDialog(
OptionDialogFrame.this, getMessage(), "Title", getType(optionTypePanel),
getType(messageTypePanel));
else if (typePanel.getSelection().equals("Input"))
{
if (inputPanel.getSelection().equals("Text field")) JOptionPane.showInputDialog(
OptionDialogFrame.this, getMessage(), "Title", getType(messageTypePanel));
else JOptionPane.showInputDialog(OptionDialogFrame.this, getMessage(), "Title",
getType(messageTypePanel), null, new String[] { "Yellow", "Blue", "Red" },
"Blue");
}
else if (typePanel.getSelection().equals("Message")) JOptionPane.showMessageDialog(
OptionDialogFrame.this, getMessage(), "Title", getType(messageTypePanel));
else if (typePanel.getSelection().equals("Option")) JOptionPane.showOptionDialog(
OptionDialogFrame.this, getMessage(), "Title", getType(optionTypePanel),
getType(messageTypePanel), null, getOptions(), getOptions()[0]);
}
}
}
/**
* A component with a painted surface
*/
class SampleComponent extends JComponent
{
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Rectangle2D rect = new Rectangle2D.Double(0, 0, getWidth() - 1, getHeight() - 1);
g2.setPaint(Color.YELLOW);
g2.fill(rect);
g2.setPaint(Color.BLUE);
g2.draw(rect);
}
public Dimension getPreferredSize()
{
return new Dimension(10, 10);
}
}
package optionDialog;
import java.awt.*;
import javax.swing.*;
/**
* @version 1.34 2015-06-12
* @author Cay Horstmann
*/
public class OptionDialogTest
{
public static void main(String[] args)
{
EventQueue.invokeLater(() -> {
JFrame frame = new OptionDialogFrame();
frame.setTitle("OptionDialogTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
实验3:组间协同学习:在本班课程QQ群内,各位同学对实验1中存在的问题进行提问,提问时注明实验1中的测试程序编号,负责对应程序的小组需及时对群内提问进行回答。
第三部分:实验总结:
在这一周的学习过程中,我了解了Swing用户界面组件,GUI相关组件。总体上说,对界面的的布局不怎么会,就算是自己负责的实验部分,也有许多是在网络上查找相关资料后才相对掌握了一些,对于实验内容我了解的依然不够全面,特别是多选按钮的运用。而对于这一周的小组协作学习,我认为这对于我们的学习的确有一定的帮助,至少对于每个负责的部分我们都有互相讨论的人选。