Java Swing实现JTable检测单元格数据变更事件的方法示例

2025-05-29 0 13

本文实例讲述了java swing实现jtable检测单元格数据变更事件的方法。分享给大家供大家参考,具体如下:

在jtable的初级教程中往往会提到,使用tablemodel的 addtablemodellistener方法可以监听单元格数据的变更,在其事件处理函,数tablechanged中,可以通过e.getcolumn()e.getfirstrow()e.getlastrow()e.gettype()来获取变更发生的位置和变更的类型(插入、更新或删除)。然而该方法存在2个致命的问题:

1.双击单元格使其处于可编辑状态后,即使没有做出任何修改,当单元格失去焦点时,该事件将被激活。

2.通过该事件你可以获取单元格最新的数据,却无法获取原有数据。

经过一番搜索发现该文章已经解决了这个问题table cell listener,作者自己实现了一个单元格监听器tablecelllistener,它订阅了指定table的addpropertychangelistener,根据e.getpropertyname()来识别单元格编辑事件,根据table.isediting()方法来判断单元格正在编辑还是编辑完毕。如果是正在编辑,则记录单元格位置和原因数据;如果已经编辑完毕,则记录新数据并与原有数据进行比对,如果不一致则说明单元格数据发生了变更,则激活指定响应函数。

测试用例如下:

tabledemo.java

?

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
/*

* copyright (c) 1995, 2008, oracle and/or its affiliates. all rights reserved.

*

* redistribution and use in source and binary forms, with or without

* modification, are permitted provided that the following conditions

* are met:

*

* - redistributions of source code must retain the above copyright

* notice, this list of conditions and the following disclaimer.

*

* - redistributions in binary form must reproduce the above copyright

* notice, this list of conditions and the following disclaimer in the

* documentation and/or other materials provided with the distribution.

*

* - neither the name of oracle or the names of its

* contributors may be used to endorse or promote products derived

* from this software without specific prior written permission.

*

* this software is provided by the copyright holders and contributors "as

* is" and any express or implied warranties, including, but not limited to,

* the implied warranties of merchantability and fitness for a particular

* purpose are disclaimed. in no event shall the copyright owner or

* contributors be liable for any direct, indirect, incidental, special,

* exemplary, or consequential damages (including, but not limited to,

* procurement of substitute goods or services; loss of use, data, or

* profits; or business interruption) however caused and on any theory of

* liability, whether in contract, strict liability, or tort (including

* negligence or otherwise) arising in any way out of the use of this

* software, even if advised of the possibility of such damage.

*/

package awtdemo;

/*

* tabledemo.java requires no other files.

*/

import javax.swing.abstractaction;

import javax.swing.action;

import javax.swing.jframe;

import javax.swing.jpanel;

import javax.swing.jscrollpane;

import javax.swing.jtable;

import javax.swing.table.abstracttablemodel;

import java.awt.dimension;

import java.awt.gridlayout;

import java.awt.event.actionevent;

/**

* tabledemo is just like simpletabledemo, except that it

* uses a custom tablemodel.

*/

@suppresswarnings("serial")

public class tabledemo extends jpanel {

private boolean debug = false;

@suppresswarnings("unused")

public tabledemo() {

super(new gridlayout(1,0));

jtable table = new jtable(new mytablemodel());

table.setpreferredscrollableviewportsize(new dimension(500, 70));

table.setfillsviewportheight(true);

//create the scroll pane and add the table to it.

jscrollpane scrollpane = new jscrollpane(table);

//add the scroll pane to this panel.

add(scrollpane);

action action = new abstractaction()

{

public void actionperformed(actionevent e)

{

tablecelllistener tcl = (tablecelllistener)e.getsource();

system.out.printf("cell changed%n");

system.out.println("row : " + tcl.getrow());

system.out.println("column: " + tcl.getcolumn());

system.out.println("old : " + tcl.getoldvalue());

system.out.println("new : " + tcl.getnewvalue());

}

};

tablecelllistener tcl = new tablecelllistener(table, action);

}

class mytablemodel extends abstracttablemodel {

private string[] columnnames = {"first name",

"last name",

"sport",

"# of years",

"vegetarian"};

private object[][] data = {

{"kathy", "smith",

"snowboarding", new integer(5), new boolean(false)},

{"john", "doe",

"rowing", new integer(3), new boolean(true)},

{"sue", "black",

"knitting", new integer(2), new boolean(false)},

{"jane", "white",

"speed reading", new integer(20), new boolean(true)},

{"joe", "brown",

"pool", new integer(10), new boolean(false)}

};

public int getcolumncount() {

return columnnames.length;

}

public int getrowcount() {

return data.length;

}

public string getcolumnname(int col) {

return columnnames[col];

}

public object getvalueat(int row, int col) {

return data[row][col];

}

/*

* jtable uses this method to determine the default renderer/

* editor for each cell. if we didn't implement this method,

* then the last column would contain text ("true"/"false"),

* rather than a check box.

*/

@suppresswarnings({ "unchecked", "rawtypes" })

public class getcolumnclass(int c) {

return getvalueat(0, c).getclass();

}

/*

* don't need to implement this method unless your table's

* editable.

*/

public boolean iscelleditable(int row, int col) {

//note that the data/cell address is constant,

//no matter where the cell appears onscreen.

if (col < 2) {

return false;

} else {

return true;

}

}

/*

* don't need to implement this method unless your table's

* data can change.

*/

public void setvalueat(object value, int row, int col) {

if (debug) {

system.out.println("setting value at " + row + "," + col

+ " to " + value

+ " (an instance of "

+ value.getclass() + ")");

}

data[row][col] = value;

firetablecellupdated(row, col);

if (debug) {

system.out.println("new value of data:");

printdebugdata();

}

}

private void printdebugdata() {

int numrows = getrowcount();

int numcols = getcolumncount();

for (int i=0; i < numrows; i++) {

system.out.print(" row " + i + ":");

for (int j=0; j < numcols; j++) {

system.out.print(" " + data[i][j]);

}

system.out.println();

}

system.out.println("--------------------------");

}

}

/**

* create the gui and show it. for thread safety,

* this method should be invoked from the

* event-dispatching thread.

*/

private static void createandshowgui() {

//create and set up the window.

jframe frame = new jframe("tabledemo - www.zzvips.com");

frame.setdefaultcloseoperation(jframe.exit_on_close);

//create and set up the content pane.

tabledemo newcontentpane = new tabledemo();

newcontentpane.setopaque(true); //content panes must be opaque

frame.setcontentpane(newcontentpane);

//display the window.

frame.pack();

frame.setvisible(true);

}

public static void main(string[] args) {

//schedule a job for the event-dispatching thread:

//creating and showing this application's gui.

javax.swing.swingutilities.invokelater(new runnable() {

public void run() {

createandshowgui();

}

});

}

}

tablecelllistener.java

?

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
package awtdemo;

import java.awt.event.*;

import javax.swing.*;

import java.beans.*;

/*

* this class listens for changes made to the data in the table via the

* tablecelleditor. when editing is started, the value of the cell is saved

* when editing is stopped the new value is saved. when the oold and new

* values are different, then the provided action is invoked.

*

* the source of the action is a tablecelllistener instance.

*/

public class tablecelllistener implements propertychangelistener, runnable

{

private jtable table;

private action action;

private int row;

private int column;

private object oldvalue;

private object newvalue;

/**

* create a tablecelllistener.

*

* @param table the table to be monitored for data changes

* @param action the action to invoke when cell data is changed

*/

public tablecelllistener(jtable table, action action)

{

this.table = table;

this.action = action;

this.table.addpropertychangelistener( this );

}

/**

* create a tablecelllistener with a copy of all the data relevant to

* the change of data for a given cell.

*

* @param row the row of the changed cell

* @param column the column of the changed cell

* @param oldvalue the old data of the changed cell

* @param newvalue the new data of the changed cell

*/

private tablecelllistener(jtable table, int row, int column, object oldvalue, object newvalue)

{

this.table = table;

this.row = row;

this.column = column;

this.oldvalue = oldvalue;

this.newvalue = newvalue;

}

/**

* get the column that was last edited

*

* @return the column that was edited

*/

public int getcolumn()

{

return column;

}

/**

* get the new value in the cell

*

* @return the new value in the cell

*/

public object getnewvalue()

{

return newvalue;

}

/**

* get the old value of the cell

*

* @return the old value of the cell

*/

public object getoldvalue()

{

return oldvalue;

}

/**

* get the row that was last edited

*

* @return the row that was edited

*/

public int getrow()

{

return row;

}

/**

* get the table of the cell that was changed

*

* @return the table of the cell that was changed

*/

public jtable gettable()

{

return table;

}

//

// implement the propertychangelistener interface

//

@override

public void propertychange(propertychangeevent e)

{

// a cell has started/stopped editing

if ("tablecelleditor".equals(e.getpropertyname()))

{

if (table.isediting()){

//system.out.printf("tablecelleditor is editing..%n");

processeditingstarted();

}

else{

//system.out.printf("tablecelleditor editing stopped..%n");

processeditingstopped();

}

}

}

/*

* save information of the cell about to be edited

*/

private void processeditingstarted()

{

// the invokelater is necessary because the editing row and editing

// column of the table have not been set when the "tablecelleditor"

// propertychangeevent is fired.

// this results in the "run" method being invoked

swingutilities.invokelater( this );

}

/*

* see above.

*/

@override

public void run()

{

row = table.convertrowindextomodel( table.geteditingrow() );

column = table.convertcolumnindextomodel( table.geteditingcolumn() );

oldvalue = table.getmodel().getvalueat(row, column);

//这里应对oldvalue为null的情况做处理,否则将导致原值与新值均为空时仍被视为值改变

if(oldvalue == null)

oldvalue = "";

newvalue = null;

}

/*

* update the cell history when necessary

*/

private void processeditingstopped()

{

newvalue = table.getmodel().getvalueat(row, column);

//这里应对newvalue为null的情况做处理,否则后面会抛出异常

if(newvalue == null)

newvalue = "";

// the data has changed, invoke the supplied action

if (! newvalue.equals(oldvalue))

{

// make a copy of the data in case another cell starts editing

// while processing this change

tablecelllistener tcl = new tablecelllistener(

gettable(), getrow(), getcolumn(), getoldvalue(), getnewvalue());

actionevent event = new actionevent(

tcl,

actionevent.action_performed,

"");

action.actionperformed(event);

}

}

}

运行效果:

Java Swing实现JTable检测单元格数据变更事件的方法示例

由图可见,单元格数据修改后,控制台输出内容变更信息!

希望本文所述对大家java程序设计有所帮助。

原文链接:http://www.cnblogs.com/pzy4447/p/5164775.html

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 Java Swing实现JTable检测单元格数据变更事件的方法示例 https://www.kuaiidc.com/114067.html

相关文章

发表评论
暂无评论