程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java Swing編程:特殊容器

Java Swing編程:特殊容器

編輯:關於JAVA

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. public void init()
  16. {
  17. //為三個組件設置最佳大小
  18. bookList.setPreferredSize(new Dimension(150, 300));
  19. bookCover.setPreferredSize(new Dimension(300, 150));
  20. bookDesc.setPreferredSize(new Dimension(300, 150));
  21. //為下拉列表添加事件監聽器
  22. bookList.addListSelectionListener(new ListSelectionListener()
  23. {
  24. public void valueChanged(ListSelectionEvent event)
  25. {
  26. Book book = (Book)bookList.getSelectedValue();
  27. bookCover.setIcon(book.getIco());
  28. bookDesc.setText(book.getDesc());
  29. }
  30. });
  31. //創建一個垂直的分割面板,
  32. //將bookCover放在上面,將bookDesc放在下面 , 支持連續布局
  33. JSPlitPane left = new JSplitPane(JSPlitPane.VERTICAL_SPLIT, true ,
  34. bookCover, new JScrollPane(bookDesc));
  35. //打開“一觸即展”的特性
  36. left.setOneTouchExpandable(true);
  37. //下面代碼設置分割條的大小。
  38. //left.setDividerSize(50);
  39. //設置該分割面板根據所包含組件的最佳大小來調整布局
  40. left.resetToPreferredSizes();
  41. //創建一個水平的分割面板
  42. //將left組件放在左邊,將bookList組件放在右邊
  43. JSPlitPane content = new JSplitPane(JSPlitPane.HORIZONTAL_SPLIT,
  44. left, bookList);
  45. jf.add(content);
  46. jf.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
  47. jf.pack();
  48. jf.setVisible(true);
  49. }
  50. public static void main(String[] args)
  51. {
  52. new TestSplitPane().init();
  53. }
  54. }
  55. class Book
  56. {
  57. private String name;
  58. private Icon ico;
  59. private String desc;
  60. public Book(){}
  61. public Book(String name , Icon ico , String desc)
  62. {
  63. this.name = name;
  64. this.ico = ico;
  65. this.desc = desc;
  66. }
  67. public void setName(String name)
  68. {
  69. this.name = name;
  70. }
  71. public String getName()
  72. {
  73. return this.name;
  74. }
  75. public void setIco(Icon ico)
  76. {
  77. this.ico = ico;
  78. }
  79. public Icon getIco()
  80. {
  81. return this.ico;
  82. }
  83. public void setDesc(String desc)
  84. {
  85. this.desc = desc;
  86. }
  87. public String getDesc()
  88. {
  89. return this.desc;
  90. }
  91. public String toString()
  92. {
  93. return name;
  94. }
  95. }

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. public void init()
  11. {
  12. books.put("ROR敏捷開發最佳實踐" , "ror.jpg");
  13. books.put("Struts2權威指南" , "struts2.jpg");
  14. books.put("基於J2EE的AJax寶典" , "AJax.jpg");
  15. books.put("輕量級J2EE企業應用實戰" , "J2EE.jpg");
  16. books.put("Spring2.0寶典" , "spring.jpg");
  17. String tip = "可看到本書的封面照片";
  18. //向JTabbedPane中添加5個Tab頁面,指定了標題、圖標和提示,但該Tab頁面的組件為null
  19. for (String bookName : books.keySet())
  20. {
  21. tabbedPane.addTab(bookName, icon, null , tip);
  22. }
  23. jf.add(tabbedPane, BorderLayout.CENTER);
  24. //為JTabbedPane添加事件監聽器
  25. tabbedPane.addChangeListener(new ChangeListener()
  26. {
  27. public void stateChanged(ChangeEvent event)
  28. {
  29. //如果被選擇的組件依然是空
  30. if (tabbedPane.getSelectedComponent() == null)
  31. {
  32. //獲取所選Tab頁
  33. int n = tabbedPane.getSelectedIndex();
  34. //為指定標前頁加載內容
  35. loadTab(n);
  36. }
  37. }
  38. });
  39. //系統默認選擇第一頁,加載第一頁內容
  40. loadTab(0);
  41. tabbedPane.setPreferredSize(new Dimension(500 , 300));
  42. //增加控制標簽布局、標簽位置的單選按鈕
  43. JPanel buttonPanel = new JPanel();
  44. ChangeAction action = new ChangeAction();
  45. buttonPanel.add(new ButtonPanel(action , "選擇標簽布局策略" ,layouts));
  46. buttonPanel.add (new ButtonPanel(action , "選擇標簽位置" ,positions));
  47. jf.add(buttonPanel, BorderLayout.SOUTH);
  48. jf.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
  49. jf.pack();
  50. jf.setVisible(true);
  51. }
  52. //為指定標簽頁加載內容
  53. private void loadTab(int n)
  54. {
  55. String title = tabbedPane.getTitleAt(n);
  56. //根據標簽頁的標題獲取對應圖書封面
  57. ImageIcon bookImage = new ImageIcon("ico/" + books.get(title));
  58. tabbedPane.setComponentAt(n, new JLabel(bookImage));
  59. //改變標簽頁的圖標
  60. tabbedPane.setIconAt(n, new ImageIcon("ico/open.gif"));
  61. }
  62. //定義改變標簽頁的布局策略,放置位置的監聽器
  63. class ChangeAction implements ActionListener
  64. {
  65. public void actionPerformed(ActionEvent event)
  66. {
  67. JRadioButton source = (JRadioButton)event.getSource();
  68. String selection = source.getActionCommand();
  69. if (selection.equals(layouts[0]))
  70. {
  71. tabbedPane.setTabLayoutPolicy(JTabbedPane.WRAP_TAB_LAYOUT);
  72. }
  73. else if (selection.equals(layouts[1]))
  74. {
  75. tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
  76. }
  77. else if (selection.equals(positions[0]))
  78. {
  79. tabbedPane.setTabPlacement(JTabbedPane.LEFT);
  80. }
  81. else if (selection.equals(positions[1]))
  82. {
  83. tabbedPane.setTabPlacement(JTabbedPane.TOP);
  84. }
  85. else if (selection.equals(positions[2]))
  86. {
  87. tabbedPane.setTabPlacement(JTabbedPane.RIGHT);
  88. }
  89. else if (selection.equals(positions[3]))
  90. {
  91. tabbedPane.setTabPlacement(JTabbedPane.BOTTOM);
  92. }
  93. }
  94. }
  95. public static void main(String[] args)
  96. {
  97. new TestJTabbedPane().init();
  98. }
  99. }
  100. //定義一個JPanel類擴展類,該類的對象包含多個縱向排列的JRadioButton控件
  101. //且Panel擴展類可以指定一個字符串作為TitledBorder
  102. class ButtonPanel extends JPanel
  103. {
  104. private ButtonGroup group;
  105. public ButtonPanel(TestJTabbedPane.ChangeAction action , String title, String[] labels)
  106. {
  107. setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), title));
  108. setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
  109. group = new ButtonGroup();
  110. for (int i = 0; labels!= null && i < labels.length; i++)
  111. {
  112. JRadioButton b = new JRadioButton(labels[i]);
  113. b.setActionCommand(labels[i]);
  114. add(b);
  115. //添加事件監聽器
  116. b.addActionListener(action);
  117. group.add(b);
  118. b.setSelected(i == 0);
  119. }
  120. }
  121. }

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(400, 300));
  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 , 160, 200);
  36. }
  37. }

