java swing 添加 jcheckbox復選框


最近接觸了一點Java的GUI編程,也就是由Java AWT更新而來的Java Swing。

  總體上而言,Java Swing編程有兩大特點:麻煩、效果差。

  麻煩是說由於設計器的使用不方便(如果您希望使用窗體設計器通過快速拖拽控件建立您的Java Swing GUI程序,請您使用MyEclipse 8.5以上版本,並且需要最高使用權限),所有代碼都得手寫,如果沒有好的編碼規范和注釋習慣。自己都會被代碼淹沒。

  效果差是指運行時的界面。具體的您可以自己嘗試發現。

  

  那么我們通過一段代碼來創建屬於我們的窗體:

復制代碼
 1 import javax.swing.JFrame;
 2 
 3 /**
 4  * 我的第一個Java窗體
 5  * 
 6  * @author Johness
 7  *
 8  */
 9 public class MyJFrame extends JFrame{
10     
11     
12     
13 }
復制代碼

  然后通過main方法來測試:

  

  運行后,窗體在屏幕左上角顯現並且是最小化的形式。

  

  呵呵,那么關於設置窗體的顯示我就不再贅述了,值得注意的是窗體的布局必須設置。

  小貼士:使用setLayout設置布局,參數傳遞null;

 

  我們討論一下怎樣在窗體的表格中顯示復選框。

  即實現如下效果:

  

  我隨便拖了些控件(數據是老師給的……)。

  好了,我們來一步步實現。

 

  小貼士二:使用add方法向控件添加內容控件。

  ①首先我們需要面板(JPanel)或其他容器控件承載表格(JTable),值得一提的是:由於窗體本身就是容器型控件,您可以考慮將表格單個地放置在窗體上。

  ②然后我們需要將表格對象創建出來並放入該容器控件,大家可以參考手冊(如JDK_API_1_6_zh_CN.CHM)創建表格控件。值得一提的是在這七個構造方法中,設計器(如果您使用了MyEclipse)使用的是JTable(TableModel dm)這個版本。而一般情況使用JTable(Vector rowData, Vector columnNames)這個版本的居多(不包括我)。如果是我,可能會選擇使用設計器的版本。

  可能有細心的朋友會發現說:設計器的版本很不方便,因為需要傳遞的是接口,我們必須寫一個類實現該接口並構造實例作為參數傳遞,麻煩,不如直接使用JTable(Object[][] rowData, Object[] columnNames)這個版本。

  那么在這里我向不知道“匿名內部類”(老師是這樣稱呼的,沒考證)的朋友普及一下Java的匿名內部類。

  在Java方法中,如果參數需要傳遞接口,可以在調用方法時傳遞一個(匿名)對象,該對象是一個不具名的類的實例,該對象所屬類實現了方法參數的接口。

  比如上面的例子JTable(TableModel dm),這是JTable的構造方法,需要的是一個TableModel接口類型的參數(這里只是舉例,實際運用比較復雜),我們可以使用如下寫法:JTable table = new JTable(new TableModel());

  毫無疑問,這種寫法是錯誤的,但是如果這樣寫就不是了:

