【JAVA】JTable学习之使用AbstractTableModel (二) 完结

在上一篇的文章中 我们知道,JTable的表格和数据是分开的,每一个Jtable都会有自己的TableModel,在其内部都有一个二维 的Vector(假如是Vector TableData)用来存放二维的表格数据,每个表格都与这个二维的Vector形成映射关系,当表格Table显示的时候通过TableModel的接口 getRowcount(),getColumnCount(),获取表格的行数和列数生成一个能容纳TableData的数据表格,然后Table通过接口
getValueAt(int row,int col)获取到对应的表格位置的数据,这样表格就能对应显示出TableData中的所有数据了;

当我们修改表格的数据的时候,函数setValueAt(int row,int col)会被调用,我们只需要在这个函数中修改TableData中对应位置的数据,然后调用函数
 fireTableCellUpdated(int row,int col);更新一下表格对应位置的数据显示即可完成对表格的数据修改;


下面进入正题,设置Jtable的表格编辑器:
   我们知道如果在我们自己的TableModel中重载函数 boolean isCellEditable(int rowIndex, int columnIndex),并且设置其返回值为真的时候就可以使得对应的表格可编辑,也就是当我们双击表格的时候 可以进入一个编辑状态,如图:
                                                
仔细观察,这是一个 JTextFilied文本框,当我们按下Enter的时候即可完成编辑,表格又会变成正常的状态 

 

 看到这里我们对表格大致就已经有一个了解了, 简而言之就是:表格是表格,数据是数据,修改数据要通过一种【组件】来获取新的数据,例如我们要获得输入的文本,那么我们可以通过一个JTextFiled来获取文本的输入,输入完成后 将文本的内容递送到调用者即可完成数据的获取;


    显示数据靠的是表格,存储数据靠的是TableModel,修改数据靠的是对应的编辑器,所谓的编辑器这也就是这篇文章所要说的 CellEditor表格编辑器、、在表的维护中是以列作为一个组的,所以对于表的每一列的数据类型必须是相同的,在默认状态下 即是我们不指定表的每一列的显示的数据类型的时候,TableModel中的数据将会被默认为String类型在Table中进行维护。

    下面我们举个例子,在表格内显示图片,与下拉列表JComboBox:


使用 JTable的3要素: 表格JTableModel编辑器


    首先建立一个表格Model存放数据,为了简单起见,设置为 2x2的表格,第一列显示JComboBox、第二列显示图片

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

class MyTableModel extends AbstractTableModel

{        

  //表格的列标题   String head[]={"下拉列表","图片"};   //表格列属性,用于设置列的维护数据类型   Class[]TypeArr = {String.class,Icon.class};   //表格的数据   Object[][]data = {                                {"选项A",new ImageIcon("C://I//pic1.png")},                               {"选项B",new ImageIcon("C://I//pic2.png")}                            };

        //表格的行数  @Override

public int getRowCount()

{return 2;}

 //表格的列数

@Override

public int getColumnCount()

{return 2;}

//获取数据

@Override

public Object getValueAt(int rowIndex, int columnIndex)

{return data[rowIndex][columnIndex];}

  //获取表格每一列需要维护的数据类型

 @Override

public Class getColumnClass(int columnIndex)

  {return TypeArr[columnIndex]; }

//设置每个表格允许编辑

@Override

public boolean isCellEditable(int rowIndex, int columnIndex)

{return true;}

//表格的列标题

@Override

public String getColumnName(int column)

{return head[column];}

 //修改数据

@Override

public void setValueAt(Object aValue, int rowIndex, int columnIndex)

{

  //修改Vector的数据 

data[rowIndex][columnIndex] = aValue;

//只需要更新对应的位置就行

this.fireTableCellUpdated(rowIndex, columnIndex);

}

}  // //

//************************************************************************自定义的图片编辑器

//实现 TableCellEditor,ActionListener 接口

class MyPicEditor extends AbstractCellEditor implements TableCellEditor,ActionListener

{

/*

*ReadMe:当我们点击表格Cell的时候,表格检测点击的消息,检测Cell是否允许编辑,

*如果允许编辑 则去调用 表格编辑器 来获取图片,获取完后将图片 送达给 TableModel

*结束编辑器的编辑状态,表格刷新显示 对应的图片

*/

//用于获取图片的变量

private Icon m_IconPic;

//作为 编辑器 ,当我们点击的时候进行图片的选择

private JButton m_IconButton;

//点击按钮的时候 进行文件选择的 Filechooser

private JFileChooser m_PicFileChooser;

//设置当我们 点击2次的时候 编辑器 才起作用

private static final int clickCountToStart = 2;

//构造函数,初始化一些信息

public MyPicEditor()

{

  m_IconButton =new JButton();

  m_IconButton.addActionListener(this);

  m_PicFileChooser = new JFileChooser();

}

//检测鼠标的点击次数,判断编辑器是否起作用

public boolean isCellEditable(EventObject anEvent) 

{

      //如果事件 是 鼠标的事件,大于设定的次数就true,否则false

      if (anEvent instanceof MouseEvent) 

      {

          System.out.println("检测鼠标的点击次数,设置编辑器是否响应");

           return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;

       }

       return false; 

 }

  

@Override

public Component getTableCellEditorComponent(JTable table, Object value,

boolean isSelected, int row, int column)

{

  System.out.println("表格Cell获取将要显示的编辑器组件,返回值编辑器包含的控件");

  //先前的表格Cell的 数据 先保存下来,用于初始化编辑器包含的控件的数据

  m_IconPic = (Icon)value;

  //返回作为编辑器的组件,这里是一个按钮

  return m_IconButton;

}

//响应编辑器包含的组件的事件

@Override

public void actionPerformed(ActionEvent e)

{

    System.out.println("编辑器组件事件响应");

    if(e.getSource()==m_IconButton)

    {

      //初始化编辑器,显示原始的图片

      m_IconButton.setIcon(m_IconPic);

      //显示文件选择器,用于选择图片

      m_PicFileChooser.showOpenDialog(m_IconButton);

       if(m_PicFileChooser.getSelectedFile()!=null)

       {

         //如果选择了新的图片将按钮设置为新的图标

         m_IconPic= new ImageIcon(m_PicFileChooser.getSelectedFile().getAbsolutePath());

       }

      //数据获取完成,终止编辑器,将数据送达 调用者

      this.fireEditingStopped();

    }

}

//将数据送达调用者,关闭编辑器,表格正常显示

@Override

public Object getCellEditorValue()

{

  System.out.println("返回结果");

  return m_IconPic;

}

}

// //下拉列表的编辑器

//****************************************************************Commbox的编辑器

class ComBoxEditor extends AbstractCellEditor implements TableCellEditor

{

/*

*ReadMe: 这个 ComboBox下拉列表的编辑器 使用一个 JLable 和一个 JComboBox组合的

*将JComboBox放到JLable里,所以只需要将 JLable 作为编辑器组件返回就行了

*/

private JComboBox m_ComboBox;

//获取 下拉列表的 选择的值

private String m_SelStr;

private JLabel m_OutLable;

//这里我们设置 鼠标点击 1 次就响应编辑器

private static final int clickCountToStart = 1;

 //初始化编辑器包含的控件信息

     public ComBoxEditor()     {  

    m_ComboBox = new JComboBox();

    m_ComboBox.addItem("选项A");

    m_ComboBox.addItem("选项B");

    m_ComboBox.addItem("选项C");

    m_ComboBox.setSize(100,30);

    m_OutLable= new JLabel();

    m_OutLable.setLayout(null);

    m_OutLable.setBounds(0012040);

    m_OutLable.add(m_ComboBox);

    m_ComboBox.setLocation(5050);

//响应下拉列表的事件

m_ComboBox.addItemListener(new ItemListener()

{

@Override

public void itemStateChanged(ItemEvent e)

{

    System.out.println("下拉列表的选中事件");

    if(e.getStateChange() == e.SELECTED)

    {

    //获取选择的值

    m_SelStr = (String)m_ComboBox.getSelectedItem();

    //结束选择

    fireEditingStopped();

      }

           }

});

    }  

//检测鼠标的点击次数,判断编辑器是否起作用

   public boolean isCellEditable(EventObject anEvent)     {  

//如果事件 是 鼠标的事件,大于设定的次数就true,否则false

 if (anEvent instanceof MouseEvent) 

 {

    System.out.println("检测鼠标的点击次数,设置编辑器是否响应");

    return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;

 }

 return false;

   }  

  

//获取编辑器的组件

@Override

public Component getTableCellEditorComponent(JTable table, Object value,

boolean isSelected, int row, int column)

{

    System.out.println("获取编辑器的组件");

    //将下拉列表设置为之前的选项

    m_SelStr = (String)value;

    m_ComboBox.setSelectedItem(m_SelStr);

    //返回值为 null的时候 是空的编辑器,就是说 = =不允许 编辑的

    return m_OutLable;

}

//获取编辑器的 值

@Override

public Object getCellEditorValue()

{

     System.out.println("返回结果");

     return m_SelStr;

  }

// // // TabelMode、编辑器都有了,我们只需要 一个JTable 显示一下就Ok了  //****************************************************定义显示表格的Frame

public class CellEditorFrame 

{

    public static void main(String[]sre)

   {

      MyTableModel m_TableModel = new MyTableModel();

  

      JTable m_TableDemo = new JTable(m_TableModel);

      //定义两个编辑器

      ComBoxEditor m_ComboBoxEditor = new ComBoxEditor();

      MyPicEditor m_PicEditor =new MyPicEditor();

  

      JFrame m_MyFrame = new JFrame("我的CellEditor");

      //为每一列 设置编辑器

      m_TableDemo.getColumnModel().getColumn(0).setCellEditor(m_ComboBoxEditor);

      m_TableDemo.getColumnModel().getColumn(1).setCellEditor(m_PicEditor);

       //设置行高

      m_TableDemo.setRowHeight(200);

  

      JScrollPane m_JScroolPanel = new JScrollPane(m_TableDemo);

      m_JScroolPanel.setViewportView(m_TableDemo);

      m_JScroolPanel.setSize(480200);

  

      m_MyFrame.add(m_JScroolPanel);

      m_MyFrame.setBounds(200200500500);

      m_MyFrame.setDefaultCloseOperation(m_MyFrame.EXIT_ON_CLOSE);

      m_MyFrame.setVisible(true);

   }

  

}

 

OK AbstractTableModel教程到此结束,下面是效果图

 

 

 

附加上一个源代码文件:CellEditor.java

解压密码 yscode

百度网盘下载地址:http://pan.baidu.com/s/1c0xRzDe

使用 AbstractTableModel 构建Table 在表格中添加JButton按钮,之前在网上找了2天没有找到好用的程序,最终终于找到一个好用的例子。 不要使,我退你们分。。 sing the Swing JTable class can quickly become a sticky business when you want to customize it to your specific needs. First you must become familiar with how the JTable class is organized. Individual cells are rendered by TableCellRenderer implementations. The table contents are represented by an implementation of the TableModel interface. By default, JTable uses DefaultTableCellRenderer to draw its cells. DefaultTableCellRenderer recognizes a few primitive types, rendering them as strings, and can even display Boolean types as checkboxes. But it defaults to displaying the value returned by toString() for types it does not specifically handle. You have to provide your own TableCellRenderer implementation if you want to display buttons in a JTable. The TableCellRenderer interface contains only one method, getTableCellRendererComponent(...), which returns a java.awt.Component that knows how to draw the contents of a specific cell. Usually, getTableCellRendererComponent() will return the same component for every cell of a column, to avoid the unnecessary use of extra memory. But when the contents of a cell is itself a component, it is all right to return that component as the renderer. Therefore, the first step towards having JButtons display correctly in a JTable is to create a TableCellRenderer implementation that returns the JButton contained in the cell being rendered. In the accompanying code listing, JTableButtonRenderer demonstrates how to do this. Even after creating a custom TableCellRenderer, you're still not done. The TableModel associated with a given JTable does not only keep track of the contents of each cell, but it also keeps track of the class of data stored in each column. DefaultTableModel is designed to work with DefaultTableCellRenderer and will return java.lang.String.class for columns containing data types that it does not specifically handle. The exact method that does this is getColumnClass(int column). Your second step is to create a TableModel implementation that returns JButton.class for cells that contain JButtons. JTableButtonModel shows one way to do this. It just returns the result of getClass() for each piece of cell data. At this point, you're almost done, but not quite. What's the use of putting a JButton in a JTable if you can't press the darn thing? By default, JTable will not forward mouse events to components contained in its cells. If you want to be able to press the buttons you add to JTable, you have to create your own MouseListener that forwards events to the JButton cells. JTableButtonMouseListener demonstrates how you could do this.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值