以上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. JFrame jf = new JFrame("MDI界面");
  7. //定義一個虛擬桌面
  8. private MyJDesktopPane desktop = new MyJDesktopPane();
  9. //保存下一個內部窗口的座標點
  10. private int nextFrameX;
  11. private int nextFrameY;
  12. //定義內部窗口為虛擬桌面的1/2大小
  13. private int width = DESKTOP_WIDTH / 2;
  14. private int height = DESKTOP_HEIGHT / 2;
  15. //為主窗口定義2個菜單
  16. JMenu fileMenu = new JMenu("文件");
  17. JMenu windowMenu = new JMenu("窗口");
  18. //定義newAction用於創建菜單和工具按鈕
  19. Action newAction = new AbstractAction("新建", new ImageIcon("ico/new.png"))
  20. {
  21. public void actionPerformed(ActionEvent event)
  22. {
  23. //創建內部窗口
  24. final JInternalFrame iframe = new JInternalFrame("新文檔",
  25. true, // 可改變大小
  26. true, // 可關閉
  27. true, // 可最大化
  28. true); // 可最小化
  29. iframe.add(new JScrollPane(new JTextArea(8, 40)));
  30. //將內部窗口添加到虛擬桌面中
  31. desktop.add(iframe);
  32. //設置內部窗口的原始位置(內部窗口默認大小是0X0,放在0,0位置)
  33. iframe.reshape(nextFrameX, nextFrameY, width, height);
  34. //使該窗口可見,並嘗試選中它
  35. iframe.show();
  36. //計算下一個內部窗口的位置
  37. nextFrameX += FRAME_DISTANCE;
  38. nextFrameY += FRAME_DISTANCE;
  39. if (nextFrameX + width > desktop.getWidth()) nextFrameX = 0;
  40. if (nextFrameY + height > desktop.getHeight()) nextFrameY = 0;
  41. }
  42. };
  43. //定義exitAction用於創建菜單和工具按鈕
  44. Action exitAction = new AbstractAction("退出", new ImageIcon("ico/exit.png"))
  45. {
  46. public void actionPerformed(ActionEvent event)
  47. {
  48. System.exit(0);
  49. }
  50. };
  51. public void init()
  52. {
  53. //為窗口安裝菜單條和工具條
  54. JMenuBar menuBar = new JMenuBar();
  55. JToolBar toolBar = new JToolBar();
  56. jf.setJMenuBar(menuBar);
  57. menuBar.add(fileMenu);
  58. fileMenu.add(newAction);
  59. fileMenu.add(exitAction);
  60. toolBar.add(newAction);
  61. toolBar.add(exitAction);
  62. menuBar.add(windowMenu);
  63. JMenuItem nextItem = new JMenuItem("下一個");
  64. nextItem.addActionListener(new ActionListener()
  65. {
  66. public void actionPerformed(ActionEvent event)
  67. {
  68. desktop.selectNextWindow();
  69. }
  70. });
  71. windowMenu.add(nextItem);
  72. JMenuItem cascadeItem = new JMenuItem("級聯");
  73. cascadeItem.addActionListener(new ActionListener()
  74. {
  75. public void actionPerformed(ActionEvent event)
  76. {
  77. //級聯顯示窗口,內部窗口的大小是外部窗口的0.75
  78. desktop.cascadeWindows(FRAME_DISTANCE , 0.75);
  79. }
  80. });
  81. windowMenu.add(cascadeItem);
  82. JMenuItem tileItem = new JMenuItem("平鋪");
  83. tileItem.addActionListener(new ActionListener()
  84. {
  85. public void actionPerformed(ActionEvent event)
  86. {
  87. //平鋪顯示所有內部窗口
  88. desktop.tileWindows();
  89. }
  90. });
  91. windowMenu.add(tileItem);
  92. final JCheckBoxMenuItem dragOutlineItem = new JCheckBoxMenuItem("僅顯示拖動窗口的輪廓");
  93. dragOutlineItem.addActionListener(new ActionListener()
  94. {
  95. public void actionPerformed(ActionEvent event)
  96. {
  97. //根據該菜單項是否選擇來決定采用哪種拖動模式
  98. desktop.setDragMode(dragOutlineItem.isSelected()
  99. ? JDesktopPane.OUTLINE_DRAG_MODE
  100. : JDesktopPane.LIVE_DRAG_MODE);
  101. }
  102. });
  103. windowMenu.add(dragOutlineItem);
  104. desktop.setPreferredSize(new Dimension(480, 360));
  105. //將虛擬桌面添加到頂級JFrame容器中
  106. jf.add(desktop);
  107. jf.add(toolBar , BorderLayout.NORTH);
  108. jf.setDefaultCloSEOperation(JFrame.EXIT_ON_CLOSE);
  109. jf.pack();
  110. jf.setVisible(true);
  111. }
  112. public static void main(String[] args)
  113. {
  114. new TestInternalFrame().init();
  115. }
  116. }
  117. class MyJDesktopPane extends JDesktopPane
  118. {
  119. //將所有窗口以級聯方式顯示,
  120. //其中offset是兩個窗口的位移距離,scale是內部窗口與JDesktopPane的大小比例
  121. public void cascadeWindows(int offset , double scale)
  122. {
  123. //定義級聯顯示窗口時內部窗口的大小
  124. int width = (int)(getWidth() * scale);
  125. int height = (int)(getHeight() * scale);
  126. //用於保存級聯窗口時每個窗口的位置
  127. int x = 0;
  128. int y = 0;
  129. for (JInternalFrame frame : getAllFrames())
  130. {
  131. try
  132. {
  133. //取消內部窗口的最大化,最小化
  134. frame.setMaximum(false);
  135. frame.setIcon(false);
  136. //把窗口重新放置在指定位置
  137. frame.reshape(x, y, width, height);
  138. x += offset;
  139. y += offset;
  140. //如果到了虛擬桌面邊界
  141. if (x + width > getWidth()) x = 0;
  142. if (y + height > getHeight()) y = 0;
  143. }
  144. catch (PropertyVetoException e)
  145. {}
  146. }
  147. }
  148. //將所有窗口以平鋪方式顯示
  149. public void tileWindows()
  150. {
  151. //統計所有窗口
  152. int frameCount = 0;
  153. for (JInternalFrame frame : getAllFrames())
  154. {
  155. frameCount++;
  156. }
  157. //計算需要多少行、多少列才可以平鋪所有窗口
  158. int rows = (int) Math.sqrt(frameCount);
  159. int cols = frameCount / rows;
  160. //需要額外增加到其他列中的窗口
  161. int extra = frameCount % rows;
  162. //計算平鋪時內部窗口的大小
  163. int width = getWidth() / cols;
  164. int height = getHeight() / rows;
  165. //用於保存平鋪窗口時每個窗口在橫向、縱向上的索引
  166. int x = 0;
  167. int y = 0;
  168. for (JInternalFrame frame : getAllFrames())
  169. {
  170. try
  171. {
  172. //取消內部窗口的最大化,最小化
  173. frame.setMaximum(false);
  174. frame.setIcon(false);
  175. //將窗口放在指定位置
  176. frame.reshape(x * width, y * height, width, height);
  177. y++;
  178. //每排完一列窗口
  179. if (y == rows)
  180. {
  181. //開始排放下一列窗口
  182. y = 0;
  183. x++;
  184. //如果額外多出的窗口與剩下的列數相等,則後面所有列都需要多排列一個窗口
  185. if (extra == cols - x)
  186. {
  187. rows++;
  188. height = getHeight() / rows;
  189. }
  190. }
  191. }
  192. catch (PropertyVetoException e)
  193. {}
  194. }
  195. }
  196. //選中下一個非圖標窗口
  197. public void selectNextWindow()
  198. {
  199. JInternalFrame[] frames = getAllFrames();
  200. for (int i = 0; i < frames.length; i++)
  201. {
  202. if (frames[i].isSelected())
  203. {
  204. // 找出下一個非最小化的窗口,嘗試選中它,
  205. //如果選中失敗,則繼續嘗試選中下一個窗口
  206. int next = (i + 1) % frames.length;
  207. while (next != i)
  208. {
  209. //如果該窗口不是處於最小化狀態
  210. if (!frames[next].isIcon())
  211. {
  212. try
  213. {
  214. frames[next].setSelected(true);
  215. frames[next].toFront();
  216. frames[i].toBack();
  217. return;
  218. }
  219. catch (PropertyVetoException e)
  220. {}
  221. }
  222. next = (next + 1) % frames.length;
  223. }
  224. }
  225. }
  226. }
  227. }

大家注意看繼承JDesktopPane的類MyJDesktopPane

其中的3個方法非常有用,這是對窗口控制的基本方法(級聯,平鋪,選下個窗口),大家可以保留下來,以備後用。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved