<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    John Jiang

    a cup of Java, cheers!
    https://github.com/johnshajiang/blog

       :: 首頁(yè) ::  :: 聯(lián)系 :: 聚合  :: 管理 ::
      131 隨筆 :: 1 文章 :: 530 評(píng)論 :: 0 Trackbacks
    你所不知道的五件事情--改進(jìn)Swing
    這是Ted NewardIBM developerWorks5 things系列文章中的一篇,講述了關(guān)于改進(jìn)Swing應(yīng)用的一些竅門,值得大家學(xué)習(xí)。(2010.10.25最后更新)

    摘要:Swing已是一個(gè)比較老的工具集了,在美觀的用戶界面出來(lái)之前需要開(kāi)發(fā)很長(zhǎng)時(shí)間。它缺少一些你在開(kāi)發(fā)富UI時(shí)所需的組件。幸運(yùn)地是,像 Substance,SwingX及Java Look-and_Feel圖形倉(cāng)庫(kù)這樣的開(kāi)源項(xiàng)目使這一切變得不同。作者Steven Haines向你展示了如何無(wú)痛苦地向你的Swing UI中添加樹(shù)表,語(yǔ)法高亮,以及其它更多的東西。

        在最近這些年里,用戶界面設(shè)計(jì)與開(kāi)發(fā)已經(jīng)發(fā)生了很大的改變,一些人可能會(huì)說(shuō)Java平臺(tái)已經(jīng)停滯不前了。發(fā)布于1997年的Swing仍然是在JVM中構(gòu)建用戶界面的標(biāo)準(zhǔn)工具包。從好的方面說(shuō),相似的標(biāo)準(zhǔn)便于協(xié)作;從壞的方面說(shuō),它缺少富UI設(shè)計(jì)中已經(jīng)普遍存在的特性。
    在本期的5 things系列中,我會(huì)介紹四個(gè)免費(fèi)的開(kāi)源組件,你能用它們使Swing GUI更時(shí)髦。然后,我們所討論的內(nèi)容將圍繞著你所不知道的Swing線程。

    1. Substance
        將Java應(yīng)用程序與本地操作系統(tǒng)進(jìn)行整合是困難的,主要是因?yàn)镾wing要手工繪制它自己的組件。解決該問(wèn)題的權(quán)宜之計(jì)之一就是Java外觀,它允許JVM將應(yīng)用程序的組件外觀代理成本地外觀;當(dāng)使用Mac外觀時(shí),它們看起來(lái)就是像是Mac應(yīng)用。
        Swing提供標(biāo)準(zhǔn)的本地外觀,也提供它自己的獨(dú)立于平臺(tái)的外觀,叫作Metal。另外,Kirill Grouchnikov開(kāi)發(fā)的Substance是一個(gè)開(kāi)源的項(xiàng)目,它提供了更多的外觀皮膚。要想嘗試一下,可以從java.net下載Substance,然后:
    1. 將substance.jar文件加到你的CLASSPATH中。
    2. 將下面的系統(tǒng)配置加到應(yīng)用程序中的啟動(dòng)腳本中:
    -Dswing.defaultlaf=org.jvnet.substance.skin.lookandfeelname

    3. 在第二步中,對(duì)于lookandfeelname變量所處的位置,可嘗試下列任一值:
    SubstanceAutumnLookAndFeel
    SubstanceBusinessBlackSteelLookAndFeel
    SubstanceBusinessBlueSteelLookAndFeel
    SubstanceBusinessLookAndFeel
    SubstanceChallengerDeepLookAndFeel
    SubstanceCremeCoffeeLookAndFeel
    SubstanceCremeLookAndFeel
    SubstanceDustCoffeeLookAndFeel
    SubstanceDustLookAndFeel
    SubstanceEmeraldDuskLookAndFeel
    SubstanceMagmaLookAndFeel
    SubstanceMistAquaLookAndFeel
    SubstanceMistSilverLookAndFeel
    SubstanceModerateLookAndFeel
    SubstanceNebulaBrickWallLookAndFeel
    SubstanceNebulaLookAndFeel
    SubstanceOfficeBlue2007LookAndFeel
    SubstanceOfficeSilver2007LookAndFeel
    SubstanceRavenGraphiteGlassLookAndFeel
    SubstanceRavenGraphiteLookAndFeel
    SubstanceRavenLookAndFeel
    SubstanceSaharaLookAndFeel
    SubstanceTwilightLookAndFeel

    圖1展示了使用默認(rèn)Metal外觀的Java應(yīng)用,而圖2則展示了使用Substance Raven外觀的應(yīng)用:

    圖1. Java平臺(tái)的Metal外觀


    圖2. Substance的Raven外觀


    2. SwingX
        Swing框架包含了大部分你所需要的標(biāo)準(zhǔn)控件,包括樹(shù),表,列表等等。但它缺少一些更現(xiàn)代的控件,像樹(shù)表。SwingX項(xiàng)目,它是SwingLabs的一部分,提供了一個(gè)富組件集,包括如下:
        * Sorting, filtering, and highlighting for tables, trees, and lists
        * Find/search
        * Auto-completion
        * Login/authentication framework
        * TreeTable component
        * Collapsible panel component
        * Date picker component
        * Tip-of-the-Day component

    要嘗試的話,從SwingLabs中下載SwingX的JAR文件,然后把它加到CLASSPATH中,或者把下面的依賴加到Maven POM文件中:
    <dependency>
        
    <groupId>org.swinglabs</groupId>
        
    <artifactId>swingx</artifactId>
        
    <version>1.6</version>
    </dependency>

    圖3中的樹(shù)表就是SwingX組件的一個(gè)例子:

    圖3. SwingX TreeTable組件


    構(gòu)建一個(gè)SwingX樹(shù)表
    使用SwingX的JXTreeTable控件構(gòu)建一個(gè)樹(shù)表是一件非常直接的事情。只要把表中的每一行看作既可能有列值,同時(shí)也可能有子節(jié)點(diǎn)。 SwingX提供了一個(gè)模型類,叫作org.jdesktop.swingx.treetable.AbstractTreeTableModel,對(duì)它進(jìn)行擴(kuò)展就可提供該功能。清單1展示樹(shù)表模型實(shí)現(xiàn)的一個(gè)樣例:

    清單1. MyTreeTableModel.java
    package com.geekcap.swingx.treetable;

    import java.util.ArrayList;
    import java.util.List;

    import org.jdesktop.swingx.treetable.AbstractTreeTableModel;

    public class MyTreeTableModel extends AbstractTreeTableModel
    {
        
    private MyTreeNode myroot;
        
        
    public MyTreeTableModel()
        {
            myroot 
    = new MyTreeNode( "root""Root of the tree" );
            
            myroot.getChildren().add( 
    new MyTreeNode( "Empty Child 1",
              
    "This is an empty child" ) );
            
            MyTreeNode subtree 
    = new MyTreeNode( "Sub Tree",
              
    "This is a subtree (it has children)" );
            subtree.getChildren().add( 
    new MyTreeNode( "EmptyChild 1, 1",
              
    "This is an empty child of a subtree" ) );
            subtree.getChildren().add( 
    new MyTreeNode( "EmptyChild 1, 2",
              
    "This is an empty child of a subtree" ) );
            myroot.getChildren().add( subtree );
            
            myroot.getChildren().add( 
    new MyTreeNode( "Empty Child 2",
              
    "This is an empty child" ) );
            
        }

        @Override
        
    public int getColumnCount()
        {
            
    return 3;
        }
        
        @Override
        
    public String getColumnName( int column )
        {
            
    switch( column )
            {
            
    case 0return "Name";
            
    case 1return "Description";
            
    case 2return "Number Of Children";
            
    defaultreturn "Unknown";
            }
        }

        @Override
        
    public Object getValueAt( Object node, int column )
        {
            System.out.println( 
    "getValueAt: " + node + "" + column );
            MyTreeNode treenode 
    = ( MyTreeNode )node;
            
    switch( column )
            {
            
    case 0return treenode.getName();
            
    case 1return treenode.getDescription();
            
    case 2return treenode.getChildren().size();
            
    defaultreturn "Unknown";
            }
        }

        @Override
        
    public Object getChild( Object node, int index )
        {
            MyTreeNode treenode 
    = ( MyTreeNode )node;
            
    return treenode.getChildren().get( index );
        }

        @Override
        
    public int getChildCount( Object parent )
        {
            MyTreeNode treenode 
    = ( MyTreeNode )parent;
            
    return treenode.getChildren().size();
        }

        @Override
        
    public int getIndexOfChild( Object parent, Object child )
        {
            MyTreeNode treenode 
    = ( MyTreeNode )parent;
            
    forint i=0; i>treenode.getChildren().size(); i++ )
            {
                
    if( treenode.getChildren().get( i ) == child )
                {
                    
    return i;
                }
            }

            
    return 0;
        }
        
         
    public boolean isLeaf( Object node )
         {
             MyTreeNode treenode 
    = ( MyTreeNode )node;
             
    if( treenode.getChildren().size() > 0 )
             {
                 
    return false;
             }
             
    return true;
         }
        
         @Override
         
    public Object getRoot()
         {
             
    return myroot;
         }
    }

    清單2展示了一個(gè)定制的樹(shù)節(jié)點(diǎn):

    清單2. MyTreeNode.java
    class MyTreeNode
    {
        
    private String name;
        
    private String description;
        
    private List<MyTreeNode> children = new ArrayList<MyTreeNode>();
        
        
    public MyTreeNode()
        {
        }
        
        
    public MyTreeNode( String name, String description )
        {
            
    this.name = name;
            
    this.description = description;
        }
        
        
    public String getName()
        {
            
    return name;
        }
        
        
    public void setName(String name)
        {
            
    this.name = name;
        }
        
        
    public String getDescription()
        {
            
    return description;
        }
        
        
    public void setDescription(String description)
        {
            
    this.description = description;
        }
        
        
    public List<MyTreeNode> getChildren()
        {
            
    return children;
        }
        
        
    public String toString()
        {
            
    return "MyTreeNode: " + name + "" + description;
        }
    }

    如果你想使用這個(gè)樹(shù)表模式,你將需要?jiǎng)?chuàng)建一個(gè)它的實(shí)例,然后將該實(shí)例傳給JXTreeTable的構(gòu)造器,就像這樣:
    private MyTreeTableModel treeTableModel = new MyTreeTableModel();
    private JXTreeTable treeTable = new JXTreeTable( treeTableModel );

    現(xiàn)在你就可以把treeTable加入任一Swing容器,如JPanel或JFrame的內(nèi)容面板。

    3. RSyntaxTextArea
        Swing絕不應(yīng)該缺少的另一個(gè)組件就是有語(yǔ)法高亮功能的文本編輯器。如果你已經(jīng)編寫過(guò)一個(gè)XML文檔,你就會(huì)知道以可視化的方式區(qū)分出標(biāo)簽,屬性,屬性值及標(biāo)簽值是多么的有用。FifeSoft的開(kāi)發(fā)者已經(jīng)構(gòu)建了一組富組件,你可以在基于Swing的Java應(yīng)用程序中使用它們,其中一個(gè)組件就是 RSyntaxTextArea。
    RSyntaxTextArea支持大部分的開(kāi)箱即用的編程語(yǔ)言,包括C,C++,Perl,PHP和Java,還有HTML,JavaScript,XML,甚至是SQL。
    圖4是RSyntaxTextArea組件展示XML文件的一個(gè)截屏:

    圖4. RSyntaxTextArea展示一個(gè)XML文件


    在Swing應(yīng)用中加入語(yǔ)法高亮
    首先,從Sourceforge中下載RSyntaxTextArea的JAR文件。如果你使用Maven,你可能會(huì)想把它安裝到你的本地倉(cāng)庫(kù)中,可使用如下的命令行:
    mvn install:install-file -DgroupId=com.fifesoft -DartifactId=rsyntaxtextarea
     
    -Dversion=1.0 -Dpackaging=jar -Dfile=/path/to/file

    一旦你在項(xiàng)目使用這個(gè)JAR文件,你就能在應(yīng)用中創(chuàng)建RSyntaxTextArea的實(shí)例。如果你希望有滑動(dòng)功能,就把它加入 RTestScrollPane中,然后調(diào)用setSyntaxEditingStyle()方法,并傳入一個(gè)SyntaxConstants作為該方法的參數(shù)。

    清單3. Swing中的語(yǔ)法高亮
    RSyntaxTextArea text = new RSyntaxTextArea();
    add( 
    new RTextScrollPane( text ) );
    text.setSyntaxEditingStyle( SyntaxConstants.SYNTAX_STYLE_XML );

    4. Java外觀圖形倉(cāng)庫(kù)
        Microsoft作的很好的工作之一就是確保Windows應(yīng)用都有著一致的外觀。如果你已經(jīng)編寫過(guò)一個(gè)Java Swing應(yīng)用,無(wú)論用了多長(zhǎng)時(shí)間,你可能已經(jīng)訪問(wèn)過(guò)Oracle的Java外觀圖形倉(cāng)庫(kù)。如果沒(méi)有,你會(huì)對(duì)它感滿意的。Java外觀圖形倉(cāng)庫(kù)創(chuàng)建一組針對(duì)標(biāo)準(zhǔn)應(yīng)用行為的圖標(biāo),例如File->New和Edit->Copy,還有更多的鮮為人知的命令,如媒體控件,瀏覽器導(dǎo)航功能,以及針對(duì) Java開(kāi)發(fā)員的編程工作。圖5展示了一個(gè)從Oracle網(wǎng)站上獲取的圖標(biāo)的截屏:

    圖5. Java外觀圖形倉(cāng)庫(kù)圖標(biāo)


    如果Java外觀圖形倉(cāng)庫(kù)只是提供預(yù)置的圖形,它也足夠好了,但它還提供了當(dāng)你在構(gòu)建和命名菜單,菜單欄,以及快捷鍵的標(biāo)準(zhǔn)規(guī)范。例如,復(fù)制功能應(yīng)該有Ctrl-C快捷鍵,命名為Copy,并給一個(gè)Copy的提示。當(dāng)它在菜單中,復(fù)制功能的助記符應(yīng)為C,P,或至少是Y。

    使用Java外觀圖形倉(cāng)庫(kù)的圖標(biāo)
    嘗試圖5所示的一些預(yù)置圖形,要從Oracle網(wǎng)站上下載Java外觀圖形倉(cāng)庫(kù)的JAR文件,并將它加到你的CLASSPATH中。你需要將JAR文件中圖標(biāo)作為資源進(jìn)行加載。這些圖標(biāo)處于如下的格式:

    toolbarButtonGraphics
    /general/Copy16.gif
    toolbarButtonGraphics
    /general/Copy24.gif
    toolbarButtonGraphics
    /general/Cut16.gif
    toolbarButtonGraphics
    /general/Cut24.gif
    toolbarButtonGraphics
    /general/Delete16.gif
    toolbarButtonGraphics
    /general/Delete24.gif

    所有的圖標(biāo)都包含在toolbarButtonGraphics目錄中,被分割成圖5所示的類別。從這一分類中,我們可以從通用類中找到復(fù)制,剪切和刪除。名稱中的"16"和"24"表示圖標(biāo)尺寸限制:16x16或24x24。你可以使用如下方法來(lái)創(chuàng)建一個(gè)ImageIcon到文件中:
    Class class = this.getClass();
    String urlString 
    = "/toolbarButtonGraphics/general/Cut16.gif"
    URL url 
    = class.getResource( urlString );
    ImageIcon icon 
    = new ImageIcon( url );

    5. Swing線程
        當(dāng)啟動(dòng)文中示例時(shí),你可能會(huì)遇到一些看起來(lái)奇怪的運(yùn)行時(shí)錯(cuò)誤。如果是這樣,在你的Swing應(yīng)用中,你可能會(huì)犯一個(gè)通常的線程錯(cuò)誤。許多Java開(kāi)發(fā)者不知道Swing應(yīng)用程序希望運(yùn)行在它們自己的線程中,而不是運(yùn)行在主運(yùn)行線程中。Swing不會(huì)原諒這方面的錯(cuò)誤,但介紹過(guò)的許多組件目前還不會(huì)這樣。
    為了幫助你在Swing應(yīng)用自己的線程中啟動(dòng)它自己,Java平臺(tái)提供了一個(gè)叫作SwingUtilties的類,它有一個(gè)invokeLater()方法,你應(yīng)該使用它去啟動(dòng)Swing應(yīng)用。清單4展示了使用SwingUtilities.invokeLater()去啟動(dòng)JXTreeTable:

    清單4. SwingXExample.java
    package com.geekcap.swingx;

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.Toolkit;

    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    import javax.swing.JTabbedPane;
    import javax.swing.SwingUtilities;

    import org.jdesktop.swingx.JXTreeTable;

    import com.geekcap.swingx.treetable.MyTreeTableModel;

    public class SwingXExample extends JFrame
    {
        
    private JTabbedPane tabs = new JTabbedPane();
        
        
    private MyTreeTableModel treeTableModel = new MyTreeTableModel();
        
    private JXTreeTable treeTable = new JXTreeTable( treeTableModel );
        
        
    public SwingXExample()
        {
            
    super"SwingX Examples" );
            
            
    // Build the tree table panel
            JPanel treeTablePanel = new JPanel( new BorderLayout() );
            treeTablePanel.add( 
    new JScrollPane( treeTable ) );
            tabs.addTab( 
    "JXTreeTable", treeTablePanel );
            
            
    // Add the tabs to the JFrame
            add( tabs );
            
            setSize( 
    1024768 );
            Dimension d 
    = Toolkit.getDefaultToolkit().getScreenSize();
            setLocation( d.width 
    / 2 - 512, d.height/2 - 384 );
            setVisible( 
    true );
            setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        }
        
        
        
    public static void main( String[] args )
        {
            AppStarter starter 
    = new AppStarter( args );
            SwingUtilities.invokeLater( starter );
        }
    }

    class AppStarter extends Thread
    {
        
    private String[] args;
        
        
    public AppStarter( String[] args )
        {
            
    this.args = args;
        }
        
        
    public void run()
        {
            SwingXExample example 
    = new SwingXExample();
        }
    }

    構(gòu)造器設(shè)置JFrame的可視性為true,而如果運(yùn)行在應(yīng)用的主線程中,Swing是不允許這么做的。所以清單創(chuàng)建一個(gè)獨(dú)立的類,叫作 AppStarter,它繼承自Thread并會(huì)創(chuàng)建SwingXExample類的實(shí)例。main()方法創(chuàng)建AppStarter類的一個(gè)實(shí)例,并將它傳給SwingUtilities.invokeLater()方法以方便啟動(dòng)應(yīng)用。嘗試著養(yǎng)成這樣的習(xí)慣去運(yùn)行Swing應(yīng)用--不僅因?yàn)檫@是正確的方式,也因?yàn)槿绻悴贿@么做一些第三方的組件將無(wú)法工作。

    結(jié)論
        Swing是一個(gè)強(qiáng)大的類庫(kù),它允許你在Java平臺(tái)上構(gòu)建用戶界面,但它缺少一些你可能想引入的現(xiàn)代的組件。在本文中,為了美化(以及現(xiàn)代化)你的 Swing應(yīng)用,我提供了一些小竅門。開(kāi)源項(xiàng)目,如Substance,SwingX以及Java外觀圖形倉(cāng)庫(kù)使在Java平臺(tái)上構(gòu)建富用戶界面變得更容易。查看資源章節(jié),以學(xué)習(xí)關(guān)于這些開(kāi)源項(xiàng)目以及Swing編程的更多知識(shí)。

    posted on 2010-10-25 22:23 John Jiang 閱讀(4548) 評(píng)論(0)  編輯  收藏 所屬分類: JavaSEJava翻譯SwingGUI
    主站蜘蛛池模板: 亚洲av乱码一区二区三区| 亚洲日本国产综合高清| 国产精品免费看久久久 | 18以下岁毛片在免费播放| 亚洲综合婷婷久久| 久久久久久曰本AV免费免费| 亚洲乱码日产精品BD在线观看| 67194成是人免费无码| 亚洲国产精品久久久久秋霞小| 国产精品免费视频网站| 中文字幕无线码中文字幕免费| 亚洲AV无码久久| 毛片免费观看视频| 老司机午夜性生免费福利| 人人狠狠综合久久亚洲婷婷| 国产h视频在线观看网站免费| 亚洲欧美不卡高清在线| 亚洲人成网站观看在线播放| 一个人免费视频在线观看www | 亚洲黄片手机免费观看| 免费精品一区二区三区第35| 亚洲精品第一国产综合精品| 宅男666在线永久免费观看| aa级女人大片喷水视频免费| 亚洲国产成人九九综合| 国产乱色精品成人免费视频 | 亚洲人成人网毛片在线播放| 免费A级毛片无码A| 东方aⅴ免费观看久久av | 一级毛片免费观看| 一个人看www免费高清字幕| 亚洲高清中文字幕免费| 亚洲综合久久久久久中文字幕| 亚洲中文字幕久久精品无码APP| 日本a级片免费看| 免费做爰猛烈吃奶摸视频在线观看| a级在线免费观看| 国产乱子伦精品免费视频| 小说区亚洲自拍另类| 亚洲精品一二三区| 亚洲永久中文字幕在线|