復制代碼
 1 import javax.swing.*;
 2 import javax.swing.event.*;
 3 import javax.swing.table.*;
 4 
 5 
 6 public class MyFirstJFrame extends JFrame {
 7     public MyFirstJFrame() {
 8         setLayout(null);
 9         
10         JTable table = new JTable(new TableModel(){
11 
12             @Override
13             public int getRowCount() {
14                 // TODO Auto-generated method stub
15                 return 0;
16             }
17 
18             @Override
19             public int getColumnCount() {
20                 // TODO Auto-generated method stub
21                 return 0;
22             }
23 
24             @Override
25             public String getColumnName(int columnIndex) {
26                 // TODO Auto-generated method stub
27                 return null;
28             }
29 
30             @Override
31             public Class<?> getColumnClass(int columnIndex) {
32                 // TODO Auto-generated method stub
33                 return null;
34             }
35 
36             @Override
37             public boolean isCellEditable(int rowIndex, int columnIndex) {
38                 // TODO Auto-generated method stub
39                 return false;
40             }
41 
42             @Override
43             public Object getValueAt(int rowIndex, int columnIndex) {
44                 // TODO Auto-generated method stub
45                 return null;
46             }
47 
48             @Override
49             public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
50                 // TODO Auto-generated method stub
51                 
52             }
53 
54             @Override
55             public void addTableModelListener(TableModelListener l) {
56                 // TODO Auto-generated method stub
57                 
58             }
59 
60             @Override
61             public void removeTableModelListener(TableModelListener l) {
62                 // TODO Auto-generated method stub
63                 
64             }});
65     }
66 }
復制代碼

  我可能需要解釋一下這些代碼:首先是JTable table = new JTable(new TableModel(){});可以看出來,大括號中間的部分是一些需要重寫的方法。

  那么大家應該怎樣理解這一句代碼呢?我們分解一下(new TableModel(){})。我們應該怎么看待?大家回想一下我以上說過的匿名內部類的定義。我們可以這樣看,new ……()是構造方法,調用來構造一個匿名對象,其后的{}不是Java的特殊語法,但是Java中可以將方法定義在里面(這里的方法生命周期與匿名對象相 同),當然,此處是用於實現接口的方法。

  清晰一點了吧?我們再來拆分:TableModel我們可以在其前面補充一個不存在的類類名,比如MyTableModel。好了,我們完整再 現一下:new MyTableModel:TableModel(){}也就是說大家可以想象成(new TableModel(){})是在聲明一個匿名對象,它屬於一個不具名的類(如MyTableModel),該類實現了TableModel接口。而由 於語法限制,不能全部寫出來所以省略了[MyTableModel:]。當然,這只是我們的推理,大家理解記憶哈。

  注:這里的匿名對象只沒有引用指向(即沒有變量名)的對象。

  實際上我們使用匿名內部類的地方很多,比如添加事件監聽。但是“上面創建JTable的方法是只作為示例,絕大多數是不會如此用的”,大家謹記。

  我會在隨筆結尾貼出全部代碼,其中創建JTable的代碼是使用了設計器的構造方式。

  ③設置表格渲染。在詳細說明之前我先解釋一下JTable的顯示原理:

  首先是數據來源,您使用JTable的構造方法,大部分重載中參數即包含了數據,比如JTable(Vector rowData, Vector columnNames)中Vector保存的數據(Vector相當於數組)。

  其次是表格樣式,表格將數據和如何顯示數據(比如列數量、列名稱、是否可編輯)保存在其數據模版中,該模版實現自接口TableModel。

  最后,表格(每一個單元格)可以設置渲染效果。

  我把完整的代碼貼出來:

