[Java][圖形程序設計Swing][學習筆記]
很多人印象中Java編寫的程序都是通過鍵盤接收輸入,在控制臺屏幕上顯示結果。其實Java還可以編寫使用圖形用戶界面(GUI) 的程序,今天就為大家介紹一下Java的圖形界面-Swing。
1,Swing 概述
在 Java 1.0 剛剛出現的時候,包含了一個用于基本 GUI 程序設計的類庫,Sun將它稱為抽象窗口工具箱( Abstract Window Toolkit, AWT)。基本AWT庫采用將處理用戶界面元素的任務委派給每個目標平臺( Windows、Solaris、 Macintosh 等)的本地 GUI 工具箱的方式,由本地 GUI 工具箱負責用戶界面元素的創建和動作。因此,Sun 公司的口號是“ 一次編寫,隨處使用”。
但此方法在不同平臺上,操作會存在差異。要想給予用戶一致的、 可預見性的界面操作方式是相當困難的。在不同平臺上的 AWT 用戶界面庫中存在著不同的 bug。研發人員必須在每一個平號上測試應用程序, 因此人們嘲弄地將 AWT 稱為“ 一次編寫, 隨處調試”。
在 1996 年,Netscape 創建了一種稱為 IFC ( Internet Foundation Class) 的 GUI 庫, 它采用了與 AWT 完全不同的工作方式。它將按鈕、菜單這樣的用戶界面元素繪制在空白窗口上,而對等體只需要創建和繪制窗口。因此,Netscape 的 IFC 組件在程序運行的所有平臺上的外觀和動作都一樣。Sun 與 Netscape 合作完善了這種方式, 創建了一個名為 Swing 的用戶界面庫。
注意:Swing 沒有完全替代 AWT, 而是基于 AWT 架構之上。Swing 僅僅提供了能力更加強大的用戶界面組件。 尤其在采用 Swing 編寫的程序中,還需要使用基本的 AWT 處理事件。可以理解為:Swing 是指 “ 被繪制的” 用戶界面類;AWT 是指像事件處理這樣的窗口工具箱的底層機制。
Swing的優勢主要有:
Swing 擁有一個豐富、 便捷的用戶界面元素集合。
Swing 對底層平臺依賴的很少,因此與平臺相關的 bug 很少。
Swing 給予不同平臺的用戶一致的感覺。
2,創建框架
在 Java 中,頂層窗口(就是沒有包含在其他窗口中的窗口)被稱為框架(frame)。在 AWT 庫中有一個稱為 Frame 的類, 用于描述頂層窗口。這個類的 Swing 版本名為 JFrame,它擴展于 Frame 類。JFrame是極少數幾個不繪制在畫布上的Swing組件之一。因此,它的修改部件(按鈕、標題欄、圖標等)由用戶的窗口系統繪制,而不是由Swing繪制。
本節中將介紹有關Swing的JFrame的常用方法。以下例子是給出了一個在屏幕中顯示一個空框架的簡單程序。
import javax.swing.*; import java.awt.*; public class SimpleFrameTest { public static void main(String[] args) { EventQueue.invokeLater(() -> { SimpleFrame frame = new SimpleFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }); } } class SimpleFrame extends JFrame { private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; public SimpleFrame() { setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT); } }
Swing類位于javax.swing包中。包名javax表示這是一個Java擴展包,而不是核心包。
默認情況下,框架的大小為0×0像素,這種框架沒有什么實際意義。這里定義了一個子類SimpleFrame,它的構造器將框架大小設置為300×200像素。這是SimpleFrame和JFrame之間唯一的差別。
在SimpleFrameTest類的main方法,我們構造了一個SimpleFrame對象使它可見。
在每個Swing程序中,有兩個技術問題需要強調
1,所有的Swing組件必須由事件分派線程(event dispatch thread)進行配置,線程將鼠標點擊和按鈕控制轉移到用戶接口組件。下面的代碼片段是事件分派線程中的執行代碼:
EventQueue.invokeLater(()-> { statements });
2,定義一個用戶關閉這個框架時的響應動作。對于這個程序而言,只讓程序簡單退出即可。選擇這個響應動作的語句是:frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);,在包含多個框架的程序中,不能在用戶關閉其中的一個框架時就讓程序退出。在默認情況下,用戶關閉窗口時只是將框架隱藏起來,而程序并沒有終止。框架起初是不可見的,為了顯示框架,main方法需要調用框架的setVisible()方法。
在初始化語句結束后,main方法退出。需要注意,退出main并沒有終止程序,終止的只是主線程。事件分派線程保持程序處于激活狀態,知道關閉框架或調用System.exit方法終止程序。
3,框架定位
JFrame類本身只包含若干個改變框架外觀的方法。當然,通過繼承,從JFrame的各個超類中繼承了許多用于處理框架大小和位置的方法。其中最重要的有下面幾個:
setLocation和setBounds方法用于設置框架的位置。
setIconImage用于告訴窗口系統在標題欄、任務切換窗口等位置顯示哪個圖標。
setTitle用于改變標題欄的文字。
setResizable利用一個boolean值確定框架的大小是否允許用戶改變。
AWT和Swing中框架和組件類的繼承層次
3.1,框架屬性
組件類的很多方法是以獲取/設置方法對形式出現的,這樣的一個獲取/設置方法對被稱為一種屬性。屬性包含屬性名和類型。將get或set之后的第一個字母改為小寫字母就可以得到相應的屬性名。
針對get/set約定有一個例外:對于類型為boolean的屬性,獲取方法由is開頭。
3.2,確定合適的框架大小
要記住:如果沒有明確地指定框架的大小,所有框架的默認值為0×0像素。
API:java.awt.Component 1.0
boolean isVisible()
void setVisible(boolean b)
獲取或設置visible屬性。組件最初是可見的,但JFrame這樣的頂層組件例外。
void setSize(int width,int height) 1.1
使用給定的寬度和高度,重新設置組件的大小。
void setLocation(int x,int y) 1.1
將組件移到一個新的位置上。如果這個組件不是頂層組件,x和y左邊(或者p.x和p.y)是容器坐標;否則是屏幕坐標(例如:JFrame)
void setBounds(int x,int y,int width,int height) 1.1
移動并重新設置組件的大小
Dimension getSize() 1.1
void setSize(Dimension d) 1.1
獲取或設置當前組件的size屬性
API:java.awt.Window 1.0
void toFront()
將這個窗口顯示在其他窗口前面 — void toBack()
將這個窗口移到桌面窗口棧的后面,并相應地重新排列所有的可見窗口。
boolean isLocationByPlatform() 5.0
void setLocationByPlatform(boolean b) 5.0
獲取或設置locationByPlatform屬性。這個屬性在窗口顯示之前被設置,由平臺選擇一個合適的位置。
API:java.awt.Frame 1.0
boolean isResizable()
void setResizable(boolean b)
獲取或設置resizable屬性。這個屬性設置后,用戶可以重新設置框架的大小。
String getTitle()
void setTitle(String s)
獲取或設置title屬性,這個屬性確定框架標題欄中的文字
Image getIconImage()
void setIconImage(Image image)
獲取或設置iconImage屬性,這個屬性確定框架的圖標。窗口系統可能會將圖標作為框架裝飾或其他部位的一部分顯示。
boolean isUndecorated() 1.4
void setUndecorated(boolean b) 1.4
獲取或設置undecorated屬性。這個屬性設置后,框架顯示中將沒有標題欄或關閉按鈕這樣的裝飾。在框架顯示之前,必須調用這個方法。
int getExtendedState() 1.4
void setExtendedState(int state) 1.4
獲取或設置窗口狀態。狀態是下列值之一。
Frame.NORMAL
Frame.ICONIFIED
Frame.MAXIMINZED_HORIZ
Frame.MAXIMIZED_VERT
Frame.MAXIMIZED_BOTH
API:java.awt.Toolkit 1.0
static Toolkit getDefaultToolkit()
返回默認的工具箱
Dimension getScreenSize()
返回用戶屏幕的尺寸
API:javax.swing.ImageIcon 1.2
ImageIcon(String filename)
構造一個圖標,其圖像存儲在一個文件中
Image getImage()
獲得該圖標的圖像
6,使用顏色
Color類用于定義顏色。在java.awt.Color類中提供了13個預定義的常量,它們分別表示13種標準顏色
BLACK,BLUE,CYAN,DARK_GRAY,GRAY,GREEN,LIGHT_GRAY,MAGENTA,ORANGE,PINK,RED,WHITE,YELLOW
可以通過提供紅、綠、藍三色成分創建一個Color對象,以達到定制顏色的目的。三種顏色都是用0-255(也就是一個字節)之間的整型數值表示,調用Color的構造器格式為:Color(int redness,int greenness,int blueness)
API:java.awt.Color 1.0
Color(int r,int g,int b)
創建一個顏色對象
參數:r 紅色值(0-255)
參數:g 綠色值(0-255)
參數:b 藍色值(0-255)
API:java.awt.Graphics 1.0
Color getColor()
void setColor(Color c)
獲取或改變當前的顏色。所有后續的繪圖操作都使用這個新顏色
參數:c 新顏色
API:java.awt.Graphics2D 1.2
Paint getPaint()
void setPaint(Paint p)
獲取或設置這個圖形環境的繪制屬性。Color類實現了Paint接口。因此,可以使用這個方法將繪制屬性設置為純色。
void fill(Shape s)
用當前的顏料填充該圖形
API:java.awt.Component 1.0
Color getBackground()
void setBackground(Color c)
獲取或設置背景顏色
參數:c 新背景顏色
Color getForeground()
void setForeground(Color c)
獲取或設置前景顏色
參數:c 新背景顏色
7,文本使用特殊字體
如果經常選用不同的字體顯示文本。人們可以通過字體名(font face name)指定一種字體。字體名由"Helvetica"這樣的字體家族名(font family name)和一個可選的"Bold"后綴組成。例如:"Helvetica"和"Helvetica Bold"屬于"Helvetica"家族的字體。
想知道某臺計算機上允許使用的字體,需要調用GraphicsEnvironment類中的getAvailableFontFamilyNames方法。這個方法將返回一個字符型數組,其中包含了所有可用的字體名。
import java.awt.*; public class ListFonts { public static void main(String[] args) { String[] fontNames = GraphicsEnvironment .getLocalGraphicsEnvironment() .getAvailableFontFamilyNames(); for (String fontName : fontNames) { System.out.println(fontName); } } }
API:java.awt.Font 1.0
Font(String name,int style,int size)
創建一個新字體對象
參數:name 字體名。不是字體名(例如,“Helvetica Bold”),就是邏輯字體名(例如,“Serif”,“SansSerif”)
參數:style 字體風格(Font.PLAIN,Font.BOLD,Font.ITALIC或Font.BOLD+Font.ITALIC)
參數:size 字體大小
String getFontName()
返回字體名,例如,“Helvetica Bold”
String getFamily()
返回字體家族名,例如,“Helvetica”
String getName()
如果采用邏輯字體名創建字體,將返回邏輯字體,例如,“SansSerif”;否則,返回字體名。
Font deriveFont(int style) 1.2
Font deriveFont(float size) 1.2
Font deriveFont(int style,float size) 1.2
返回一個新字體,除給定大小和字體風格外,其余與原字體一樣
API:java.awt.font.LineMetrics 1.2
float getLeading()
返回字體的行間距-從一行文本底端到下一行文本頂端之間的空隙
float getHeight()
返回字體的總高度-兩條文本基線之間的距離(下坡度+行間距+上坡度)
API:java.awt.Graphics 1.0
Font getFont()
void setFont(Font font)
獲取或設置當前的字體。這種字體將被應用與后續的文本繪制操作中。
參數:font 一種字體
void drawString(String str,int x,int y)
采用當前字體和顏色繪制一個字符串
參數:str 將要繪制的字符串
參數:x 字符串開始的x坐標
參數:y 字符串開始的y坐標
8,顯示圖像
對于照片這樣的復雜圖像來說,通常都是由掃描儀或特殊的圖像處理軟件生成的。
一旦圖像保存在本地或網絡上,就可以將它們讀到Java應用程序中,并在Graphic對象上進行顯示。
以下例子:在一個窗口中平鋪顯示了一幅圖像。這里采用paintComponent方法來實現平鋪顯示。它的基本過程為:先在左上角顯示圖像的一個拷貝,然后使用copyArea將其拷貝到整個窗口。
import javax.swing.*; import java.awt.*; public class ImageTest { public static void main(String[] args) { JFrame frame = new ImageFrame(); frame.setTitle("ImageTest"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } } /* * A frame with an image component * */ class ImageFrame extends JFrame { public ImageFrame() { add(new ImageComponent()); pack(); } } /* * A component that displays a tiled image * */ class ImageComponent extends JComponent { private static final int DEFAULT_WIDTH = 300; private static final int DEFAULT_HEIGHT = 200; private Image image; public ImageComponent() { image = new ImageIcon("blue-ball.gif").getImage(); } public void paintComponent(Graphics g) { if (image == null) { return; } int imageWidth = image.getWidth(this); int imageHeight = image.getHeight(this); //draw the image in the upper-left corner g.drawImage(image, 0, 0, null); //tile the image across the component for (int i = 0; i * imageWidth <= getWidth(); i++) { for (int j = 0; j * imageHeight <= getHeight(); j++) { if (i + j > 0) { g.copyArea(0, 0, imageWidth, imageHeight, i * imageWidth, j * imageHeight); } } } } public Dimension getPreferredSize() { return new Dimension(DEFAULT_WIDTH, DEFAULT_HEIGHT); } }
Java
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。