天天看點

swing内容

UI 元件簡介

在開始學習 Swing 之前,必須回答針對真正初學者的一個問題:什麼是 UI?初學者的答案是“使用者界面”。但是因為本教程的目标是要保證您不再隻是個初學者,是以我們需要比這個定義更進階的定義。

是以,我再次提出這個問題:什麼是 UI?您可能把它定義成您按下的按鈕、打字的位址欄 、打開和關閉的視窗,等等,這些都是 UI 的元素,但是除了在螢幕上看到的這些之外,還有更多都是 UI 元素。比如滑鼠、鍵盤、音量、螢幕顔色、使用的字型,以及一個對象相對于另一個對象的位置,這些都包含在 UI 之中。實際上,在計算機和使用者的互動之中扮演角色的任何對象都是 UI 的組成部分。這看起來足夠簡單,但是您應當驚訝的是,有許多人和大型公司已經為它努力了很多年。實際上,現在有的大學專業的惟一課程就是研究這種互動。

Swing 的角色

Swing 是 Java 平台的 UI —— 它充當處理使用者和計算機之間全部互動的軟體。它實際上充當使用者和計算機内部之間的中間人。Swing 到底是如何做這項工作的呢?它提供了處理前面一節中描述的 UI 各方面内容的機制:

  • 鍵盤:Swing 提供了捕捉使用者輸入的方法。
  • 顔色:Swing 提供改變在螢幕上看到的顔色的方法。
  • 打字的位址欄:Swing 提供了文本元件,處理所有普通任務。
  • 音量:Swing 不太擅長。

無論如何,Swing 為您提供了建立自己的 UI 所需要的所有工具

MVC

Swing 甚至走得更遠一步,在基本的 UI 原則之上又放上了一個公共的設計模式。這個設計模式叫做模型-視圖-控制器(Model-View-Controller,MVC),它試圖“把角色分開”。MVC 讓負責顯示的代碼、處理資料的代碼、對互動進行響應并驅動變化的代碼彼此分離。

有點迷惑?如果我為這個設計模式提供一個現實世界的非技術性示例,它就比較容易了。請想像一次時裝秀。把秀場當成 UI,假設服裝就是資料,是展示給使用者的計算機資訊。現在,假設這次時裝秀中隻有一個人。這個人設計服裝、修改服裝、同時還在 T 台上展示這些服裝。這看起來可不是一個構造良好的或有效率的設計。

現在,假設同樣的時裝秀采用 MVC 設計模式。這次不是一個人做每件事,而是将角色分開。時裝模特(不要與 MVC 縮寫中的模型混淆)展示服裝。他們扮演的角色是視圖。他們知道展示服裝(資料的)适當方法,但是根本不知道如何建立或設計服裝。另一方面,時裝設計師充當控制器。時裝設計師對于如何在 T 台上走秀沒有概念,但他能建立和操縱服裝。時裝模特和設計師都能獨立地處理服裝,但都有自己的專業領域。

這就是 MVC 設計模式背後的概念:讓 UI 的每個方面處理它擅長的工作。如果您仍然不明白,那麼教程後面的示例有望消除您的迷惑 —— 但是在您繼續進行的時候,請記住基本的原則:用可視元件顯示資料,同時讓其他類操縱資料。

JComponent

Swing 的整個可視元件庫的基礎構造塊是 JComponent。它是所有元件的父類。它是一個抽象類,是以不能建立 JComponent,但是作為類層次結構的結果,從字面意義來說它包含了數百個函數,Swing 中的每個元件都可以使用這些函數。顯然,有些概念要比其他概念重要,是以對于本教程,需要學習的重要的東西是:

  • JComponent 不僅是 Swing 元件的基類,還是定制元件的基類(有關的更多資訊在“中級 Swing”教程中)。
  • 它為所有元件提供了繪制的基礎架構 —— 一些友善進行元件定制的東西(同樣,在“中級 Swing”中,有關于這個主題的更多資訊)。
  • 它知道如何處理所有的鍵盤按鍵。是以類隻需要偵聽特定的鍵。
  • 它包含 add() 方法,可以添加其他 JComponent。換種方式來看,可以把任意 Swing 元件添加到其他任何 Swing 元件,進而構造嵌套元件(例如,JPanel 包含 JButton,甚至包含一些古怪的組合,例如 JMenu 包含 JButton)。

簡單的swing小部件

JLabel

Swing 庫中最基礎的元件是 JLabel。它所做的正是您所期望的:呆在那兒,看起來很漂亮,描述其他元件。下圖顯示了的 JLabel 實際應用:

JLabel

不太吸引人,但是仍然有用。實際上,在整個應用程式中,不僅把 JLabel 用作文本描述,還将它用作圖檔描述。每當在 Swing 應用程式中看到圖檔的時候,它就有可能是 JLabel。JLabel 對于 Swing 初學者來說沒有許多意料之外的方法。基本的方法包括設定文本、圖檔、對齊以及标簽描述的其他元件:

  • get/setText(): 擷取/設定标簽的文本。
  • get/seticon(): 擷取/設定标簽的圖檔。
  • get/setHorizontalAlignment(): 擷取/設定文本的水準位置。
  • get/setVerticalAlignment(): 擷取/設定文本的垂直位置。
  • get/setDisplayedMnemonic(): 擷取/設定标簽的通路鍵(下劃線文字)。
  • get/setLableFor(): 擷取/設定這個标簽附着的元件,是以當使用者按下 Alt+通路鍵時,焦點轉移到指定的元件。

 JButton

Swing 中的基本動作元件 JButton,是與每個視窗中都能看到的 OK 和 Cancel 一樣的按鈕;這些按鈕所做的正是您希望它們做的工作 —— 在單擊它們之後,将發生一些事情。到底會發生什麼呢?您必須定義發生的内容(請參閱 事件,以獲得更多資訊)。一個 JButton 執行個體看起來如下所示:

JButton

用來改變 JButton 屬性的方法與 JLabel 的方法類似(您可能發現,在大多數 Swing 元件中,這些屬性都類似)。它們控制文本、圖檔和方向:

  • get/setText(): 擷取/設定标簽的文本。
  • get/seticon(): 擷取/設定标簽的圖檔。
  • get/setHorizontalAlignment(): 擷取/設定文本的水準位置。
  • get/setVerticalAlignment(): 擷取/設定文本的垂直位置。
  • get/setDisplayedMnemonic(): 擷取/設定通路鍵(下劃線字元),與 Alt 按鈕組合時,造成按鈕單擊。

除了這些方法,我還要介紹 JButton 包含的另外一組方法。這些方法利用了按鈕的所有不同狀态。狀态是對元件進行描述的一個屬性,通常采用真/假設定。在 JButton 中,可以包含以下可能狀态:活動/不活動、選中/沒選中、滑鼠經過/滑鼠離開、按下/沒按下,等等。另外,可以組合這些狀态,例如按鈕可以在滑鼠經過的同時被選中。現在您可能會問自己用這些狀态到底要做什麼。作為示例,請看看您的浏覽器上的後退按鈕。請注意在滑鼠經過它的時候,圖檔是如何變化的,在按下該按鈕時,圖檔又是如何變化的。這個按鈕利用了不同的狀态。每個狀态采用不同的圖檔,這是提示使用者互動正在進行的一種普遍并且有效的方式。JButton 上的狀态方法是:

  • get/setDisabledIcon()
  • get/setDisableSelectedIcon()
  • get/setIcon()
  • get/setPressedIcon()
  • get/setRolloverIcon()
  • get/setRolloverSelectedIcon()
  • get/setSelectedIcon()

JTextField

Swing 中的基本文本元件是 JTextField,它允許使用者在 UI 中輸入文本。我肯定您熟悉文本字段:要掌握本教程,則必須使用一個文本字段輸入使用者名和密碼。您輸入文本、删除文本、選中文本、把文字四處移動 —— Swing 替您負責所有這些工作。作為 UI 開發人員,利用 JJTextField 時,實際上并不需要做什麼。

在任何情況下,這是 JTextField 實際使用時看起來的樣子:

JTextField

在處理 JTextField 時,隻需要關注一個方法 —— 這應當是很明顯的,這個方法就是設定文本的方法:

get/setText()

,用于擷取/設定 JTextField 中的文本。

JFrame

迄今為止,我介紹了 Swing 的三個基本構造塊:标簽、按鈕和文本字段;但是現在需要個地方放它們,希望使用者知道如何處理它們。JFrame 類就是做這個的——它是一個容器,允許您把其他元件添加到它裡面,把它們組織起來,并把它們呈現給使用者。它有許多其他好處,但是我認為先看看它的圖檔最簡單:

JFrame

JFrame 實際上不僅僅讓您把元件放入其中并呈現給使用者。比起它表面上的簡單性,它實際上是 Swing 包中最複雜的元件。為了最大程度地簡化元件,在獨立于作業系統的 Swing 元件與實際運作這些元件的作業系統之間,JFrame 起着橋梁的作用。JFrame 在本機作業系統中是以視窗的形式注冊的,這麼做之後,就可以得到許多熟悉的作業系統視窗的特性:最小化/最大化、改變大小、移動。但是對于本教程的目标來說,把 JFrame 當作放置元件的調色闆就足夠了。可以在 JFrame 上調用的一些修改屬性的方法是:

  • get/setTitle(): 擷取/設定幀的标題。
  • get/setState(): 擷取/設定幀的最小化、最大化等狀态。
  • is/setVisible(): 擷取/設定幀的可視狀态,換句話說,是否在螢幕上顯示。
  • get/setLocation(): 擷取/設定幀在螢幕上應當出現的位置。
  • get/setsize(): 擷取/設定幀的大小。
  • add(): 将元件添加到幀中。

簡單應用程式

就像所有的“x 入門”教程一樣,本教程也包含必不可少的 HelloWorld 示範。但這個示例不僅對觀察 Swing 應用程式如何工作有用,還對確定設定正确很有用。一旦使這個簡單的應用程式能夠成功運作,那麼之後的每個示例也将能夠運作。下圖顯示了完成後的示例:

HelloWorld 示例

第一步是建立類。将元件放在 JFrame 上的 Swing 應用程式需要繼承JFrame 類,如下所示:

這樣做之後,就得到上面描述的所有 JFrame 屬性,最重要的是作業系統對視窗的本機支援。下一步是把元件放在螢幕上。在這個示例中,使用了一個 null 布局。在教程的後面部分,您将學到更多關于布局和布局管理器的内容。但對于這個示例,可以用數字表示 JFrame 上的像素位置:

現在元件都放在了 JFrame 上,并且需要在螢幕上顯示 JFrame,并讓應用程式可以運作。就像在所有的 Java 應用程式中一樣,必須添加一個 main 方法,才能讓 Swing 應用程式運作。在這個 main 方法中,隻需要建立 HelloWorld 應用程式對象,然後調用其setVisible()即可:

完成了!這就是建立應用程式的所有過程。

完整代碼如下:

package cn.edu.jnu.www;

import javax.swing.*;

import javax.swing.event.*;

import java.awt.*;

import java.awt.event.*;

public class HelloWorld extends JFrame{

 private JLabel jLabel;

 private JTextField jTextField;

 private JButton jButton;

public HelloWorld()

{

   super();

   this.setSize(300, 200);

   this.getContentPane().setLayout(null);

   this.add(getJLabel(), null);

   this.add(getJTextField(), null);

   this.add(getJButton(), null);

   this.setTitle("HelloWorld");

}

private javax.swing.JLabel getJLabel() {

   if(jLabel == null) {

      jLabel = new javax.swing.JLabel();

      jLabel.setBounds(34, 49, 53, 18);

      jLabel.setText("Name:");

   }

   return jLabel;

}

private javax.swing.JTextField getJTextField() {

   if(jTextField == null) {

      jTextField = new javax.swing.JTextField();

      jTextField.setBounds(96, 49, 160, 20);

   }

   return jTextField;

}

private javax.swing.JButton getJButton() {

   if(jButton == null) {

      jButton = new javax.swing.JButton();

      jButton.setBounds(103, 110, 71, 27);

      jButton.setText("OK");

   }

   return jButton;

}

public static void main(String[] args)

{

   HelloWorld w = new HelloWorld();

   w.setVisible(true);

}

}

附加的swing小部件(上)

JComboBox

在這一節中,我将介紹 Swing 庫中的其他全部元件、如何使用它們、它們看起來是什麼樣的,等等,這部分内容應當讓您更好地了解 Swing 為 UI 開發人員提供了什麼。

我們從 JComboBox 開始介紹。組合框與下拉選擇相似,差別在于使用組合框時使用者可以不從清單中選擇項目,還可以選擇一個(而且隻有一個)項目。在某些版本的組合框中,還可以輸入自己的選擇。浏覽器的位址欄就是一個示例:它是一個允許輸入自己選項的組合框。以下是 JComboBox 在 Swing 中看起來的樣子:

JComboBox

JComboBox 的重要函數包括 JComboBox 包含的資料。需要有一種方法來設定 JComboBox 中的資料、修改資料、在使用者選擇時得到使用者的選擇。可以使用以下 JComboBox 方法:

  • addItem()

    :添加一個項目到 JComboBox.
  • get/setSelectedIndex()

    :擷取/設定 JComboBox 中選中項目的索引。
  • get/setSelectedItem()

    :擷取/設定選中的對象。
  • removeAllItems()

    :從 JComboBox 删除所有對象。
  • remoteItem()

    :從 JComboBox 删除特定對象。

JTextField

JTextField 的一個細微變化是 JPasswordField,它允許您隐藏在文本字段區域中顯示的字元。畢竟,在您輸入密碼的時候,如果每個人都能看到,那可沒什麼好處?可能根本就不好,而且在私人資料如此脆弱的今天,您需要所有能夠得到的幫助。以下是 JPasswordField 在 Swing 中看起來的樣子:

JPasswordField

JPasswordField 上額外的“安全性”方法對 JTextField 的行為做了輕微改變,是以不能閱讀文本:

  • get/setEchoChar()

    :擷取/設定每次字元輸入時在 JPasswordField 中顯示的字元。在擷取密碼時,不會傳回“回聲”,而是傳回實際的字元。
  • getText()

    : 不應當 使用這個函數,因為它會帶來可能的安全問題(String 會儲存在記憶體中,可能的堆棧轉儲會暴露密碼)。
  • getPassword()

    :這是從 JPasswordField 中獲得密碼的恰當方法,因為它傳回一個包含密碼的

    char[]

    。為了保證恰當的安全性,數組應當被清為 0,以確定它不會保留在記憶體中。

 JCheckBox/JRadioButton

JCheckBox 和 JRadioButton 元件向使用者呈現選項,通常采用多選的格式。差別是什麼?從實踐的角度來說,它們沒有那麼不同。它們的行為方式相同。但是,在一般的 UI 實踐中,它們有細微差異:JRadioButton 通常組合在一起,向使用者呈現帶有必選答案的問題,而且這些答案具有強制性(這意味着問題隻能有一個答案)。JRadioButton 的行為保證了這個用法。一旦選擇了JRadioButton,就不能取消對它的選擇,除非選擇了在同一組中的另外一個單選鈕。從效果上看,這就保證了選項的惟一和必選。JCheckBox 的不同在于,允許随機地選擇/取消除選擇,并允許為問題選擇多個答案。

這裡是個示例。問題“您是男孩還是女孩!”有兩個惟一答案選項“男孩”或“女孩”。使用者必須選擇一個,不能同時選中。另一方面,問題“您的習慣是什麼?”的答案有“跑步”、“睡覺”或“閱讀”,不應當隻允許為此問題選擇一個答案,因為人們可能有不止一個習慣。

把這些 JCheckBoxe 或 JRadioButton 捆綁成一組的類是

ButtonGroup

類。它允許把選項組織在一起(例如“男孩”和“女孩”),這樣,其中一個被選擇時,另外一個就自動取消選擇。

以下是 JCheckBox 和 JRadioButton 在 Swing 中看起來的樣子:

JCheckBox 和 JRadioButton

需要記住的重要的 ButtonGroup 方法是:

  • add()

    :添加 JCheckBox 或 JRadioButton 到 ButtonGroup。
  • getElements()

    :獲得 ButtonGroup 中的全部元件,允許對它們進行疊代,找到其中選中的那個。

 JMenu/JMenuItem/JMenuBar

JMenu、JMenuItem 和 JMenuBar 元件是在 JFrame 中開發菜單系統的主要構造塊。任何菜單系統的基礎都是 JMenuBar。它平淡而乏味,但卻是必需的,因為每個 JMenu 和 JMenuItem 都要用它建構。要用

setJMenuBar()

方法把 JMenuBar 附着到 JFrame。一旦将它附加到 JFrame 中,就可以添加所有想要的菜單、子菜單和菜單項。

JMenu/JMenuItem 的差別看起來可能很明顯,但實際上,在幕後看起來并不像表面那樣。看看類的類層次結構,就知道

JMenu

JMenuItem

的子類。但是,在表面上,它們是有差別的:用 JMenu 包含其他 JMenuItem 和 JMenu;JMenuItem 在選中時觸發操作。

JMenuItem 也支援快捷鍵的概念。與您用過的大多數應用程式一樣,Swing 應用程式允許您按下 Ctrl+(某個鍵)來觸發一個操作,就像選中菜單鍵本身一樣。想想用來剪切和粘貼的快捷鍵 Ctrl+X 和 Ctrl+V。

除此之外,JMenu 和 JMenuItem 都支援通路鍵。用 Alt 鍵與某個字母關聯,模拟菜單本身的選擇(例如,在 Windows 中按下 Alt+F,然後按下 Alt+x 就可以關閉應用程式)。

以下是包含 JMenu 和 JMenuItem 的 JMenuBar 在 Swing 中的樣子:

JMenuBar、JMenu 和 JMenuItem

這些類需要的重要方法是:

  • JMenuItem and JMenu:
    • get/setAccelerator()

      :擷取/設定用作快捷鍵的 Ctrl+鍵。
    • get/setText()

      :擷取/設定菜單的文本。
    • get/setIcon()

      :擷取/設定菜單使用的圖檔。
  • JMenu 專用:
    • add()

      :添加另外一個 JMenu 或 JMenuItem 到 JMenu(建立嵌套菜單)。

 JSlider

在應用程式中 JSlider 支援數值變化。它是一種迅速而簡單的方式,不僅能讓使用者以可視形式獲得他們目前選擇的回報,還能得到可以接受的值的範圍。想像一下這種情況:可以提供一個文本字段,允許使用者輸入值,但是這樣做就帶來了額外的麻煩,要確定輸入的值是數字,還要確定數字元合要求的數值範圍。例如,如果有一個金融 Web 站點,它向您提問要在股票上投資的百分比,那麼您不得不檢查在文本字段中輸入的值,以確定它們是數字,而且在 0 到 100 之間。如果換用 JSlider,那麼就可以確定選擇的是指定範圍内的數字。

在 Swing 中,JSlider 看起來如下所示:

JSlider

JSlider 中的重要方法是:

  • get/setMinimum()

    :擷取/設定可以選擇的最小值。
  • get/setMaximum()

    :擷取/設定可以選擇的最大值。
  • get/setOrientation()

    :擷取/設定 JSlider 是上/下還是左/右滾動條。
  • get/setValue()

    :擷取/設定 JSlider 的初始值。

 JSlider

與 JSlider 非常像,可以用 JSpinner 允許使用者選擇一個整數值。JSlider 的一個主要優勢就是比 JSlider 的空間緊湊。但是,它的不足就是無法友善地設定其邊界。

但是,兩個元件之間的比較僅此而已。JSpinner 更加靈活,可以用來在任意組的值之間進行選擇。除了在數字間選擇,它還可以用來在日期、名稱、顔色和任何事之間進行選擇。這使 JSpinner 極為強大,允許您提供其中隻包含預定義的選擇的元件。使用這種方式,它與 JComboBox 類似,但是它們的應用不能互換。隻應把 JSpinner 用在邏輯上連續的選擇 —— 數字和日期是最合邏輯的選擇。而另一方面,在呈現看起來随機的選擇并且選擇之間沒有連接配接的時候,JComboBox 是更好的選擇。

JSpinner 看起來如下所示:

JSpinner

重要方法是:

  • get/setValue()

    :擷取/設定 JSpinner 的初始值,在基本執行個體中,需要是整數。
  • getNextValue()

    :擷取按下上箭頭按鈕之後應當選中的下一個值。
  • getPreviousValue()

    :擷取按下下箭頭按鈕之後應當選中的前一個值。

 JToolBar

JToolBar 充當其他元件(JButton、JComboBoxe 等)的調色闆,共同構成您在大多數應用程式中熟悉的工具欄。工具欄允許程式把常用的指令放在可以迅速發現的位置,并把它們以常用指令組的形式組合在一起。一般(但不總是這樣)情況下,工具欄按鈕在菜單欄中會有對應的指令。雖然這不是必需的,但已經變成了一種公共實踐,您也應當試着這麼做。

JToolBar 也提供了您在其他工具欄中看到過的其他功能:“浮動”的能力(也就是成為主幀頂部獨立的幀)。

下圖顯示了一個非浮動 JToolBar:

非浮動 JToolBar

對于 JToolBar,要記住的重要方法是:

is/setFloatable()

,它擷取/設定 JToolBar 是否可以浮動。

 JToolTip

您可能到處都看到過 JToolTip,但是從來不知道它們叫什麼。它們就像您鞋帶上的塑膠部件 —— 到處都有,但是您就是不知道它們正确的名字(如果您想知道,那麼可以叫它們 金屬箍)。JToolTip 就是您将滑鼠停留在某個東西上面的時候彈出來的小“泡泡”。它們在應用程式中可能非常有用,可以為難用的項目提供幫助、擴充資訊,甚至在擁擠的 UI 中顯示某個項目的完整文本。在 Swing 中,可以通過把滑鼠放在某個元件上的特定時間來觸發它們;它們通常在滑鼠處于不活動狀态大約 1 秒鐘之後顯示。隻要滑鼠還停留在那個元件上,它們就保持可見。

JToolTip 的重要部分是它的易用性。

setToolTip()

方法是

JComponent

類中的一個方法,這意味着每個 Swing 元件都能有一個與之關聯的工具提示。雖然

JToolTip

本身也是一個 Swing 類,但目前,對于您的需要,它确實沒有提供更多功能,而且本身也不該被建立。可以通過調用 JComponent 的

setToolTip()

函數通路和使用它。

以下是 JToolTip 看起來的樣子:

A JToolTip

附加的swing小部件(下)

JOptionPane

JOptionPane

是在 Swing 中類似“快捷方式”的東西。通常,作為 UI 開發人員,您需要向使用者呈現快速資訊,讓使用者了解錯誤和資訊。甚至可能想得到一些快速資料,例如名稱或數字。在 Swing 中,

JOptionPane

類為這些東西提供了快捷方式,但這并不是它必須完成的任務。不需要讓每個開發人員重頭開始重複相同的工作,Swing 已經提供了這個基本的但很有用的類,為 UI 開發人員提供了擷取和接收簡單消息的簡易方法。

以下是一個 JOptionPane:

JOptionPane

使用 JOptionPane 時有點麻煩的是可以使用的全部選項。雖然簡單,但是它仍然提供了大量選項,這些選項有可能造成混淆。學習 JOptionPane 的最好方法就是使用它;編寫代碼,觀察彈出的是什麼。這個元件幾乎可以讓您修改它的每一方面:幀标題、消息本身、顯示的圖示、按鈕選項,以及是否需要文本響應。因為有太多的可能性,無法在本教程中一一列舉它們,是以您最好是通路 JOptionPane 的 API 頁面,檢視它的衆多可能性。

 JTextArea

JTextArea 比 JTextField 更進了一步。JTextField 被局限在一行文本中,而 JTextArea 擴充了這個能力,支援多行文本。可以把它想像成一個空白頁,您可以在其中的任意地方進行輸入。正如您可能猜到的,JTextArea 包含許多與 JTextField 相同的功能,畢竟,它們實際上是相同的元件。但是 JTextArea 提供了一些額外的重要功能,可以把它差別開。這些功能包括單詞自動換行的能力(即把長文本自動換行到下一行,而不是将單詞從中斷開)、對文本自動換行的能力(即把長的文本行移動到下一行,而不是建立一個需要水準滾動條的非常長的行)。

Swing 中的 JTextArea 看起來就像您期望的那樣:

A JTextArea

支援行和單詞的自動換行的重要方法是:

  • is/setLineWrap()

    :設定在行過長的時候是否要自動換行。
  • is/setWrapStyleWord()

    :設定在單詞過長的時候是否要把長單詞移到下一行。

 JScrollPane

上面的示例構造完成之後,假設 JTextArea 包含太多文本,而給定的空間中容納不下,那這該怎麼辦?如果您以為會自動出現滾動條,那麼很不幸,您錯了。JScrollPane 添補了這個空白,為 Swing 元件提供了處理所有與滾動條相關的動作。是以雖然為每個需要的元件提供滾動塊可能有些痛苦,但是一旦添加了它,它就會自動處理每件事,包括在需要的時候隐藏/顯示滾動條。

除了用需要自動換行的元件建立 JScrollPane 之外,不必直接處理它。根據上面的示例,用 JTextArea 調用 JScrollPane 的構造函數,這為 JTextArea 建立了在文本過長時滾動的能力:

更新後的示例看起來如下所示:

JScrollPane 示例

JScrollPane 也公開了它将建立的兩個 JScrollBar。這些 JScrollBar 元件也包含一些方法,可以用這些方法來修改元件的行為(雖然它們不在本教程的範圍之内)。

使用 JScrollPane 需要的方法是:

  • getHorizontalScrollBar()

    :傳回水準的 JScrollBar 元件。
  • getVerticalScrollBar():

    傳回垂直的 JScrollBar 元件.
  • get/setHorizontalScrollBarPolicy()

    :這個“政策”可以是以下三個之一:Always、Never 或 As Needed。
  • get/setVerticalScrollBarPolicy()

    :與水準函數相同。

JList

JList 是一個有用的元件,用于向使用者呈現許多選擇。可以把它當作 JComboBox 的擴充。JList 提供了更多選擇,并添加了多選的能力。在 JList 與 JComboBox 之間進行選擇通常取決于以下兩個特性:如果需要多選,或者選擇的選項超過 15 個(雖然這個數字并不是通用規則),那麼就應當選擇 JList。

應用将 JList 與 JScrollPane 結合使用,就像上面示範的那樣,因為它能夠呈現比它的空間所能容納的更多的選項。

JList 包含選擇模型的概念(在 JTable 中也會看到),在這裡,可以設定 JList 接受不同類型的選擇。這些類型是:單一選擇(隻能選擇一項)、單一間隔選擇(隻能選擇相鄰選項),以及任意多項或者多項間隔選擇(可以選擇任意數量、任意組合的選擇)。

JList 是第一個我稱為 “複雜元件” 的元件,該複雜元件還包含 JTable 和 JTree,它們支援大量的定制變化,其中包括改變 UI 的表現方式、處理資料的方式。因為本教程隻是想介紹基礎知識,是以我不想深入這些更進階的功能,但是在使用這些元件時有件事需要記住 —— 它們帶來的挑戰要比目前為止介紹過的所有元件都大。