復制代碼
  1 import java.awt.Component;
  2  import java.awt.event.ActionEvent;
  3  import java.awt.event.ActionListener;
  4  
  5  import javax.swing.*;
  6  import javax.swing.table.*;
  7  
  8  
  9  public class MyFirstJFrame extends JFrame {
 10      
 11      // 作為測試的main方法
 12      public static void main(String[] args) {
 13          new MyFirstJFrame().setVisible(true);
 14      }
 15      
 16      /**
 17       * 構造方法
 18       */
 19      public MyFirstJFrame() {
 20          InitialComponent();
 21      }
 22      
 23      /**
 24       * 初始化組件的方法
 25       */
 26      private void InitialComponent(){
 27          // 設置窗體參數
 28  
 29          // 設置布局模式
 30           setLayout(null);
 31          // 設置窗體大小
 32          setSize(480, 360);
 33          // 設置窗體居中(非常規方法)
 34           setLocationRelativeTo(null);
 35          // 關閉窗體退出程序
 36          setDefaultCloseOperation(DISPOSE_ON_CLOSE);
 37          
 38          // 初始化面板
 39          panel = new JPanel();
 40          panel.setSize(this.getWidth(), this.getHeight());
 41          panel.setLocation(0,0);
 42          panel.setLayout(null);
 43          
 44          // 初始化表格
 45          table = new JTable(new DefaultTableModel(new Object[][]{{"第一行"},{"第二行"},{"第三行"},{"第四行"}}, new String[]{"測試行1","測試行2"}){
 46              /* (non-Javadoc)
 47               * 重寫方法,判斷表單元格是否可編輯
 48               * 可以通過row和column索引判斷某一個單元格是否可編輯
 49               * 此處設為都不可編輯
 50               * @see javax.swing.table.DefaultTableModel#isCellEditable(int, int)
 51               */
 52              @Override
 53              public boolean isCellEditable(int row, int column) {
 54                  return false;
 55              }
 56          });
 57          
 58          // 開始向表格中添加復選框(注意:此示例較為簡單,缺省很多判斷,也沒有動態代碼支持)
 59          // 通過設置列渲染
 60          
 61          // 方法一:直接方式 使用TableColumn的setCellRenderer方法(推薦)
 62          // 此方法可以設置某一列的渲染(即使用某一個組件--即控件來顯示單元格數據)
 63          table.getColumnModel().getColumn(1).setCellRenderer(new TableCellRenderer(){
 64  
 65               /*(non-Javadoc)
 66               * 此方法用於向方法調用者返回某一單元格的渲染器(即顯示數據的組建--或控件)
 67               * 可以為JCheckBox JComboBox JTextArea 等
 68               * @see javax.swing.table.TableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int)
 69               */
 70              @Override
 71              public Component getTableCellRendererComponent(JTable table,
 72                      Object value, boolean isSelected, boolean hasFocus,
 73                      int row, int column) {
 74                  // 創建用於返回的渲染組件
 75                  JCheckBox ck = new JCheckBox();
 76                  // 使具有焦點的行對應的復選框選中                     
77 ck.setSelected(isSelected);
//設置背景顏色  這里是設置jcheckbox的背景顏色 直接設置為透明,我這里是用了一種明暗交替的顏色轉換,所以背景顏色設置了一下                 
ck.setOpaque(false);
78 // 設置單選box.setSelected(hasFocus); 79 // 使復選框在單元格內居中顯示 80 ck.setHorizontalAlignment((int) 0.5f); 81 return ck; 82 }}); 83 84 // 方法二:先設置列編輯器,然后設置單元格渲染 85 // 設置列編輯器 86 // 在以復選框為對象設置列編輯器時,必須保證該列能夠被編輯,否則無法更改狀態 87 // (此步驟可以省略,省略時不要忘記將列設為不可編輯) 88 // table.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(new JCheckBox())); 89 90 // 設置單元格渲染(這里是設置表格級別的渲染) 91 /*table.setDefaultRenderer(Object.class, new TableCellRenderer(){ 92 93 @Override 94 public Component getTableCellRendererComponent(JTable table, 95 Object value, boolean isSelected, boolean hasFocus, 96 int row, int column) { 97 // 判斷是否為需要渲染的列 98 if(column == 1){ 99 // 和方法一基本一致 100 JCheckBox box = new JCheckBox(); 101 box.setSelected(isSelected); 102 // 設置單選box.setSelected(hasFocus); 103 box.setHorizontalAlignment((int) CENTER_ALIGNMENT); // 0.5f 104 return box; 105 } 106 // 如果不是需要渲染的列,封裝文本域顯示數據 107 return new JTextArea(value.toString()); 108 }});*/ 109 110 // 在多選是需要按住Ctrl鍵或者鼠標按住拖過連續的需要選中的行,應該給用戶說明 111 // 第一種方法是被推薦的,因為它具有選中的高亮顯示,界面能更加友好 112 table.setSize(panel.getWidth(),panel.getHeight() - 90); 113 table.setLocation(0, 0); 114 115 116 btn = new JButton("Test"); 117 btn.setSize(80,40); 118 btn.setLocation((panel.getWidth()) / 2 - 40, panel.getHeight() - 80); 119 120 // 按鈕點擊時顯示當前選中項 121 btn.addActionListener(new ActionListener(){ 122 123 @Override 124 public void actionPerformed(ActionEvent e) { 125 for(int rowindex : table.getSelectedRows()){ 126 JOptionPane.showMessageDialog(null, rowindex + " " + table.getValueAt(rowindex, 0)); 127 } 128 }}); 129 130 panel.add(table); 131 panel.add(btn); 132 this.add(panel); 133 134 } 135 136 // 定義一些必要的組件 137 private JPanel panel; 138 private JTable table; 139 private JButton btn; 140 }
復制代碼

 

  上面的代碼有一些缺陷,大家需要做一些修改。實際上我也不希望貼上完全無誤的perfect的代碼,對需要學習的朋友不是好事兒。

 

  總結:充分理解Java的方法返回值作為判斷依據。

  1、匿名內部類(匿名對象后{}的妙用)。

  2、窗體的布局:默認布局為(最后添加?)的控件占據其窗體的全部空間。

  3、編輯器、渲染。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM