雖然目前Java算不上前端開發的主力,但是作為Java入門基礎的一部分,學習Java的GUI編程還是有必要的,而且可以做出一些小且有趣的圖形程序來提高學習熱情。本篇學習總結均為一個Beginner的筆記與心得,如有描述不到或錯誤之處,敬請指正。
目錄:
1. JavaGUI主要開發工具 -- Swing類庫的誕生與功能
一個合格的Java Developer,不僅要掌握技術,還要有一定的Java歷史背景知識儲備。所以先簡要介紹一下用於JavaGUI開發的主要類庫:Swing。
在Java 1.0時代便有設計GUI的基本類庫Abstract Window Toolkit,簡稱AWT。AWT庫工作原理是將處理用戶界面元素的任務委派給目標平台(操作系統)的本地GUI工具箱,由本地GUI工具箱負責用戶界面元素的創建和動作。這種工作方式是有利也有弊,先說下利處:
弊處:
1996年,Netscape創建了另一種GUI庫IFC,他的工作方式是 將用戶界面組件繪制在空白窗口上,而對等體只需要負責創建和繪制空白窗口。Sun和Netscape合作並完善了這種方式,創建了名為Swing的用戶界面庫,這便是Swing的誕生。
但是Swing並沒有完全取代AWT,到目前Java SE 8中依舊有AWT與Swing兩個功能類庫:
Swing沒有完全取代AWT的原因是:Swing是基於AWT的架構之上,Swing僅僅是提供了能力更強大的用戶界面組件。在Swing編寫的程序中,還是需要AWT進行事件處理。簡單說就是,Swing是用戶界面類,AWT是底層機制。
AWT和Swing中框架和組件類的繼承層次
2.創建JFrame框架
Frame意為框架,也就是最頂層的窗口,可以在框架裡添加組件。我們創建一個窗口首先要創建一個框架。
JFrame的內部結構
注:Swing組件類都以“J”開頭,如 JButton,JFrame等,AWT組件不帶“J"。如果Swing組件和AWT組件一起用可能會導致視覺和行為的不一致。
現在,我們來創建一個空框架:
1 package simpleFrame; 2 3 //會用到awt和swing的類,先import。 4 import java.awt.*; 5 import javax.swing.*; 6 7 //創建一個SimpleFrame的類,裡面只有一個main函數,main函數裡有個事件分派線程。 8 public class SimpleFrame { 9 public static void main(String[] args) { 10 EventQueue.invokeLater(new Runnable() { 11 public void run() { 12 JFrame frame = new SizedFrame(); //new一個SizeFrame對象給frame變量管理,這便有了框架。SizeFrame是JFrame的子類。 13 frame.setTitle("SimpleFrame"); //設置框架的標題. 14 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //設定關閉按鈕。 15 frame.setVisible(true); //設定框架可見。 16 } 17 }); 18 } 19 } 20 21 //其實到這裡為止,我們可以在第12行直接new一個JFrame交給frame,但是JFrame默認框架大小是0×0,沒什麼實際意義。 22 //所以我們選擇繼承JFrame做一個子類起名SizedFrame,在這個類裡做一個構造器來設定框架的大小。 23 class SizedFrame extends JFrame { 24 25 //構造器 26 public SizedFrame() { 27 28 //下面四行代碼為獲取你pc屏幕的高度和寬度,交給int變量screenHeight和screenWidth。 29 Toolkit kit = Toolkit.getDefaultToolkit(); 30 Dimension screenSize = kit.getScreenSize(); 31 int screenHeight = screenSize.height; 32 int screenWidth = screenSize.width; 33 34 //setSize方法由父類Component類(GUI對象的祖先)繼承而來。設定框架長寬都為屏幕的1/2. 35 //setLocationByPlatform由Window類(Frame類的父類)繼承而來。由平台(操作系統)來選擇一個合適的顯示位置。 36 setSize(screenWidth/2,screenHeight/2); 37 setLocationByPlatform(true); 38 39 //setIconImage方法由Frame類繼承而來,設置框架圖標。 40 Image img = new ImageIcon("icon.gif").getImage(); 41 setIconImage(img); 42 43 //當然,事件分派線程裡的設定標題、設定關閉按鈕、和設定框架可見操作,也可以放在構造器裡來做。 44 } 45 }
Windows 10下運行:
3.在框架中添加組件JComponent
在Java中,Frame被設計成放置組件的容器,可以將用戶界面元素放置其中,JComponent就是一種組件(component本身就意為組件)。所以,現在我們可以在JComponent中書寫一些文字,並將其放置在Frame中:
1 package notHelloWorld; 2 3 import java.awt.*; 4 import javax.swing.*; 5 6 public class NotHelloWorld { 7 public static void main(String[] args) { 8 EventQueue.invokeLater(new Runnable() { 9 public void run() { 10 JFrame frame = new NotHelloWorldFrame(); 11 frame.setTitle("NotHelloWorld"); 12 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 13 frame.setVisible(true); 14 } 15 }); 16 } 17 } 18 19 class NotHelloWorldFrame extends JFrame { 20 21 //構造器 22 public NotHelloWorldFrame() { 23 //在框架中add組件並pack。 24 //當然也可以不必擴展JFrame類,可以直接在第10行new一個JFrame對象,並在其後add組件。 25 //這裡我們沒有設置框架的長寬,因為組件JComponent有長寬,框架會根據組件的大小調整自己的長寬。 26 add(new NotHelloWorldComponent()); 27 pack(); 28 } 29 } 30 31 class NotHelloWorldComponent extends JComponent { 32 public static final int MASSAGE_X = 75; 33 public static final int MASSAGE_Y = 100; 34 35 private static final int DEFAULT_WIDTH = 300; 36 private static final int DEFAULT_HEIGHT = 200; 37 38 //必須覆蓋paintComponent方法才能讓組件自己把自己畫出來。 39 //這個方法需要一個Graphics對象,在Java中,所有繪制必須使用Graphics對象。 40 public void paintComponent(Graphics g) { 41 //畫出一個字符串,並設置自組件左上角(0,0)開始顯示的位置。 42 g.drawString("Not a 'Hello, World!' program.", MASSAGE_X, MASSAGE_Y); 43 } 44 45 //還要覆蓋此方法以確定組件的首選長寬。 46 public Dimension getPreferredSize() { 47 return new Dimension(DEFAULT_WIDTH,DEFAULT_HEIGHT); 48 } 49 }
運行: