馬凱軍 周強 張季躍《面向物件與程式設計 Java》第十四周學習總結
實驗十四 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相關元件。總體上說,對介面的的佈局不怎麼會,就算是自己負責的實驗部分,也有許多是在網路上查詢相關資料後才相對掌握了一些,對於實驗內容我瞭解的依然不夠全面,特別是多選按鈕的運用。而對於這一週的小組協作學習,我認為這對於我們的學習的確有一定的幫助,至少對於每個負責的部分我們都有互相討論的人選。