总体上而言,Java Swing编程有两大特点:麻烦、效果差。
麻烦是说由于设计器的使用不方便(如果您希望使用窗体设计器通过快速拖拽控件建立您的Java Swing GUI程序,请您使用MyEclipse 8.5以上版本,并且需要最高使用权限),所有代码都得手写,如果没有好的编码规范和注释习惯。自己都会被代码淹没。效果差是指运行时的界面。具体的您可以自己尝试发现。
通过一段代码来创建属于我们的窗体:
1 import javax.swing.JFrame; 2 2 3 3 /** 4 4 * 我的第一个Java窗体 5 5 * 6 6 * @author Johness 7 7 * 8 8 */ 9 9 public class MyJFrame extends JFrame{ 10 10 11 11 12 12 13 13 }
然后通过main方法来测试:
运行后,窗体在屏幕左上角显现并且是最小化的形式。那么关于设置窗体的显示就不再赘述了,值得注意的是窗体的布局必须设置。
小贴士:使用setLayout设置布局,参数传递null;
讨论一下怎样在窗体的表格中显示复选框。即实现如下效果:
小贴士二:使用add方法向控件添加内容控件。
①首先我们需要面板(JPanel)或其他容器控件承载表格(JTable),值得一提的是:由于窗体本身就是容器型控件,您可以考虑将表格单个地放置在窗体上。
②然后我们需要将表格对象创建出来并放入该容器控件,(如JDK_API_1_6_zh_CN.CHM)创建表格控件。值得一提的是在这七个构造方法中,设计器(如果您使用了MyEclipse)使用的是JTable(TableModel dm)
这个版本。而一般情况使用
JTable(Vector rowData,Vector columnNames)
在Java方法中,如果参数需要传递接口,可以在调用方法时传递一个(匿名)对象,该对象是一个不具名的类的实例,该对象所属类实现了方法参数的接口。比如上面的例子JTable(TableModel dm)
,这是JTable的构造方法,需要的是一个TableModel接口类型的参数(这里只是举例,实际运用比较复杂),我们可以使用如下写法:JTable table = new JTable(new TableModel());
正确写法如下:
1 import javax.swing.*; 2 2 import javax.swing.event.*; 3 3 import javax.swing.table.*; 4 4 5 5 6 6 public class MyFirstJFrame extends JFrame { 7 7 public MyFirstJFrame() { 8 8 setLayout(null); 9 9 10 10 JTable table = new JTable(new TableModel(){ 11 11 12 12 @Override 13 13 public int getRowCount() { 14 14 // TODO Auto-generated method stub 15 15 return 0; 16 16 } 17 17 18 18 @Override 19 19 public int getColumnCount() { 20 20 // TODO Auto-generated method stub 21 21 return 0; 22 22 } 23 23 24 24 @Override 25 25 public String getColumnName(int columnIndex) { 26 26 // TODO Auto-generated method stub 27 27 return null; 28 28 } 29 29 30 30 @Override 31 31 public Class<?> getColumnClass(int columnIndex) { 32 32 // TODO Auto-generated method stub 33 33 return null; 34 34 } 35 35 36 36 @Override 37 37 public boolean isCellEditable(int rowIndex, int columnIndex) { 38 38 // TODO Auto-generated method stub 39 39 return false; 40 40 } 41 41 42 42 @Override 43 43 public Object getValueAt(int rowIndex, int columnIndex) { 44 44 // TODO Auto-generated method stub 45 45 return null; 46 46 } 47 47 48 48 @Override 49 49 public void setValueAt(Object aValue, int rowIndex, int columnIndex) { 50 50 // TODO Auto-generated method stub 51 51 52 52 } 53 53 54 54 @Override 55 55 public void addTableModelListener(TableModelListener l) { 56 56 // TODO Auto-generated method stub 57 57 58 58 } 59 59 60 60 @Override 61 61 public void removeTableModelListener(TableModelListener l) { 62 62 // TODO Auto-generated method stub 63 63 64 64 }}); 65 65 } 66 66 }
解释一下这些代码:首先是JTable table = new JTable(new TableModel(){});可以看出来,大括号中间的部分是一些需要重写的方法。new ……()是构造方法,调用来构造一个匿名对象,其后的{}不是Java的特殊语法,但是Java中可以将方法定义在里面(这里的方法生命周期与匿名对象相 同),当然,此处是用于实现接口的方法。TableModel我们可以在其前面补充一个不存在的类类名,比如MyTableModel。new MyTableModel:TableModel(){}也就是说大家可以想象成(new TableModel(){})是在声明一个匿名对象,它属于一个不具名的类(如MyTableModel),该类实现了TableModel接口。而由 于语法限制,不能全部写出来所以省略了[MyTableModel:]。
③设置表格渲染。在详细说明之前先解释一下JTable的显示原理:
首先是数据来源,您使用JTable的构造方法,大部分重载中参数即包含了数据,比如JTable(VectorrowData, Vector columnNames)
中Vector保存的数据(Vector相当于数组)。
其次是表格样式,表格将数据和如何显示数据(比如列数量、列名称、是否可编辑)保存在其数据模版中,该模版实现自接口TableModel。
最后,表格(每一个单元格)可以设置渲染效果。
完整的代码如下:
1 import java.awt.Component; 2 2 import java.awt.event.ActionEvent; 3 3 import java.awt.event.ActionListener; 4 4 5 5 import javax.swing.*; 6 6 import javax.swing.table.*; 7 7 8 8 9 9 public class MyFirstJFrame extends JFrame { 10 10 11 11 // 作为测试的main方法 12 12 public static void main(String[] args) { 13 13 new MyFirstJFrame().setVisible(true); 14 14 } 15 15 16 16 /** 17 17 * 构造方法 18 18 */ 19 19 public MyFirstJFrame() { 20 20 InitialComponent(); 21 21 } 22 22 23 23 /** 24 24 * 初始化组件的方法 25 25 */ 26 26 private void InitialComponent(){ 27 27 // 设置窗体参数 28 28 29 29 // 设置布局模式 30 30 setLayout(null); 31 31 // 设置窗体大小 32 32 setSize(480, 360); 33 33 // 设置窗体居中(非常规方法) 34 34 setLocationRelativeTo(null); 35 35 // 关闭窗体退出程序 36 36 setDefaultCloseOperation(DISPOSE_ON_CLOSE); 37 37 38 38 // 初始化面板 39 39 panel = new JPanel(); 40 40 panel.setSize(this.getWidth(), this.getHeight()); 41 41 panel.setLocation(0,0); 42 42 panel.setLayout(null); 43 43 44 44 // 初始化表格 45 45 table = new JTable(new DefaultTableModel(new Object[][]{{"第一行"},{"第二行"},{"第三行"},{"第四行"}}, new String[]{"测试行1","测试行2"}){ 46 46 /* (non-Javadoc) 47 47 * 重写方法,判断表单元格是否可编辑 48 48 * 可以通过row和column索引判断某一个单元格是否可编辑 49 49 * 此处设为都不可编辑 50 50 * @see javax.swing.table.DefaultTableModel#isCellEditable(int, int) 51 51 */ 52 52 @Override 53 53 public boolean isCellEditable(int row, int column) { 54 54 return false; 55 55 } 56 56 }); 57 57 58 58 // 开始向表格中添加复选框(注意:此示例较为简单,缺省很多判断,也没有动态代码支持) 59 59 // 通过设置列渲染 60 60 61 61 // 方法一:直接方式 使用TableColumn的setCellRenderer方法(推荐) 62 62 // 此方法可以设置某一列的渲染(即使用某一个组件--即控件来显示单元格数据) 63 63 table.getColumnModel().getColumn(1).setCellRenderer(new TableCellRenderer(){ 64 64 65 65 /*(non-Javadoc) 66 66 * 此方法用于向方法调用者返回某一单元格的渲染器(即显示数据的组建--或控件) 67 67 * 可以为JCheckBox JComboBox JTextArea 等 68 68 * @see javax.swing.table.TableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int) 69 69 */ 70 70 @Override 71 71 public Component getTableCellRendererComponent(JTable table, 72 72 Object value, boolean isSelected, boolean hasFocus, 73 73 int row, int column) { 74 74 // 创建用于返回的渲染组件 75 75 JCheckBox ck = new JCheckBox(); 76 76 // 使具有焦点的行对应的复选框选中 77 77 ck.setSelected(isSelected); 78 //设置背景颜色 这里是设置jcheckbox的背景颜色 直接设置为透明,我这里是用了一种明暗交替的颜色转换,所以背景颜色设置了一下 79 ck.setOpaque(false); 80 78 // 设置单选box.setSelected(hasFocus); 81 79 // 使复选框在单元格内居中显示 82 80 ck.setHorizontalAlignment((int) 0.5f); 83 81 return ck; 84 82 }}); 85 83 86 84 // 方法二:先设置列编辑器,然后设置单元格渲染 87 85 // 设置列编辑器 88 86 // 在以复选框为对象设置列编辑器时,必须保证该列能够被编辑,否则无法更改状态 89 87 // (此步骤可以省略,省略时不要忘记将列设为不可编辑) 90 88 // table.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(new JCheckBox())); 91 89 92 90 // 设置单元格渲染(这里是设置表格级别的渲染) 93 91 /*table.setDefaultRenderer(Object.class, new TableCellRenderer(){ 94 92 95 93 @Override 96 94 public Component getTableCellRendererComponent(JTable table, 97 95 Object value, boolean isSelected, boolean hasFocus, 98 96 int row, int column) { 99 97 // 判断是否为需要渲染的列 100 98 if(column == 1){ 101 99 // 和方法一基本一致 102 100 JCheckBox box = new JCheckBox(); 103 101 box.setSelected(isSelected); 104 102 // 设置单选box.setSelected(hasFocus); 105 103 box.setHorizontalAlignment((int) CENTER_ALIGNMENT); // 0.5f 106 104 return box; 107 105 } 108 106 // 如果不是需要渲染的列,封装文本域显示数据 109 107 return new JTextArea(value.toString()); 110 108 }});*/ 111 109 112 110 // 在多选是需要按住Ctrl键或者鼠标按住拖过连续的需要选中的行,应该给用户说明 113 111 // 第一种方法是被推荐的,因为它具有选中的高亮显示,界面能更加友好 114 112 table.setSize(panel.getWidth(),panel.getHeight() - 90); 115 113 table.setLocation(0, 0); 116 114 117 115 118 116 btn = new JButton("Test"); 119 117 btn.setSize(80,40); 120 118 btn.setLocation((panel.getWidth()) / 2 - 40, panel.getHeight() - 80); 121 119 122 120 // 按钮点击时显示当前选中项 123 121 btn.addActionListener(new ActionListener(){ 124 122 125 123 @Override 126 124 public void actionPerformed(ActionEvent e) { 127 125 for(int rowindex : table.getSelectedRows()){ 128 126 JOptionPane.showMessageDialog(null, rowindex + " " + table.getValueAt(rowindex, 0)); 129 127 } 130 128 }}); 131 129 132 130 panel.add(table); 133 131 panel.add(btn); 134 132 this.add(panel); 135 133 136 134 } 137 135 138 136 // 定义一些必要的组件 139 137 private JPanel panel; 140 138 private JTable table; 141 139 private JButton btn; 142 140 }