JList 在 Swing 中看起來如下所示:

JList

JList 中有許多處理資料的函數,而且根據我的說法,這些也隻不過是使用 JList 的細節的皮毛而已。以下是一些基本方法:

  • get/setSelectedIndex()

    :擷取/設定清單中選中的行;在多選擇清單的情況下,傳回一個

    int[]

  • get/setSelectionMode()

    :與上面解釋的一樣,擷取/設定選擇模式,模式有:單一、單一間隔和多選間隔。
  • setListData()

    :設定在 JList 中使用的資料。
  • get/setSelectedValue()

    :獲得選中的對象(與選中行号對應)。

 JTable

在考慮 JTable 時,請想像一下一個 Excel 工作表,這樣就可以對 JTable 在 Swing 中的作用有一個清晰的印象。它與工作表共享許多相同的特征:單元格、行、列、移動列、隐藏列等。JTable 把 JList 的想法更進了一步。它不是在一列中顯示資料,而是在多列中顯示資料。讓我們以人為例。JList 隻能顯示人的一個屬性 —— 例如他或她的名字。而 JTable 就能夠顯示多個屬性 —— 名字、年齡、位址,等等。JTable 是支援提供資料的大多數資訊的 Swing 元件。

不幸的是,作為代價,JTable 也是最難對付的 Swing 元件。許多 UI 開發人員都為了學習 JTable 的每個細節而頭痛。在這裡,我希望我把能把您解救出來,隻用您的 JTable 知識處理問題。

許多 JList 中的概念也擴充到了 JTable,其中包括不同的選擇間隔的概念。但是 JList 中一列的概念變成了 JTable 的單元格的概念。這意味着在 JTable 中進行選擇時會有不同的方式,例如列、行或者一個單元格。

在 Swing 中,JTable 看起來如下所示:

JTable

最後,JTable 的大多數函數都超出本教程的範圍;“中級 Swing”會深入這個複雜元件的更多細節。

 JTree

JTree 是另外一個複雜元件,它不像 JTable 那樣難用,但是也不像 JList 那麼容易。使用 JTree 時麻煩的部分是它要求的資料模型。

JTree 的功能來自樹的概念,樹有分支和葉子。您在 Windows 中使用 IE 浏覽器時,可能非常熟悉這個概念 —— 可以展開和折疊分支,顯示可以選擇和取消選擇的不同葉子。

您很有可能發現樹在應用程式中不像表格或清單那樣有用,是以在 Internet 上沒有許多有幫助的這方面的示例。實際上,像 JTable 一樣,JTree 沒有什麼入門級的功能。如果決定使用 JTree,那麼立即就可以達到中級水準,當然還必須學習随之而來的概念。是以,示例應用程式沒有介紹 JTree,是以也很不幸,不管是入門教程還是中級教程,都沒有涉及這個不太流行的元件。

但是,樹有一些時候是符合需求的合理的 UI 元件。檔案/目錄系統就是一個示例(就像在 IE 浏覽器中那樣),而且當資料采取層次結構的時候,也就是說資料采用樹的形式的時候,JTree 就是最佳元件。

在 Swing 中,JTree 看起來如下所示:

JTree

Swing概念

布局、模型和事件

既然您已經知道了大多數(肯定不是全部)可以用來制作 UI 的元件,那麼就必須實際用它們做些什麼。您不能隻是随意地把它們放在螢幕上,然後就指望它們立即就能工作。您必須把它們放在特定的點上,對它們的互動作出反應,然後根據互動更新它們,用資料填充它們。要填滿 UI 知識的這片空白,還需要更多地學習 UI 的其他重要部分。

是以,讓我們來研究以下内容:

  • 布局:Swing 包括許多布局,布局也是類,負責處理元件在應用程式中的擺放位置,以及在應用程式改變尺寸或者删除、添加元件時對元件進行相應處理。
  • 事件:您需要對按下按鈕、單擊滑鼠和使用者在 UI 上能做的每件事進行響應。想像一下,如果不能響應會發生什麼 —— 使用者單擊之後,什麼變化也沒有。
  • 模型: 對于更進階的元件(清單、表格和樹),以及一些像 JComboBox 這樣的更容易的元件來說,模型是處理資料最有效的途徑。它們把大部分處理資料的工作從實際的元件本身撤出來(請回想一下前面讨論的 MVC),并提供了一個公共資料對象類(例如

    Vector

    ArrayList

    )的包裝器。

簡單布局

就像在前面提到過的,布局替您處理元件在應用程式中的擺放。您的第一個問題可能是“為什麼不能用像素告訴它應當在什麼地方呢?”是的,您可以這樣做,但是在視窗改變大小的時候,或者更糟一些情況,即使用者改變其螢幕的分辨率的時候,亦或在有人想在其他作業系統上試用應用程式的時候,您立刻就會遇到麻煩。布局管理器把這些擔心一掃而空。不是每個人都用相同的設定,是以布局管理器會建立“相對”布局,允許您指定元件相對于其他元件的擺放方式,決定事物改變尺寸的方式。這是好的部分:比聽起來更容易。隻要調用

setLayout(yourLayout)

設定布局管理器即可。後面對

add()

的調用可以将元件添加到容器中,并讓布局管理器負責将它放在應當的位置上。

目前在 Swing 中包含了大量布局;看起來好象每次釋出都會有一個新布局負責不同的目的。但是,有些經過實踐檢驗的布局一直存在,而且會永遠存在,我指的是永遠 —— 因為從 1995 年 Java 語言的第一個發行版開始,就有這些布局。這些布局是:FlowLayout、GridLayout 和 BorderLayout。

