Swing組件提供了對組件周圍的邊框區域進行定制的功能。為了簡單,我們可以使用預定義的八個邊框,或者是我們可以創建自己的邊框。在本章中,我們將會了解如何最好的使用已存在邊框以及如何創建我們自己的邊框。
7.1 Some Basics on Woring with Borders
邊框是帶有標準的setBorder()與getBorder()屬性方法的JComponent屬性。所以,所有的JComponent子類的Swing組件都具有邊框。默認情況下,一個組件并沒有與其相關聯的自定義邊框。(JComponent的getBorder()方法返回null。)相反,組件顯示的默認邊框是依據當前的觀感對于其狀態最為合適的邊框。例如,對于JButton,對于每一個觀感特定不同的邊框,邊框可以表現為按下,未按下或是禁止。
盡管對于所有的組件初始的邊框屬性設置為null,我們可以通過調用JComponent的setBorder(Border newValue)方法來修改組件的邊框。一旦設置,修改的值就會覆蓋當前觀感的邊框,并且在組件的區域內繪制新邊框。如果在稍后的時候,我們希望將邊框重新設置為對于狀態與觀感合適的邊框,我們可以將邊框屬性修改為null,使用setBorder(null)并且調用組件的updateUI()方法。updateUI()方法會通知觀感重新設置邊框。如果我們沒有調用updateUI()方法,則組件將沒有邊框。
圖7-1顯示了一個JLabel周圍的各種邊框設置,通過文本標簽來標明邊框類型。如何創建不同的邊框將會在本章的稍后部分進行討論。
7.1.1 Exploring the Border Inteface
我們可以在javax.swing.border包中找到Border接口。這個接口構成了所有邊框類的基礎。這個接口直接由AbstractBorder類實現,這個類是所有預定義的Swing邊框類的父類:BevelBorder,CompoundBorder,EmptyBorder,EtchedBorder,LineBorder,MatteBorder,SoftBevelBorder以及TitledBorder。另外一個有趣的類就是BorderFactory類,我們可以在javax.swing包中找到這個類。這個類使用工廠設計模式來創建邊框,隱藏了實現細節,并且可以緩存各種選項來優化共同使用。
在這里顯示的Border接口由三個方法構成:paintBorder(),getBordernsets()以及isBorderOpaque()。這些方法會在后面的章節中進行描述。
paintBorder()
paintBorder()方法是這個接口的關鍵方法。其定義如下:
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
邊框實現的繪制是由這個方法完成的。通常,Border實現首先會詢問Insets維度,然后在外層區域的四個邊進行繪制,如圖7-2所示。如果邊框是不透明的,paintBorder()實現必須填充整個內部區域。如果一個邊框是不透明的,并沒有填充區域,那么這是一個bug并且需要修正。
列表7-1顯示了一個簡單的paintBorder()實現,這個實現使用比上部與下部略淺的顏色填充左邊與右邊。
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { Insets insets = getBorderInsets(c); Color color = c.getForeground(); Color brighterColor = color.brighter(); // Translate coordinate space g.translate(x, y); // Top g.setColor(color); g.fillRect(0, 0, width, insets.top); // Left g.setColor(brighterColor); g.fillRect(0, insets.top, insets.left, height-insets.top-insets.bottom); // Bottom g.setColor(color); g.fillRect(0, height-insets.bottom, width, insets.bottom); // Right g.setColor(brighterColor); g.fillRect(width-insets.right, insets.top, insets.right, height-insets.top-insets.bottom); // Translate coordinate space back g.translate(-x, -y); }
?
當創建我們自己的邊框時,我們將會經常發現我們自己在填充相同的非重疊矩形區域。Graphics的translate()方法簡化了繪制坐標的指定。無需轉換坐標,我們需要通過原始的(x,y)來偏移繪制。
注意:我們不能通過插入g.fillRect(x,y,width,height)來簡化,因為這會填充整個組件區域,而不是邊框區域。
getBorderInsets()
getBorderInsets()方法會返回在指定的組件c作為Insets對象的周圍繪制邊框所必須的空間。其定義如下:
public Insets getBorderInsets(Component c)
如圖7-2所示,這些內部區域定義了可以繪制邊框的合法區域。Component參數可以使得我們使用他的一些屬性來決定內部區域的尺寸。
isBorderOpaque()
邊框可以是不透明的或是透明的。isBorderOpaque()方法可以返回true或是false來表明邊框是哪種形式。其定義如下:
public boolean isBorderOpaque()
當這個方法返回true時,邊框需要是非透明的,填充其整個內部區域。當其返回false時,沒有繪制的區域將會保持邊框所在的組件的背景顏色。
7.1.2 Introducing BorderFactory
現在我們已經基本了解了Border接口是如何工作的,現在我們來了解一下作為簡單創建邊框方法的BorderFactory類。我們可以在javax.swing包中找到這個類,BorderFactory類提供了一系列的static方法來創建預定義的邊框。無需調用不同的邊框類的特定構造函數,通過這個工廠類我們幾乎可以創建所有的邊框。這個工廠類同時可以緩存一些邊框的創建從而避免多次重新創建經常使用的邊框。這個類的定義如下:
public class BorderFactory { public static Border createBevelBorder( int type); public static Border createBevelBorder( int type, Color highlight, Color shadow); public static Border createBevelBorder( int type, Color highlightOuter, Color highlightInner, Color shadowOuter, Color shadowInner); public static CompoundBorder createCompoundBorder(); public static public static Border createEmptyBorder(); public static Border createEmptyBorder( int top, int left, int bottom, int right); public static Border createEtchedBorder(); public static Border createEtchedBorder(Color highlight, Color shadow); public static Border createEtchedBorder( int type); public static Border createEtchedBorder( int type, Color highlight, Color shadow); public static Border createLineBorder(Color color); public static Border createLineBorder(Color color, int thickness); public static Border createLoweredBevelBorder(); public static MatteBorder createMatteBorder( int top, int left, int bottom, int right, Color color); public static MatteBorder createMatteBorder( int top, int left, int bottom, int right, Icon icon); public static Border createRaisedBevelBorder(); public static TitledBorder createTitledBorder(Border border); public static TitledBorder createTitledBorder(Border border, String title); public static TitledBorder createTitledBorder(Border border, String title, int justification, int position); public static TitledBorder createTitledBorder(Border border, String title, int justification, int position, Font font); public static TitledBorder createTitledBorder(Border border, String title, int justification, int position, Font font, Color color); public static TitledBorder createTitledBorder(String title); }
?
我們將會在描述特定的邊框類型的過程中描述這個類的不同方法。例如,要創建一個具有紅線的邊框,我們可以使用下面的語句,然后將這個邊框關聯到一個組件。
Border lineBorder = BorderFactory.createLineBorder(Color.RED);
7.1.3 Starting with AbstractBorder
在我們了解javax.swing.border包中單個的邊框之前,一個系統邊框需要獲得特別的關注:AbstractBorder。正如前面所提到的,AbstractBorder類是其他的預定義邊框的父類。
創建AbstractBorder
AbstractBorder有一個構造函數:
public AbstractBorder()
因為AbstractBorder是其他標準邊框的父類,這個構造函數實際是為其他邊框類自動調用的。
檢測AbstractBorder方法
AbstractBorder類提供了Border接口的三個方法實現。
public Insets getBorderInsets(Component c)
AbstractBorder的內部區域是零。每一個預定義的子類要重寫getBorderInsets()方法。
public boolean isBorderOpaque()
AbstractBorder的默認非透明屬性設置為false。這就意味著如果我們需要繪制類似點劃線的邊框,組件的背景將會是透明的。許多預定義的子類重寫了isBorderOpaque()方法。
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
AbstractBorder的繪制邊框是空的。所有的子類應該重寫這個方法來實際繪制一個邊框,也許除了EmptyBorder。
除了提供了Border方法的默認實現以外,AbstractBorder提供了我們可以利用的其他兩個功能,或者僅是允許系統使用。首先,還有另外一個需要兩個參數Component與Insets的getBorderInsets()方法:
public Insets getBorderInsets(Component c, Insets insets)
在這個方法版本中,并沒有創建并返回一個新的Insets對象,所傳遞的Insets對象首先被修改然后返回。使用這個方法可以避免每次需要查詢邊框內部區域時創建然后銷毀額外的Insets對象。
第二個可用的新方法是getInteriorRectangle(),這個方法有靜態與非靜態版本。指定了Component,Border,以及四個整數參數,這個方法將會返回一個內部的Rectangle,從而組件可以在邊框內部區域內繪制其自身。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
