Java Swing编程:特殊容器

开发 后端
Swing还提供我们许多特殊容器方便我们编程,JSplitPane(分割面板),JTabbedPane(多选项卡),JLayeredPane(层容器,允许组件互相重叠),最后讲两个复杂的容器JDesktopPane和JInternalFrame这些多是为了实现MDI(多文档界面)。

Swing还提供我们许多特殊容器方便我们编程,JSplitPane(分割面板),JTabbedPane(多选项卡),JLayeredPane(层容器,允许组件互相重叠),***讲两个复杂的容器JDesktopPane和JInternalFrame这些多是为了实现MDI(多文档界面),这些容器不是三言两语能说清楚的,所以我将以举例的方式(其中多是书中的例子,举的都不错,自己一个一个写可吃不消),如还有不懂的,请多查阅API文档。

eg:JSplitPane(分割面板)

  1. public class TestSplitPane  
  2. {  
  3.     Book[] books = new Book[]{  
  4.         new Book("Struts2权威指南" , new ImageIcon("ico/struts2.jpg") ,   
  5.             "全面介绍Struts2的各方/n面知识"),  
  6.         new Book("轻量级J2EE企业应用实战" , new ImageIcon("ico/j2ee.jpg") ,  
  7.             "介绍Struts、Spring和/nHibernate整合开发的知识"),  
  8.         new Book("基于J2EE的Ajax宝典" , new ImageIcon("ico/ajax.jpg") ,   
  9.             "全面介绍J2EE平台上Ajax/n开发的各方面知识")  
  10.     };  
  11.     JFrame jf = new JFrame("测试JSplitPane");  
  12.     JList bookList = new JList(books);  
  13.     JLabel bookCover = new JLabel();  
  14.     JTextArea bookDesc = new JTextArea();  
  15.  
  16.     public void init()  
  17.     {  
  18.         //为三个组件设置***大小  
  19.         bookList.setPreferredSize(new Dimension(150300));  
  20.         bookCover.setPreferredSize(new Dimension(300150));  
  21.         bookDesc.setPreferredSize(new Dimension(300150));  
  22.         //为下拉列表添加事件监听器  
  23.         bookList.addListSelectionListener(new ListSelectionListener()  
  24.         {  
  25.             public void valueChanged(ListSelectionEvent event)  
  26.             {    
  27.                 Book book = (Book)bookList.getSelectedValue();  
  28.                 bookCover.setIcon(book.getIco());  
  29.                 bookDesc.setText(book.getDesc());  
  30.             }  
  31.          });  
  32.         //创建一个垂直的分割面板,  
  33.         //将bookCover放在上面,将bookDesc放在下面 , 支持连续布局  
  34.         JSplitPane left = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true ,   
  35.             bookCover, new JScrollPane(bookDesc));  
  36.         //打开“一触即展”的特性  
  37.         left.setOneTouchExpandable(true);  
  38.         //下面代码设置分割条的大小。  
  39.         //left.setDividerSize(50);   
  40.         //设置该分割面板根据所包含组件的***大小来调整布局   
  41.         left.resetToPreferredSizes();  
  42.         //创建一个水平的分割面板  
  43.         //将left组件放在左边,将bookList组件放在右边  
  44.         JSplitPane content = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,  
  45.             left, bookList);  
  46.         jf.add(content);  
  47.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  48.         jf.pack();  
  49.         jf.setVisible(true);  
  50.     }  
  51.     public static void main(String[] args)  
  52.     {    
  53.         new TestSplitPane().init();  
  54.     }  
  55. }  
  56. class Book  
  57. {   
  58.     private String name;  
  59.     private Icon ico;  
  60.     private String desc;  
  61.  
  62.     public Book(){}  
  63.  
  64.     public Book(String name , Icon ico , String desc)  
  65.     {  
  66.         this.name = name;  
  67.         this.ico = ico;  
  68.         this.desc = desc;  
  69.     }  
  70.  
  71.     public void setName(String name)  
  72.     {  
  73.         this.name = name;  
  74.     }  
  75.     public String getName()  
  76.     {  
  77.          return this.name;  
  78.     }  
  79.  
  80.     public void setIco(Icon ico)  
  81.     {  
  82.         this.ico = ico;  
  83.     }  
  84.     public Icon getIco()  
  85.     {  
  86.          return this.ico;  
  87.     }  
  88.  
  89.     public void setDesc(String desc)  
  90.     {  
  91.         this.desc = desc;  
  92.     }  
  93.     public String getDesc()  
  94.     {  
  95.          return this.desc;  
  96.     }  
  97.     public String toString()  
  98.     {  
  99.         return name;  
  100.     }  

eg:JTabbedPane(多选项卡)

  1. public class TestJTabbedPane  
  2. {  
  3.     JFrame jf = new JFrame("测试Tab页面");  
  4.     //创建一个Tab页面的标签放在左边,采用换行布局策略的JTabbedPane  
  5.     JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.LEFT , JTabbedPane.WRAP_TAB_LAYOUT);     
  6.     ImageIcon icon = new ImageIcon("ico/close.gif");  
  7.     String[] layouts = {"换行布局" , "滚动条布局"};  
  8.     String[] positions = {"左边" , "顶部" , "右边" , "底部"};  
  9.     Map<String , String> books = new LinkedHashMap<String , String>();  
  10.  
  11.     public void init()  
  12.     {  
  13.         books.put("ROR敏捷开发***实践" , "ror.jpg");  
  14.         books.put("Struts2权威指南" , "struts2.jpg");  
  15.         books.put("基于J2EE的Ajax宝典" , "ajax.jpg");  
  16.         books.put("轻量级J2EE企业应用实战" , "j2ee.jpg");  
  17.         books.put("Spring2.0宝典" , "spring.jpg");  
  18.         String tip = "可看到本书的封面照片";  
  19.         //向JTabbedPane中添加5个Tab页面,指定了标题、图标和提示,但该Tab页面的组件为null  
  20.         for (String bookName : books.keySet())  
  21.         {  
  22.             tabbedPane.addTab(bookName, icon, null , tip);  
  23.         }  
  24.         jf.add(tabbedPane, BorderLayout.CENTER);  
  25.         //为JTabbedPane添加事件监听器  
  26.         tabbedPane.addChangeListener(new ChangeListener()  
  27.         {  
  28.             public void stateChanged(ChangeEvent event)  
  29.             {         
  30.                 //如果被选择的组件依然是空  
  31.                 if (tabbedPane.getSelectedComponent() == null)  
  32.                 {  
  33.                     //获取所选Tab页  
  34.                     int n = tabbedPane.getSelectedIndex();  
  35.                     //为指定标前页加载内容  
  36.                     loadTab(n);  
  37.                 }  
  38.             }  
  39.         });  
  40.         //系统默认选择***页,加载***页内容  
  41.         loadTab(0);  
  42.         tabbedPane.setPreferredSize(new Dimension(500 , 300));  
  43.         //增加控制标签布局、标签位置的单选按钮  
  44.         JPanel buttonPanel = new JPanel();  
  45.         ChangeAction action = new ChangeAction();  
  46.         buttonPanel.add(new ButtonPanel(action , "选择标签布局策略" ,layouts));  
  47.         buttonPanel.add (new ButtonPanel(action , "选择标签位置" ,positions));  
  48.         jf.add(buttonPanel, BorderLayout.SOUTH);  
  49.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  50.         jf.pack();  
  51.         jf.setVisible(true);  
  52.  
  53.     }  
  54.     //为指定标签页加载内容  
  55.     private void loadTab(int n)  
  56.     {  
  57.         String title = tabbedPane.getTitleAt(n);  
  58.         //根据标签页的标题获取对应图书封面  
  59.         ImageIcon bookImage = new ImageIcon("ico/" + books.get(title));  
  60.         tabbedPane.setComponentAt(n, new JLabel(bookImage));  
  61.         //改变标签页的图标  
  62.         tabbedPane.setIconAt(n, new ImageIcon("ico/open.gif"));  
  63.     }  
  64.     //定义改变标签页的布局策略,放置位置的监听器  
  65.     class ChangeAction implements ActionListener  
  66.     {  
  67.         public void actionPerformed(ActionEvent event)  
  68.         {  
  69.             JRadioButton source = (JRadioButton)event.getSource();  
  70.             String selection = source.getActionCommand();  
  71.             if (selection.equals(layouts[0]))  
  72.             {  
  73.                 tabbedPane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);  
  74.             }  
  75.             else if (selection.equals(layouts[1]))  
  76.             {  
  77.                 tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);  
  78.             }  
  79.             else if (selection.equals(positions[0]))  
  80.             {  
  81.                 tabbedPane.setTabPlacement(JTabbedPane.LEFT);  
  82.             }  
  83.             else if (selection.equals(positions[1]))  
  84.             {  
  85.                 tabbedPane.setTabPlacement(JTabbedPane.TOP);  
  86.             }  
  87.             else if (selection.equals(positions[2]))  
  88.             {  
  89.                 tabbedPane.setTabPlacement(JTabbedPane.RIGHT);  
  90.             }  
  91.             else if (selection.equals(positions[3]))  
  92.             {  
  93.                 tabbedPane.setTabPlacement(JTabbedPane.BOTTOM);  
  94.             }  
  95.         }  
  96.     }  
  97.  
  98.     public static void main(String[] args)  
  99.     {    
  100.         new TestJTabbedPane().init();  
  101.     }  
  102. }  
  103.  
  104. //定义一个JPanel类扩展类,该类的对象包含多个纵向排列的JRadioButton控件  
  105. //且Panel扩展类可以指定一个字符串作为TitledBorder  
  106. class ButtonPanel extends JPanel  
  107. {    
  108.     private ButtonGroup group;  
  109.     public ButtonPanel(TestJTabbedPane.ChangeAction action , String title, String[] labels)  
  110.     {    
  111.         setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title));  
  112.         setLayout(new BoxLayout(this, BoxLayout.X_AXIS));  
  113.         group = new ButtonGroup();  
  114.         for (int i = 0; labels!= null && i < labels.length; i++)  
  115.         {    
  116.             JRadioButton b = new JRadioButton(labels[i]);  
  117.             b.setActionCommand(labels[i]);  
  118.             add(b);  
  119.             //添加事件监听器  
  120.             b.addActionListener(action);  
  121.             group.add(b);  
  122.             b.setSelected(i == 0);  
  123.         }  
  124.     }  

eg:JLayeredPane(层容器,允许组件互相重叠)

  1. public class TestJLayeredPane  
  2. {  
  3.     JFrame jf = new JFrame("测试JLayeredPane");  
  4.     JLayeredPane layeredPane = new JLayeredPane();  
  5.     public void init()  
  6.     {  
  7.         //向layeredPane中添加3个组件  
  8.         layeredPane.add(new ContentPanel(10 , 20 , "Struts2权威指南" ,   
  9.             "ico/struts2.jpg"), JLayeredPane.MODAL_LAYER);  
  10.         layeredPane.add(new ContentPanel(100 , 60 , "RoR敏捷开发***实践",   
  11.             "ico/ror.jpg"), JLayeredPane.DEFAULT_LAYER);  
  12.         layeredPane.add(new ContentPanel(190 , 100 , "轻量级J2EE企业应用实战",   
  13.             "ico/j2ee.jpg"), 4);  
  14.         layeredPane.setPreferredSize(new Dimension(400300));  
  15.         layeredPane.setVisible(true);  
  16.         jf.add(layeredPane);  
  17.         jf.pack();  
  18.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  19.         jf.setVisible(true);  
  20.     }  
  21.     public static void main(String[] args)   
  22.     {  
  23.         new TestJLayeredPane().init();  
  24.     }  
  25. }  
  26. //扩展了JPanel类,可以直接创建一个放在指定位置,  
  27. //且有指定标题、放置指定图标的JPanel对象  
  28. class ContentPanel extends JPanel  
  29. {  
  30.     public ContentPanel(int xPos , int yPos , String title , String ico)  
  31.     {  
  32.         setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title));  
  33.         JLabel label = new JLabel(new ImageIcon(ico));  
  34.         add(label);  
  35.         setBounds(xPos , yPos , 160200);  
  36.     }  

以上3例子由于都是广告,我就不贴给大家了,没图片不影响程序的效果。

***是JDesktopPane和JInternalFrame来实现MDI

  1. public class TestInternalFrame  
  2. {  
  3.     final int DESKTOP_WIDTH = 480;  
  4.     final int DESKTOP_HEIGHT = 360;  
  5.     final int FRAME_DISTANCE = 30;  
  6.  
  7.     JFrame jf = new JFrame("MDI界面");  
  8.     //定义一个虚拟桌面  
  9.     private MyJDesktopPane desktop = new MyJDesktopPane();  
  10.     //保存下一个内部窗口的座标点  
  11.     private int nextFrameX;  
  12.     private int nextFrameY;  
  13.     //定义内部窗口为虚拟桌面的1/2大小  
  14.     private int width = DESKTOP_WIDTH / 2;  
  15.     private int height = DESKTOP_HEIGHT / 2;  
  16.     //为主窗口定义2个菜单  
  17.     JMenu fileMenu = new JMenu("文件");  
  18.     JMenu windowMenu = new JMenu("窗口");  
  19.     //定义newAction用于创建菜单和工具按钮  
  20.     Action newAction = new AbstractAction("新建"new ImageIcon("ico/new.png"))  
  21.     {  
  22.         public void actionPerformed(ActionEvent event)  
  23.         {  
  24.             //创建内部窗口  
  25.             final JInternalFrame iframe = new JInternalFrame("新文档",  
  26.                 true// 可改变大小  
  27.                 true// 可关闭  
  28.                 true// 可***化  
  29.                 true); // 可最小化  
  30.             iframe.add(new JScrollPane(new JTextArea(840)));  
  31.             //将内部窗口添加到虚拟桌面中  
  32.             desktop.add(iframe);  
  33.             //设置内部窗口的原始位置(内部窗口默认大小是0X0,放在0,0位置)  
  34.             iframe.reshape(nextFrameX, nextFrameY, width, height);  
  35.             //使该窗口可见,并尝试选中它  
  36.             iframe.show();  
  37.             //计算下一个内部窗口的位置  
  38.             nextFrameX += FRAME_DISTANCE;  
  39.             nextFrameY += FRAME_DISTANCE;  
  40.             if (nextFrameX + width > desktop.getWidth()) nextFrameX = 0;  
  41.             if (nextFrameY + height > desktop.getHeight()) nextFrameY = 0;  
  42.         }  
  43.     };  
  44.     //定义exitAction用于创建菜单和工具按钮  
  45.     Action exitAction = new AbstractAction("退出"new ImageIcon("ico/exit.png"))  
  46.     {  
  47.         public void actionPerformed(ActionEvent event)  
  48.         {  
  49.             System.exit(0);  
  50.         }  
  51.     };  
  52.  
  53.     public void init()  
  54.     {  
  55.         //为窗口安装菜单条和工具条  
  56.         JMenuBar menuBar = new JMenuBar();  
  57.         JToolBar toolBar = new JToolBar();  
  58.         jf.setJMenuBar(menuBar);  
  59.         menuBar.add(fileMenu);  
  60.         fileMenu.add(newAction);  
  61.         fileMenu.add(exitAction);  
  62.         toolBar.add(newAction);  
  63.         toolBar.add(exitAction);  
  64.         menuBar.add(windowMenu);  
  65.         JMenuItem nextItem = new JMenuItem("下一个");  
  66.         nextItem.addActionListener(new ActionListener()  
  67.         {  
  68.             public void actionPerformed(ActionEvent event)  
  69.             {  
  70.                 desktop.selectNextWindow();  
  71.             }  
  72.         });  
  73.         windowMenu.add(nextItem);  
  74.         JMenuItem cascadeItem = new JMenuItem("级联");  
  75.         cascadeItem.addActionListener(new ActionListener()  
  76.         {  
  77.             public void actionPerformed(ActionEvent event)  
  78.             {  
  79.                 //级联显示窗口,内部窗口的大小是外部窗口的0.75  
  80.                 desktop.cascadeWindows(FRAME_DISTANCE , 0.75);  
  81.             }  
  82.         });  
  83.         windowMenu.add(cascadeItem);  
  84.         JMenuItem tileItem = new JMenuItem("平铺");  
  85.         tileItem.addActionListener(new ActionListener()  
  86.         {  
  87.             public void actionPerformed(ActionEvent event)  
  88.             {  
  89.                 //平铺显示所有内部窗口  
  90.                 desktop.tileWindows();  
  91.             }  
  92.         });  
  93.         windowMenu.add(tileItem);  
  94.         final JCheckBoxMenuItem dragOutlineItem = new JCheckBoxMenuItem("仅显示拖动窗口的轮廓");  
  95.         dragOutlineItem.addActionListener(new ActionListener()  
  96.         {  
  97.             public void actionPerformed(ActionEvent event)  
  98.             {  
  99.                 //根据该菜单项是否选择来决定采用哪种拖动模式  
  100.                 desktop.setDragMode(dragOutlineItem.isSelected()   
  101.                     ? JDesktopPane.OUTLINE_DRAG_MODE  
  102.                     : JDesktopPane.LIVE_DRAG_MODE);  
  103.             }  
  104.         });  
  105.         windowMenu.add(dragOutlineItem);  
  106.         desktop.setPreferredSize(new Dimension(480360));  
  107.         //将虚拟桌面添加到***JFrame容器中  
  108.         jf.add(desktop);  
  109.         jf.add(toolBar , BorderLayout.NORTH);  
  110.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);  
  111.         jf.pack();  
  112.         jf.setVisible(true);  
  113.     }  
  114.  
  115.     public static void main(String[] args)  
  116.     {    
  117.         new TestInternalFrame().init();  
  118.     }  
  119. }  
  120. class MyJDesktopPane extends JDesktopPane  
  121. {  
  122.     //将所有窗口以级联方式显示,  
  123.     //其中offset是两个窗口的位移距离,scale是内部窗口与JDesktopPane的大小比例  
  124.     public void cascadeWindows(int offset , double scale)  
  125.     {  
  126.         //定义级联显示窗口时内部窗口的大小  
  127.         int width = (int)(getWidth() * scale);  
  128.         int height = (int)(getHeight() * scale);  
  129.         //用于保存级联窗口时每个窗口的位置  
  130.         int x = 0;  
  131.         int y = 0;  
  132.         for (JInternalFrame frame : getAllFrames())  
  133.         {    
  134.             try 
  135.             {    
  136.                 //取消内部窗口的***化,最小化  
  137.                 frame.setMaximum(false);  
  138.                 frame.setIcon(false);  
  139.                 //把窗口重新放置在指定位置  
  140.                 frame.reshape(x, y, width, height);  
  141.                 x += offset;  
  142.                 y += offset;  
  143.                 //如果到了虚拟桌面边界  
  144.                 if (x + width > getWidth()) x = 0;  
  145.                 if (y + height > getHeight()) y = 0;  
  146.             }  
  147.             catch (PropertyVetoException e)  
  148.             {}  
  149.         }  
  150.     }  
  151.     //将所有窗口以平铺方式显示  
  152.     public void tileWindows()  
  153.     {    
  154.         //统计所有窗口  
  155.         int frameCount = 0;  
  156.         for (JInternalFrame frame : getAllFrames())  
  157.         {  
  158.             frameCount++;  
  159.         }  
  160.         //计算需要多少行、多少列才可以平铺所有窗口  
  161.         int rows = (int) Math.sqrt(frameCount);  
  162.         int cols = frameCount / rows;  
  163.         //需要额外增加到其他列中的窗口  
  164.         int extra = frameCount % rows;  
  165.         //计算平铺时内部窗口的大小  
  166.         int width = getWidth() / cols;  
  167.         int height = getHeight() / rows;  
  168.         //用于保存平铺窗口时每个窗口在横向、纵向上的索引  
  169.         int x = 0;  
  170.         int y = 0;  
  171.         for (JInternalFrame frame : getAllFrames())  
  172.         {    
  173.             try 
  174.             {  
  175.                 //取消内部窗口的***化,最小化  
  176.                 frame.setMaximum(false);  
  177.                 frame.setIcon(false);  
  178.                 //将窗口放在指定位置  
  179.                 frame.reshape(x * width, y * height, width, height);  
  180.                 y++;  
  181.                 //每排完一列窗口  
  182.                 if (y == rows)  
  183.                 {  
  184.                     //开始排放下一列窗口  
  185.                     y = 0;  
  186.                     x++;  
  187.                     //如果额外多出的窗口与剩下的列数相等,则后面所有列都需要多排列一个窗口  
  188.                     if (extra == cols - x)  
  189.                     {  
  190.                         rows++;  
  191.                         height = getHeight() / rows;  
  192.                     }  
  193.                 }  
  194.             }  
  195.             catch (PropertyVetoException e)  
  196.             {}  
  197.         }  
  198.     }  
  199.     //选中下一个非图标窗口  
  200.     public void selectNextWindow()  
  201.     {    
  202.         JInternalFrame[] frames = getAllFrames();  
  203.         for (int i = 0; i < frames.length; i++)  
  204.         {    
  205.             if (frames[i].isSelected())  
  206.             {    
  207.                 // 找出下一个非最小化的窗口,尝试选中它,  
  208.                 //如果选中失败,则继续尝试选中下一个窗口  
  209.                 int next = (i + 1) % frames.length;  
  210.                 while (next != i)  
  211.                 {  
  212.                     //如果该窗口不是处于最小化状态  
  213.                     if (!frames[next].isIcon())  
  214.                     {  
  215.                         try 
  216.                         {    
  217.                             frames[next].setSelected(true);  
  218.                             frames[next].toFront();  
  219.                             frames[i].toBack();  
  220.                             return;  
  221.                         }  
  222.                         catch (PropertyVetoException e)  
  223.                         {}  
  224.                     }  
  225.                     next = (next + 1) % frames.length;  
  226.                 }  
  227.             }  
  228.         }  
  229.     }  

大家注意看继承JDesktopPane的类MyJDesktopPane

其中的3个方法非常有用,这是对窗口控制的基本方法(级联,平铺,选下个窗口),大家可以保留下来,以备后用。

原文链接:http://blog.csdn.net/terryzero/article/details/3770982

【编辑推荐】

  1. Java Swing编程:基本组件
  2. Java Swing用户界面设计:序
  3. 用Swing制作精美的图层叠加图
  4. 简述Java图形用户界面设计(Swing)
  5. Effective Java 创建和销毁对象
责任编辑:林师授 来源: terryzero的博客
相关推荐

2012-01-17 14:09:54

JavaSwing

2012-01-17 14:05:29

JavaSwing

2012-01-17 13:46:55

JavaSwing

2012-01-17 13:53:16

JavaSwing

2012-01-17 13:16:34

JavaSwing

2009-07-10 13:36:32

Swing容器

2012-04-28 10:25:11

JavaSwing

2012-04-24 09:40:42

SwingJava

2012-04-27 15:21:45

JavaSwing

2009-07-10 13:20:37

Swing容器组件

2012-01-17 13:58:17

JavaSwing

2012-02-02 09:21:39

编程

2012-01-17 14:01:33

JavaSwing

2009-07-10 11:45:44

Java Swing

2009-07-10 14:20:01

AcceleratorJava Swing

2009-07-16 11:13:50

Java Swing

2009-07-10 13:09:53

.Net与Java S

2009-07-10 10:47:01

Java Swing

2009-07-10 15:10:02

Java Swing经

2023-07-03 09:59:00

并发编程并发容器
点赞
收藏

51CTO技术栈公众号