FlowLayout 從左到右安排元件。當空間不足時,就移到下一行。它是使用起來最簡單的布局,是以,也就是能力最弱的布局:

FlowLayout 執行個體

GridLayout 就像您想像的那樣工作:它允許指定行和列的數量,然後在添加元件時把元件放在這些單元格中:

GridLayout 執行個體

即使 Swing 中添加了許多新的布局管理器,BorderLayout 仍然是其中非常有用的一個。即使有經驗的 UI 開發人員也經常使用 BorderLayout。它使用東、南、西、北、中的概念在螢幕上放置元件:

BorderLayout 執行個體

 GridBagLayout

雖然上面的示例對于簡單的布局來說很好,但是更進階的 UI 需要更進階的布局管理器。這是 GridBagLayout 發揮作用的地方。不幸的是,使用它的時候極易混淆、極為困難,每個曾經用過它的人都會同意這點。我也不能反對;但是除了它的困難之外,它可能是用 Swing 内置的布局管理器建立漂亮 UI 的最好方式。

以下是我的第一個小建議:在最新版的 Eclipse 中,有内置的可視化建構器,這個個小建議可以自動根據每個螢幕的需要來建構必需的 GridBagLayout 代碼。請使用這個功能!它會節約無數為了讓數字正确而浪費的時間。是以在我用這一節解釋 GridBagLayout 如何工作、如何調整它才能讓它做得最好時,建議您去找一個可視化建構器并生成代碼。它會節約您的工作時間

事件

最後,我們來到 Swing 最重要的一部分:處理事件,對 UI 的互動作出反應。Swing 用事件/偵聽器模型處理事件。這個模型的工作方式是:允許某個類登記到某個元件的某個事件上。登記到事件的這個類叫做偵聽器,因為它等候元件的事件發生,而且在事件發生時采取行動。元件本身知道如何“激活”事件(即,知道它能生成的互動類型,以及如何讓偵聽器知道這個互動什麼時候發生)。元件與包含有關互動資訊的事件和類針對互動進行通信。

把技術方面的空談放在一邊,我們來看幾個 Swing 中事件的執行個體。首先從最簡單的示例開始,即一個 JButton,按下它的時候,會在控制台上輸出“Hello”。

JButton 知道它什麼時候被按下;這是在内部處理的,不需要代碼處理它。但是,偵聽器需要進行登記,以接收來自 JButton 的事件,這樣您才能輸出“Hello”。

listener

類通過實作

listener

接口然後調用 JButton 上的

addActionListener()

做到這一點:

JList 也用類似的方式工作。當有人在 JList 中選中什麼時,您可能想把選中的對象輸出到控制台上:

從這兩個示例,您應當能夠了解事件/偵聽器模型在 Swing 中如何工作了。實際上,Swing 中的每個互動都是以這種方式處理的,是以通過了解這個模型,您就立即能夠了解在 Swing 中如何處理每個事件,以及如何對使用者可能抛給您的任何互動做反應了。

模型

現在,您應當了解了 Java 的集合(Collection),這是一組處理資料的 Java 類。這些類包括

ArrayList

HashMap

Set

。大多數應用程式在反複處理資料時,經常用這些類。但是,當需要在 UI 中使用這些資料類時,出現了一個限制。UI 不知道如何顯示它們。請先想一分鐘。如果有一個

JList

和一個某種資料對象(例如

Person

對象)的

ArrayList

JList

怎樣才能知道要顯示什麼?它是要顯示某個人的名字,還是連名帶姓一起顯示?

這就是模型的概念發揮作用的地方了。雖然模型這個術語表達的範圍更大,但是在本教程的示例中,我用 UI 模型這個術語描述元件用來顯示資料的類。

在 Swing 中每個處理集合資料的的元件都采用模型的概念,而且這也是使用和操縱資料的首選方法。它清晰地把 UI 的工作與底層資料分開(請回想 MVC 示例)。模型工作的機制是向元件描述如何顯示集合資料。我說的“描述”指的是什麼呢?每個元件需要的描述略有不同:

  • JComboBox 要求其模型告訴它把什麼文本作為選項顯示,以及有多少選項。
  • JSpinner 要求其模型告訴它顯示什麼文本,前一個和下一個選擇是什麼。
  • JList 也要求其模型告訴它把什麼文本作為選項顯示,存在多少選項。
  • JTable 要求的更多:它要求模型告訴它存在多少列和多少行,列名稱、每列的類以及在每個單元格中顯示什麼文本。
  • JTree 要求它的模型告訴它整個樹的根節點、父節點和子節點。

您可能會問:為什麼要做這麼些工作?為什麼要把這些功能分開?請想像以下場景:您有一個複雜的 JTable,有許多列資料,您在許多不同的螢幕上使用這個表格。如果您突然決定删除某個列,那麼怎麼做會更容易呢?修改您使用的每個 JTable 執行個體中的代碼?還是建立一個可以在每個 JTable 執行個體中使用的模型類,然後隻修改這一個模型類呢?顯然,所做的修改越少越好。

模型示例

我們來看看模型如何工作,在一個簡單的 JComboBox 示例中使用模型。在 JComboBox 前面的示範中,我介紹了如何調用

setItem()

向資料中添加項目。雖然對于簡單的示範,這樣做可以接受,但是在實際的應用程式中很少這麼用。畢竟,在有 25 個選項,而且選項不斷變化的時候,您還真的想每次都調用

addItem()

25 次對這些選項進行疊代嗎?當然不是。

JComboBox 包含一個方法調用

setModel()

,它接受

ComboBoxModel

類的執行個體。應當用這個方法代替

addItem()

方法來建立 JComboBox 中的資料。

假設有一個

ArrayList

,其中使用字母表作為其資料(“A”、“B”、“C” ,等等):

采用模型時更好的地方是:您可以反複重用它。例如,假設 JComboBox 的資料需要從字母表變成 1 到27 的數字。那麼隻用一行就可以實作這個變化:用新的資料

List

添加 JComboBox,不需要使用額外的代碼:

模型在 Swing 中是非常有好處的特性,因為它們提供了代碼重用功能,而且使資料處理更加容易。更常見的應用是在大型應用程式中,伺服器端開發人員建立和檢索資料,并把資料傳遞給 UI 開發人員。如何處理這些資料和正确地顯示它們,取決于 UI 開發人員,而模型就是實作這項任務的工具。

Swing入門(一) (2009-04-21 00:02:20)

标簽:it  分類:Awt/Swing學習

(轉自http://terrificwanjun.bokee.com)

package cn.edu.jnu.www;

import javax.swing.*;

import javax.swing.event.*;

import java.awt.*;

import java.awt.event.*;

public class test {

 public static void main(String[] args) {

  JFrame a=new JFrame("中繼資料庫系統");

  Container c=new  Container();

  //Swing更強調容器的概念,一般不允許之間将元件放置到頂層容器中

  //而是放在容器架構中,而awt則是直接放的

  a.setSize(200,200);

  a.setLocation(100, 200);

  a.setLayout(new BorderLayout());

  JButton b=new JButton("GO");

  c=a.getContentPane();

  c.add(b,BorderLayout.SOUTH);

  a.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

  a.setVisible(true);

 }

}

Swing學習(二) (2009-04-21 00:03:22)

标簽:it  分類:Awt/Swing學習

(轉自http://terrificwanjun.bokee.com)

  接觸java幾天,自己試着做了第一個java程式,其實隻是一個簡單的對話框視窗,不過做起還是費了半天功夫,主要是對一些文法還不太熟悉,幸虧有CSDN上的朋友相助,問題得以解決.

import java.awt.*;

import javax.swing.*;

public void class AboutDialog extends JDialog {              //這裡誤用void,傳回空值     

  public AboutDialog() {

   this.setTitle("About");                                                    //窗體标題顯示

           this.setSize(320, 200);                                                //窗體的大小

       JLabel about = new JLabel("關于:JAVA的一個視窗 :) ");             //對話框内容

        about.setHorizontalAlignment(SwingConstants.CENTER);     //内容顯示在視窗的中央

       this.getContentPane().add(about, BorderLayout.CENTER);

  }

  public static void main(String[] args) throws HeadlessException {

          AboutDialog kk = new  AboutDialog() ;

         kk.setVisible(true);                                                                             //原來的show()顯示已過時

         kk.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);       

 }

}

上面誤用void生成的結果,有興趣的朋友可以試試.另外查了一下J2SE API,才知道show( )方法已經被setvisible( )取代.

使用Frame建立窗體

在Awt中,Window類沒有邊界和菜單欄,是以不能直接使用Window類來建立窗體,必須使用Window類的子類Frame來建立,建立代碼為:

package cn.edu.jnu.www;

import java.awt.*;

import java.awt.event.*;

public class FrameTest {

 public static void main(String[] args) {

  // TODO 自動生成方法存根 

  Frame myFrame=new Frame("Hello");

  //Frame 是帶有标題和邊界的頂層視窗

  myFrame.setLocation(250, 150);

  //myFrame.setLayout(new BorderLayout(10,20));

  //設定窗體布局,BorderLayout裡面的兩個參數用指定的元件之間的水準間距構造一個邊界布局。

  //BorderLayout為JAVA中的預設窗體布局

  //myFrame.setLayout(new FlowLayout(FlowLayout.LEFT));

  //設定窗體布局為FlowLayout,對齊方式居左對齊

  //myFrame.setLayout(new GridLayout(3,2));

  //設定窗體布局為GridLayout,将窗體分為6塊,3行2列

  myFrame.setSize(300,400);

  Button myButton1=new Button("east");

  Button myButton2=new Button("south");

  Button myButton3=new Button("west");

  Button myButton4=new Button("north");

  Button myButton5=new Button("center");

  //myFrame.add(myButton1,BorderLayout.EAST);

  myFrame.add(myButton1,"East");

  //兩種方法都可以,但是要注意大小寫

  myFrame.add(myButton2,BorderLayout.SOUTH);

  myFrame.add(myButton3,BorderLayout.WEST);

  myFrame.add(myButton4,BorderLayout.NORTH);

  myFrame.add(myButton5,BorderLayout.CENTER);

  //myFrame.addWindowListener(new myWindowListener());

  //使用擴充卡的方法實作監聽器作用

  //myFrame.addWindowListener(new yourWindowListener());

  //使用匿名内部類的方法實作監聽器的功能,隻有含有擴充卡的事件才可以使用此方法

  myFrame.addWindowListener(new WindowAdapter(){

   public void windowClosing(WindowEvent e){

    System.exit(0);

   }

  });

  myFrame.setVisible(true);

  //myFrame.show();//eclipse 不建議使用show()方法

 }

}

//使用WindowAdapter擴充卡類來實作監聽器

zhua : http://blog.sina.com.cn/s/blog_43c4b6530100cywl.html

繼續閱讀