java圖形化Swing教程(二)
阿新 • • 發佈:2019-02-04
與多執行緒、泛型等不同,Swing主要在於使用。
下面主要放程式碼和註釋,少說話。
(一)共用程式碼
所有繼承JFrame的類都要有一個開始的框架來包含他們,這裡直接給出框架,以下幾點中不會重複書寫。
package Event;
import java.awt.*;
import javax.swing.*;
/**
*
* @author QuinnNorris
* 共用程式碼
*/
public class BaseFrame {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// 開啟一個執行緒,所有的Swing元件必須由事件分派執行緒進行配置,執行緒將滑鼠點選和按鍵控制轉移到使用者介面元件。
EventQueue.invokeLater(new Runnable() {
// 匿名內部類,是一個Runnable介面的例項,實現了run方法
public void run() {
JFrame frame = new *********();
// 將*號的地方換成你實現的JFrame的子類,來實現你的程式碼
frame.setExtendedState(Frame.MAXIMIZED_BOTH);
// 將視窗最大化
frame.setTitle("Christmas");
// 設定視窗標題
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 選擇當用戶關閉框架的時候進行的操作 ,在有些時候需要將視窗隱藏,不能直接退出需要用到這個方法
frame.setVisible(true);
// 將視窗可見化,這樣以便使用者在第一次看見視窗之前我們能夠向其中新增內容
}
});
}
}
輸出結果:得到一個基本的公用框架,以後的內容可以在其他類中書寫,放入這個框架中。
(二)按鈕事件
package Event;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/**
*
* @author QuinnNorris 按鈕事件
*/
public class ButtonFrame extends JFrame {
private JPanel buttonPanel;
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;
public ButtonFrame() {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
// 設定預設寬度和高度
buttonPanel = new JPanel();
// 將類的例項域中的JPanel面板物件例項化
makeButton("yellow",Color.YELLOW);
makeButton("blue",Color.BLUE);
makeButton("red",Color.RED);
//呼叫makeButton方法來建立並新增按鈕
add(buttonPanel);
// 我們將這個新增好按鈕的面板新增到原框架中
}
/**
* 通過方法來建立按鈕,並且完成關聯監視器和新增入面板的操作
* @param name 建立按鈕的標識
* @param backgroundColor 點選按鈕後改變的顏色,匿名內部類只能訪問final修飾的變數,所以要用final
*/
public void makeButton(String name,final Color backgroundColor){
JButton colorButton = new JButton(name);
//通過不同的標識名,我們建立按鈕
buttonPanel.add(colorButton);
//我們將建立的按鈕新增到面板中
//匿名內部類,建立一個ActionListener的例項
colorButton.addActionListener(new ActionListener(){
/**
* 當按鈕點選的時候,會自動的呼叫actionPerformed方法
*/
public void actionPerformed(ActionEvent event) {
buttonPanel.setBackground(backgroundColor);
// 呼叫setBackground方法,設定背景顏色
}
});
}
}
輸出結果:在一個全屏視窗中,上方有三個不同顏色的按鈕,按下去後,背景顏色會隨之改變。
(三)更改主題
package Event;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
/**
*
* @author QuinnNorris 更換主題
*/
public class MetalFrame extends JFrame {
private JPanel buttonPanel;
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;
public MetalFrame() {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
// 設定預設寬度和高度
buttonPanel = new JPanel();
// 將類的例項域中的JPanel面板物件例項化
UIManager.LookAndFeelInfo[] infos = UIManager
.getInstalledLookAndFeels();
// 呼叫這個靜態方法,我們獲得所有主題
makeButton(infos);
// 呼叫makeButton方法來將主題實現
add(buttonPanel);
// 我們將這個新增好按鈕的面板新增到原框架中
}
/**
* 通過方法來建立所有的主題按鈕,並且將他們關聯監視器
*
* @param infos
* 包含有所有型別主題的陣列
*/
private void makeButton(final UIManager.LookAndFeelInfo[] infos) {
for (UIManager.LookAndFeelInfo info : infos) {
JButton button = new JButton(info.getName());
// 用for-each迴圈來遍歷所有的主題
final UIManager.LookAndFeelInfo innerInfo = info;
// 將info複製並且定義位final型別,便於內部類的使用
buttonPanel.add(button);
// 我們將建立的按鈕新增到面板中
// 匿名內部類,建立一個ActionListener的例項
button.addActionListener(new ActionListener() {
/**
* 當按鈕點選的時候,會自動的呼叫actionPerformed方法
*/
public void actionPerformed(ActionEvent ae) {
try {
UIManager.setLookAndFeel(innerInfo.getClassName());
// 呼叫setLookAndFeel方法,更改主題
SwingUtilities.updateComponentTreeUI(buttonPanel);
// 通過這個靜態方法,將更改的主題立即應用
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
}
輸出結果:視窗上方有五個主題按鈕,分別寫著他們各自主題的名字,點選後會立即更改所屬主題。
(四)按鈕與擊鍵動作
package Event;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/**
*
* @author QuinnNorris 按鈕與擊鍵動作
*/
public class ActionFrame extends JFrame {
private JPanel buttonPanel;
private static final int DEFAULT_WIDTH = 300;
private static final int DEFAULT_HEIGHT = 200;
public ActionFrame() {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
// 設定預設寬度和高度
buttonPanel = new JPanel();
// 將類的例項域中的JPanel面板物件例項化
Action yellowAction = new ColorAction("Yellow", Color.YELLOW);
// 建立一個自己定義的ColorAction物件yellowAction
buttonPanel.add(new JButton(yellowAction));
// 建立一個按鈕,其屬性從所提供的 Action中獲取
add(buttonPanel);
// 我們將這個新增好按鈕的面板新增到原框架中
InputMap imap = buttonPanel
.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
// 我們將JPanel物件的InputMap設定為第二種輸入對映,並建立該物件
imap.put(KeyStroke.getKeyStroke("ctrl Y"), "panel.yellow");
// 在imap中通過呼叫擊鍵類KeyStroke的靜態方法設定擊鍵輸入ctrl+Y的組合
// 第二個引數是一個標誌引數,將這對引數用鍵值對的形式存入imap
ActionMap amap = buttonPanel.getActionMap();
// 我們不能將InputMap直接和Action做對映,我們需要用ActionMap做過渡
// 用JPanel中的getACtionMap方法獲得amap物件
amap.put("panel.yellow", yellowAction);
// 將imap中標記引數對應的擊鍵組合和相應的Action組合起來
}
public class ColorAction extends AbstractAction {
/**
* ColorAction的構造器,存放鍵值對
* @param name 按鈕的名稱
* @param c 按鈕對應點選後顯示的顏色
*/
public ColorAction(String name, Color c) {
putValue(Action.NAME, name);
putValue(Action.SHORT_DESCRIPTION,
"Set panel color to " + name.toLowerCase());
putValue("color", c);
//在構造器中設定一些鍵值對對映,這些設定的屬性將會被JPanel讀取
}
/**
* 當按鈕點選或擊鍵的時候,會自動的呼叫actionPerformed方法
*/
public void actionPerformed(ActionEvent event) {
Color c = (Color) getValue("color");
buttonPanel.setBackground(c);
// 呼叫setBackground方法,設定背景顏色
}
}
}
輸出結果:視窗上方有yellow按鈕,通過點選或者ctrl+Y都可以使背景變黃,滑鼠懸停在上面一段時間會顯示說明文字。
(五)滑鼠操作
package Event;
import javax.swing.*;
/**
*
* @author QuinnNorris
* 繼承JFrame的子類,將Component物件內容打包
*/
public class MouseFrame extends JFrame{
public MouseFrame(){
add(new MouseComponent());
//向框架中新增一個JComponent的例項
pack();
}
}
package Event;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import javax.swing.*;
/**
*
* @author QuinnNorris 滑鼠點選
*/
public class MouseComponent extends JComponent {
private static final int SIDELENGTH = 100;
// 定義創造的正方形的邊長
private ArrayList<Rectangle2D> squares;
// 宣告一個正方形集合
private Rectangle2D current;
// java類庫中用來描述矩形的類,它的物件可以看作是一個矩形
/**
* 構造器方法,做初始化工作
*/
public MouseComponent() {
squares = new ArrayList<>();
current = null;
addMouseListener(new MouseHandler());
// 新增一個我們實現的類,這個類繼承了監測滑鼠點選情況的MouseListener
addMouseMotionListener(new MouseMotionHandler());
// 新增另一個實現類,這個類繼承了監測滑鼠移動情況的MouseMotionListener
}
/**
* 我們覆蓋了這個以用來列印圖形,將會被自動呼叫
*
* @param g
* Graphics是我們要使用的2D的一個父類
*/
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
// 轉換為我們需要使用的型別
for (Rectangle2D r : squares)
g2.draw(r);
// 對陣列中的每個正方形,都進行繪製
}
/**
* 判斷在這個座標上是否有圖形
*
* @param p
* 一對當前的x,y的座標值
* @return 返回存在的圖形或者null
*/
public Rectangle2D find(Point2D p) {
for (Rectangle2D r : squares) {
if (r.contains(p))
//contains方法測定座標是否在圖形的邊界內
return r;
}
// 如果在squares這個陣列中有這個位置的座標,表明這個位置上非空
// 返回這個位置上的物件
return null;
// 否則如果什麼都沒有,返回null
}
/**
* 在這個座標位置增加一個圖形
* @param p 座標位置
*/
public void add(Point2D p) {
double x = p.getX();
double y = p.getY();
//獲取x和y的座標
current = new Rectangle2D.Double(x - SIDELENGTH / 2,
y - SIDELENGTH / 2, SIDELENGTH, SIDELENGTH);
//用獲得的座標和既定的邊長構建一個新的正方形,並將其賦值給current
squares.add(current);
//將current新增到squares佇列中
repaint();
//重繪影象
}
/**
* 將這個位置的圖形移除
* @param s 代表所要移除的矩形物件
*/
public void remove(Rectangle2D s) {
if (s == null)
return;
//如果要移除的內容為空,直接返回
if (s == current)
current = null;
//如果要移除的內容和current正指向的內容相同,則將current清空
//避免發生不必要的錯誤
squares.remove(s);
//將s從squares的列表中直接刪去
repaint();
//重繪影象
}
/**
*
* @author QuinnNorris 繼承了MouseAdapter類的滑鼠點選控制類
*/
private class MouseHandler extends MouseAdapter {
/**
* 單擊滑鼠操作
*/
public void mousePressed(MouseEvent event) {
current = find(event.getPoint());
// 將滑鼠單擊的這個點的座標的物件賦給current
if (current == null)
//如果這個點沒有物件,當前指向空的位置
add(event.getPoint());
//在這個點繪製正方形
}
/**
* 滑鼠雙擊操作
*/
public void mouseClicked(MouseEvent event) {
current = find(event.getPoint());
// 將滑鼠單擊的這個點的座標的物件賦給current
if (current != null && event.getClickCount() >= 2)
//如果這個點有物件,而且點選滑鼠的次數大於2
remove(current);
//移除current
}
}
/**
*
* @author QuinnNorris
* 滑鼠移動拖動類
*/
private class MouseMotionHandler implements MouseMotionListener {
/**
* 滑鼠游標移動到元件上,但未按下時呼叫
*/
public void mouseMoved(MouseEvent event) {
if (find(event.getPoint()) == null)
//如果滑鼠所在位置不是空
setCursor(Cursor.getDefaultCursor());
//則將游標的影象設定為預設的影象
else
setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
//如果當前位置有影象,則將游標樣式設定為手型
}
/**
* 滑鼠游標在元件上按下,並拖動時呼叫
*/
public void mouseDragged(MouseEvent event) {
if (current != null) {
//因為在呼叫這個方法之前肯定會呼叫點選滑鼠的方法
//所以我們直接判斷:如果現在current不為空
int x = event.getX();
int y = event.getY();
//獲取到座標
current.setFrame(x - SIDELENGTH / 2, y - SIDELENGTH / 2,
SIDELENGTH, SIDELENGTH);
//最後在滑鼠放下時進行圖形繪製
repaint();
//重繪影象
}
}
}
}
輸出結果:在這個窗體中,單擊一次滑鼠會建立一個100畫素為邊長的小正方形。在正方形內,雙擊或更多次點選會刪除這個正方形。可以點住正方形並進行拖動,並且在指示正方形區域內時,滑鼠指標變為手型指標。