• Java Swing 组件大全实例演示


    一 抛砖引玉

      本文指在利用一个小程序”Swing 组件大全”来引导大家学习Java这门语言,熟悉Java Swing的各个组件。并在学习过程中参考作者设计这一程序的方法和思想,最终形成自己的思维方式和学习方式。你能举一返三是作者最开心的事情。小程序演示了Java Swing大部分组件。最后附上了全部代码及详细的注释说明。希望本文能对大家学习Java有所帮助。

      随着Java风潮席卷国内,学习Java的方法和路径越来越多。而在大量的书本前,在Java庞大的类库前大大家都有点迷失方向的感觉,是学 J2EE,J2ME还是。。。。。。然而所有的这些都或多或少的离不开J2SE。万丈高楼平地起。J2SE是整个Java的基础,学好了这个对Java的各个方向都是很有利的。而学习J2SE的最初点就在界面设计,因为界面编程是你来感觉最直接的手段,是提高大家编程兴趣的很好开始,因为你写完程序编译后可马上看到自己的成果。而不像后台编程做完了都感受不到效果。而好的界面也是你测试你其他程序的基础。

      界面设计!不就是拖拉操作吗?如果是VB,VC等可视化的编程,的确只是一些拖拉操作,由于Java语言的设计中所有的东西都是程序代码,在 Java中如果想要设计一个好的界面,可不是简单的拖拉操作能完成的。即使使用了如JBuilder这么强大的可视化工具,你也得亲自动手写一些界面设计代码才能很好的完成你的任务。如果你能在此基础上理解Java界面设计的思想,对你学习这门语言将有莫大的帮助。

      Java界面设计主要涉及Awt,Swing两大类库,Swing是Awt的扩展和功能加强。下面我们就以Swing为基础来说说整个Java的界面设计。

      二 感受效果

      在开始之前,让我们看看这篇文章要达到的效果,有了目标和成果才有学习的兴趣,起码我是这样认为和学习的。如下图所示,这就是我们设计的界面,它包括了Swing中大部分常用的组件。有些功能界面上反映不出来,大家可尝试编译源代码点南击各个部分,看看它们的响应事件。



      三 设计思想和方法

      不知道大家(一般是初学者)在看编程书籍的时候有这种体会没有:在看的过程中,好像大部理解了,并且效率还不错,可是回头来要自己写个和书上一样的程序出来,可能不少人只有重新拿书照打的了;有些人在照书上打过了一遍,也似乎理解了。可回头来真正到用的时候,好像又不记得了。作者本人在初学编程时就经历过很多次这种情况。

      追其原因,无外乎没有融会贯通所学的知识,编程最讲求动手二字,动手的真正意义在于写自己所想所领会的程序而不是copy现成的程序。因为只有经过自己思考,设计才能把书上的知识真正溶入自己的大脑。下面我们以”Swing 组件大全”来说说这个方法和思想。

      在看完书上介绍的Swing组件这章后,我心中对Swing大概有了个了解,只差动手了。而本人又不想照书上的例子一个个来试。于是就想到了做个程序把书上介绍的所有组件放到一个界面来,并尝试用到书上介绍的所有方法。

      砍柴不误磨刀功!在开始这前,我手画了一份设计图纸,如上面界面所示(当然没那么漂亮了)。并用简单的软件工程思想对结构进行了大概的划分。这里把整个界面划分为一个主模块和五大子模块。所有的子模块都是继承至相应的容器,主模块SwingTest既是管理模块也是主界面,继承JFrame主框架,管理本身的属性及JFrame上的其他子模块。MenuTest子模块继承至JmenuBar负责菜单的显示和事件处理。其他子模块继承至JPanel,管理放置在其上的组件的布局和显示。从子模块的名字大家也可看到他们的位置和功能。如下图所示:

     

      在编写程序前想好结构和思路是个很好的习惯,它将会帮你大大减少工作量,提高程序的可读性和效率。

    四 容器,布局管理器,嵌板

      Swing中所有的组件都是放到容器中,主要的容器包括:JFrame,JPanel,JWindow,JDialog,JPanle。JFrame是java的主框架,几乎所有的Java应用程序界面都是在主框架之中设计的。有些容器并非一层,而由几层嵌板组成,本文将会用到其中在个:拆分嵌板(JSplitPane),内容嵌板, 页签式嵌板(TabbedPane)

      拆分嵌板:按指定的方向和方式拆分其内的两个子组件,记住一个拆分嵌板只能拆分两个子组件,如果想要拆分三个,大家自己先想一想办法。本节最后给出了答案。

      内容嵌板: JFrame,Jwindow,Jdialog就是上面提到的有多层嵌板的容器,如果要在这些容器上面放置组件,必须放置在他们的内容嵌板(pane)上。我们通过函数getContentPane()可得到当前容器的内容嵌板。

      页签式嵌板:这个嵌板如同卡片,在上面提供文件夹式的页签,当前只显示一页,如要进入下一页,只要点击上面的页签。

      有些如JPanel是可以直接放置组件的容器。所以不需要使用嵌板。

      如果要按自己的想法排列放在容器上的组件,我们必须使用到布局管理器(Layout)来进行管理。Java系统默认的布局管理器为边界管理器 (BorderLayout)。它把版面分为五大块,中央区域(Center),顶端(North),底部(South),左侧(West),右侧 (East),细心的你可能会发现我们的主界面就是用的这个布局架构。其他的几个布局管理器有:

      流布局(FlowLayout):把其内的组件按从左到右,从上到下的流方式排列。

      网格布局(GridLayout):把组件放置到布局中的设置的每个网格中

      无序网格布局(GridBagLayout):类似于网格布局,但功能更强大也更复杂。能处理所有的布局。

      如果你仔细观察会发现我们的主界面最右边会发现使用了网格布局。

      下面来看看我们的主模块的构造函数代码,来感受一下上面的结构设计。

    public SwingTest()

    {

    // 初始化所有子模块

    MenuTest menuTest = new MenuTest();

    LeftPanel leftPanel = new LeftPanel();

    RightPanel rightPanel = new RightPanel();

    BottomPanel bottomPanel = new BottomPanel();

    CenterPanel centerPanel = new CenterPanel();

    // 设置主框架的布局

    Container c = this.getContentPane();

    // c.setLayout(new BorderLayout())

    this.setJMenuBar(menuTest);

    c.add(leftPanel,BorderLayout.WEST);

    c.add(rightPanel,BorderLayout.EAST);

    c.add(centerPanel,BorderLayout.CENTER);

    c.add(bottomPanel,BorderLayout.SOUTH);

    setSize(700,500);

    setTitle("Swing 组件大全简体版");

    // 隐藏frame的标题栏,此功暂时关闭,以方便使用window事件

    // setUndecorated(true);

    setLocation(200,150);

    show();

    }

      如拆分三个子组件,可把一个拆分嵌板做为另一个拆分嵌板的子组件!

      五 事件模型

      在Swing 中每个组件都可触发事件,一旦触发事件会被一个或多个Listener(监听器)接收。不同类型的事件分别由个别的class表示。事件发生点可以和处理事件的代码分开。

      要想处理事件,只要产生Listener对象,并调用组件的addXXXListener()方法注册事件。我们大部分是通过继承事件接口来处理事件的。但是继承Java接口我们必须实现出接口中的所有方法。有些接口包含了大量的函数,如果要一个个实现是件很麻烦的事件上,Java中定义了相应接口的Adapter接配器类来解决这种情况。接配器类已经帮我们实现了接口的所有方法,而我们只要继承接配器就可在代码内做我们想做的事情。也即只要实现或覆写我们想要实现的方法。

      下面我们还是以主模块为例,来处理关闭窗口事件。

    // 利用无名内隐类,增加窗口事件

    this.addWindowListener(new WindowAdapter()

    {

    public void WindowClosing(WindowEvent e)

    {

    // 释放资源,退出程序

    dispose();

    System.exit(0);

    }

    });

      如上所示,我们向主框架注册了一个窗口事件addWindowListener(),事件继承了WindowAdapter接配器,并重载了方法WindowClosing(),方法中利用dispose()释放窗口资源,System.exit(0)关闭窗口。

      六 总结

      好了,我们来回顾一个我们的上面的内容:设计的思路,容器,嵌板,布局管理器, Swing组件的事件。

      大家明白了为什么做项目能快速提高自己水平了吧。其实上面的方法原理和做项目差不多,任何事只要经过自己的大脑思考,亲手操作,想忘记并不是那么容易的了。相信看了本文和代码再辅以相关的书籍介绍,大家对Swing处理会有一定的感性理解了。

      开始动手吧。发挥你的天才思维,自己设计一个更好的Swing组件大全吧。当然你也可在本程序的基础上完善其中更复杂的功能。比如:把树形列表内容用window文件资源器代替,把表格的处理和数据库相连接或和相关数据连接,让文本区可显示图片。。。。。哦,天啊。说不定一个好的产品也会因此诞生。

      再次强调开始之前请先设计你的界面,画出你的程序结构图。即使再小的程序也请你大概勾一个它的轮廓。

      七 具体代码

      由于代码中已经附上了比较详细的注释,在此就不一一解释说明了。在此要提醒大家在研究源代码时要注意几个复杂的组件的处理方式:如树形组件 (JTree),表格(JTable),文本区(JtextArea),定时器(Timer)。为了方便大家直接复制源代码来编译,所有的模块都是放在一个主类中实现的。所有源代码的事件都是用嵌套的内隐类方法来实现的。如果大家不习惯这种写法,程序中已经消除了各模块之间的关联性,可很方便的把各子模块分离成类文件。代码只是演示了Swing的大部组件,各个组件没有很深入的处理了。

    下面是源码:

    import javax.swing.*;

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.tree.*;
    import javax.swing.event.*;
    import javax.swing.border.*;
    import javax.swing.table.*;

    /** 
     * Swing 组件测试程序
     * 测试Swing所有组件及其相应的事件
     * @author 天翼.李 2003.4.17 晚23:14
     * @link 
    http://www.robochina.org
     * @link robococde@etang.com
     */
    public class SwingTest extends JFrame
    {
        /**
         * 主模块,初始化所有子模块,并设置主框架的相关属性
         */
        public SwingTest()
        {
            // 初始化所有模块
            MenuTest menuTest = new MenuTest();
            LeftPanel leftPanel = new LeftPanel();
            RightPanel rightPanel = new RightPanel();
            BottomPanel bottomPanel = new BottomPanel();
            CenterPanel centerPanel = new CenterPanel();
            
            // 设置主框架的布局
            Container c = this.getContentPane();
            // c.setLayout(new BorderLayout())
            this.setJMenuBar(menuTest);
            
            c.add(leftPanel,BorderLayout.WEST);
            c.add(rightPanel,BorderLayout.EAST);
            c.add(centerPanel,BorderLayout.CENTER);
            c.add(bottomPanel,BorderLayout.SOUTH);
            
            // 利用无名内隐类,增加窗口事件
            this.addWindowListener(new WindowAdapter()
                {
                    public void WindowClosing(WindowEvent e)
                    {   
                        // 释放资源,退出程序
                        dispose();
                        System.exit(0);
                    }
                });
                
            
            
            setSize(700,500);
            setTitle("Swing 组件大全简体版");
            // 隐藏frame的标题栏,此功暂时关闭,以方便使用window事件
            // setUndecorated(true);
            setLocation(200,150);
            show();        
        }

        ////////////////////////////////////////////////////////////////////////////
        /**
         * 菜单栏处理模块
         * JMenuBar --+
         *            --JMenu--+
         *                       --JMenuItem  --ActionListener 
         *              
         */
        class MenuTest extends JMenuBar
        {
            private JDialog aboutDialog;
                
            /**
             * 菜单初始化操作
             */    
            public MenuTest()
            {
                JMenu fileMenu = new JMenu("文件");
                JMenuItem exitMenuItem = new JMenuItem("退出",KeyEvent.VK_E);
                JMenuItem aboutMenuItem = new JMenuItem("关于...",KeyEvent.VK_A);            
                                                    
                fileMenu.add(exitMenuItem);
                fileMenu.add(aboutMenuItem);
                
                this.add(fileMenu);        
                
                        
                aboutDialog = new JDialog();
                initAboutDialog();
                            
                // 菜单事件
                exitMenuItem.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent e)
                    {
                        dispose();
                        System.exit(0);
                    }
                });
                
                aboutMenuItem.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent e)
                    {
                        // "关于"对话框的处理
                        aboutDialog.show();
                    }
                });            
                            
            }
            
            /**
             * 返回关于对话框
             */
            public JDialog getAboutDialog()
            {
                return aboutDialog;
            }
            
            /**
             * 设置"关于"对话框的外观及响应事件,操作和JFrame一样都是在内容
             * 框架上进行的
             */
            public void initAboutDialog()
            {
                aboutDialog.setTitle("关于");
                
                Container con =aboutDialog.getContentPane();
                 
                // Swing 中使用html语句
                Icon icon = new ImageIcon("smile.gif");
                JLabel aboutLabel = new JLabel("<html><b><font size=5>"+
                "<center>Swing 组件大全简体版!"+"<br>天翼.李",icon,JLabel.CENTER);
                            
                //JLabel aboutLabel = new JLabel("Swing 组件大全简体版!",icon,JLabel.CENTER);
                con.add(aboutLabel,BorderLayout.CENTER);
                
                aboutDialog.setSize(450,225);
                aboutDialog.setLocation(300,300);                        
                aboutDialog.addWindowListener(new WindowAdapter()
                {
                    public void WindowClosing(WindowEvent e)
                    {
                        dispose();
                    }                    
                });            
            }
        }
        
        ////////////////////////////////////////////////////////////////////////////
        /**
         * 最左边模块,继承JPanel,初始化内容为JTree
         * JPanel--+
         *         --JTree
         */
        class LeftPanel extends JPanel
        {
            private int i = 0;
            public LeftPanel()
            {
                
                DefaultMutableTreeNode    root = new DefaultMutableTreeNode("Root");
                DefaultMutableTreeNode child = new DefaultMutableTreeNode("Child");
                DefaultMutableTreeNode select = new DefaultMutableTreeNode("select");
                
                DefaultMutableTreeNode child1 = new DefaultMutableTreeNode(""+i);
                
                root.add(child);        
                root.add(select);
                child.add(child1);    
                
                JTree tree = new JTree(root);
                tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
                
                // 每个节点的行高
                tree.setRowHeight(20);            
                tree.addTreeSelectionListener(new TreeSelectionListener ()
                {
                    public void valueChanged(TreeSelectionEvent e)
                    {
                        // 内隐类不能直接引用外部类tree,1.外部变量可申明为final 2.新建外部类的对象
                        JTree tree =(JTree)e.getSource();
                        DefaultMutableTreeNode selectNode = (DefaultMutableTreeNode)tree.getLastSelectedPathComponent();
                        i++;
                        selectNode.add(new DefaultMutableTreeNode(""+i));
                    }
                });            
                
                tree.setPreferredSize(new Dimension(100,300));
            //    tree.setEnabled(true);
                JScrollPane scrollPane = new JScrollPane(tree);
                //scrollPane.setSize(100,350);
                this.add(scrollPane);
            }
        }
        
        ////////////////////////////////////////////////////////////////////////////
        /**
         * 最下面层模块,继承JPanel,初始化内容为进度条,并由定时器控制
         * JPanel--+
         *         --JProcessBar  --Timer
         */
        class BottomPanel extends JPanel
        {
            private JProgressBar pb;
            ////////////////////////////////////////
            //public class 
            //////////////////////////////
            public BottomPanel()
            {
                pb = new JProgressBar();
                pb.setPreferredSize(new Dimension(680,20));
                
                // 设置定时器,用来控制进度条的处理
                Timer time = new Timer(1,new ActionListener()
                { 
                    int counter = 0;
                    public void actionPerformed(ActionEvent e)
                    {
                        counter++;
                        pb.setValue(counter);
                        Timer t = (Timer)e.getSource();
                        
                        // 如果进度条达到最大值重新开发计数
                        if (counter == pb.getMaximum())
                        {
                            t.stop();
                            counter =0;
                            t.start();
                        }                    
                    }
                });
                time.start();
                
                pb.setStringPainted(true);
                pb.setMinimum(0);
                pb.setMaximum(1000);
                pb.setBackground(Color.white);
                pb.setForeground(Color.red);
                            
                this.add(pb);                
            }
            
            /**
             * 设置进度条的数据模型
             */
            public void setProcessBar(BoundedRangeModel rangeModel)
            {
                pb.setModel(rangeModel);
            }
        }
        
        ////////////////////////////////////////////////////////////////////////////
        /**
         * 最右边模块,继承JPanel,初始化各种按钮
         * JPanel--+
         *         --JButton  --JToggleButton -- JList -- JCombox --JCheckBox ....
         */
        class RightPanel extends JPanel
        {
            public RightPanel()
            {
                this.setLayout(new GridLayout(8,1));        
                
                
                // 初始化各种按钮
                JCheckBox checkBox = new JCheckBox("复选按钮");            
                JButton button = new JButton("打开文件");
                button.addActionListener(new ActionListener()
                {
                    public void actionPerformed(ActionEvent e)
                    {
                        JFileChooser file = new JFileChooser();
                        int result = file.showOpenDialog(new JPanel());
                        if (result ==file.APPROVE_OPTION) 
                        {
                            String fileName = file.getSelectedFile().getName();                    
                            String dir = file.getCurrentDirectory().toString();
                              JOptionPane.showConfirmDialog(null,dir+"\\"+fileName,"选择的文件",JOptionPane.YES_OPTION);
                         }
                    }
                });
                ////////////////////////////////////////
                //public
                //////////////////////////////////////////
                        
                JToggleButton toggleButton = new JToggleButton("双态按钮");
                
                ButtonGroup    buttonGroup = new ButtonGroup();
                JRadioButton radioButton1 = new JRadioButton("单选按钮1",false);
                JRadioButton radioButton2 = new JRadioButton("单选按钮2",false);
                
                // 组合框的处理
                JComboBox comboBox = new JComboBox();
                comboBox.setToolTipText("点击下拉列表增加选项");
                comboBox.addActionListener(new ActionListener() 
                {
                    public void actionPerformed(ActionEvent e)
                    {
                        JComboBox comboBox =(JComboBox)e.getSource();
                        comboBox.addItem("程序员");
                        comboBox.addItem("分析员");
                    }
                });
                
                // 列表框的处理
                DefaultListModel litem = new DefaultListModel();
                litem.addElement("香蕉");
                litem.addElement("水果");
                JList list = new JList(litem);
                
                
                list.addListSelectionListener(new ListSelectionListener ()
                {
                    public void valueChanged(ListSelectionEvent e)
                    {
                        JList l = (JList)e.getSource();
                        Object s= l.getSelectedValue();
                        JOptionPane.showMessageDialog(null,s,"消息框",JOptionPane.YES_OPTION);
                    }
                });
                
                // 增加按钮组
                buttonGroup.add(radioButton1);
                buttonGroup.add(radioButton2);
                
                // 增加各种按钮到JPanel中显示
                add(button);
                add(toggleButton);
                add(checkBox);
                add(radioButton1);            
                add(radioButton2);
                add(comboBox);
                
                add(list);
                
                this.setBorder(new EtchedBorder(EtchedBorder.LOWERED,Color.LIGHT_GRAY,Color.blue));
            }        
        }
        
        ////////////////////////////////////////////////////////////////////////////
        /**
         * 中间层模块,继承JPanel,初始化页签,并在页签中设置文本区,表格,
         * 文本区上下用分隔条分隔
         * JPanel--+
         *         -JTabbedPane--+
         *                          --Draw    --JTable  -JTextAreas -JText --JPopupMenu
         */
        class CenterPanel extends JPanel
        {
            public CenterPanel()
            {
                JTabbedPane tab = new JTabbedPane(JTabbedPane.TOP);
                
                JTextField textField = new JTextField("文本域,点击打开<文件按钮>可选择文件");
                textField.setActionCommand("textField");
                
                JTextPane textPane = new JTextPane();
                textPane.setCursor(new Cursor(Cursor.TEXT_CURSOR));
                textPane.setText("编辑器,试着点击文本区,试着拉动分隔条。");
                            
                textPane.addMouseListener(new MouseAdapter () 
                {
                    public void mousePressed (MouseEvent e)
                    {
                        JTextPane textPane = (JTextPane)e.getSource();
                        textPane.setText("编辑器点击命令成功");
                    //    textField.setText(""+textPane.getText());
                    }
                });
                
                /*
                UpperCaseDocument doc = new Document(); 
                textField.setDocumentsetDocument(doc);
                doc.addDocumentListener(new DocumentListener()
                {
                    public void changedUpdate(DocumentEvent e){}
                    public void removeUpdate(DocumentEvent e){}
                    public void insertUpdate(DocumentEvent e)
                    {
                        Document text = (Document)e.getDocument();
                        text.setText("复制成功");
                    }                
                });
                */
                
                JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,textField,textPane);
                
                    
                JTable table = new JTable(10,10);
                //table.showHorizontalLines(true);
                //table.showVerticalLines(true);
                //table.gridColor(Color.blue);
                
                JPanel pane  = new JPanel();
                pane.add(table.getTableHeader(),BorderLayout.NORTH);
                pane.add(table);
                            
                tab.addTab("文本演示",splitPane);
                //tab.addTab(table.getTableHeader());
                tab.addTab("表格演示",pane);
                tab.setPreferredSize(new Dimension(500,600));
                this.add(tab);
                this.setEnabled(true);            
            }
        }
        
        
        public static void main(String args[])
        {
            // 设置主框架属性,此处没有使用,可打开看看效果
            //try
            //{
            //    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            //}
            //catch  (Exception e){}
            new SwingTest();                        
        }
    }

    来自:

    http://www.yesky.com/382/1712382_1.shtml

    http://www.blogjava.net/gdws/archive/2006/10/27/77721.aspx

  • 相关阅读:
    (转)要在自己感兴趣的领域成为专家,要经过一万小时训练
    (学习日记)数据结构第一章中life游戏开发的学习记录
    (转)响应式Web设计是大势所趋还是时代的产物
    (学习日记)裘宗燕:C/C++ 语言中的表达式求值
    (转)如果你喜欢编程 给想做程序员的人的7个建议
    NHibernate 中删除数据的几种方法
    如何避免在安装SQL SERVER 2008时,出现Rule “Previous releases of Microsoft Visual Studio 2008″ failed.
    【转】A brief overview of Ncqrs
    爱博图微博图片批量下载小工具
    解释用Q号算出你的年龄的“奥妙”。。。
  • 原文地址:https://www.cnblogs.com/langtianya/p/2714914.html
Copyright © 2020-2023  润新知