一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java Swing實現(xiàn)JTable檢測單元格數(shù)據(jù)變更事件的方法示例

Java Swing實現(xiàn)JTable檢測單元格數(shù)據(jù)變更事件的方法示例

2021-02-04 11:50pzy4447 Java教程

這篇文章主要介紹了Java Swing實現(xiàn)JTable檢測單元格數(shù)據(jù)變更事件的方法,結合完整實例形式分析了Swing實現(xiàn)JTable檢測單元格數(shù)據(jù)變更事件過程中出現(xiàn)的問題與相關解決方法,需要的朋友可以參考下

本文實例講述了java swing實現(xiàn)jtable檢測單元格數(shù)據(jù)變更事件的方法。分享給大家供大家參考,具體如下:

在jtable的初級教程中往往會提到,使用tablemodel的 addtablemodellistener方法可以監(jiān)聽單元格數(shù)據(jù)的變更,在其事件處理函,數(shù)tablechanged中,可以通過e.getcolumn()e.getfirstrow()e.getlastrow()e.gettype()來獲取變更發(fā)生的位置和變更的類型(插入、更新或刪除)。然而該方法存在2個致命的問題:

1.雙擊單元格使其處于可編輯狀態(tài)后,即使沒有做出任何修改,當單元格失去焦點時,該事件將被激活。

2.通過該事件你可以獲取單元格最新的數(shù)據(jù),卻無法獲取原有數(shù)據(jù)。

經(jīng)過一番搜索發(fā)現(xiàn)該文章已經(jīng)解決了這個問題table cell listener,作者自己實現(xiàn)了一個單元格監(jiān)聽器tablecelllistener,它訂閱了指定table的addpropertychangelistener,根據(jù)e.getpropertyname()來識別單元格編輯事件,根據(jù)table.isediting()方法來判斷單元格正在編輯還是編輯完畢。如果是正在編輯,則記錄單元格位置和原因數(shù)據(jù);如果已經(jīng)編輯完畢,則記錄新數(shù)據(jù)并與原有數(shù)據(jù)進行比對,如果不一致則說明單元格數(shù)據(jù)發(fā)生了變更,則激活指定響應函數(shù)。

測試用例如下:

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.ythuaji.com.cn");
    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實現(xiàn)JTable檢測單元格數(shù)據(jù)變更事件的方法示例

由圖可見,單元格數(shù)據(jù)修改后,控制臺輸出內(nèi)容變更信息!

希望本文所述對大家java程序設計有所幫助。

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 嫩草影院久久99 | 黑人性xxx | 国产日韩欧美在线观看不卡 | 欧美多gayxxxx | 欧美日韩国产亚洲一区二区 | 含羞草传媒网站免费进入欢迎 | 国产亚洲玖玖玖在线观看 | 手机看片自拍自自拍日韩免费 | 奇米影视一区 | 欧美成a人片免费看久久 | 经典千人斩一区二区视频 | 欧美激烈精交gif动态图18p | 波多野结衣之双方调教在线观看 | 国产精品毛片无码 | 女八把屁股扒开让男生添 | 久久国产综合精品欧美 | 日韩高清在线观看 | 午夜爱 | 日产精品一二三四区国产 | 天天射夜夜爽 | 日韩二区三区 | 2019亚洲男人天堂 | 女同69式互添在线观看免费 | 欧美日韩三区 | 久久中文电影 | 免费观看日本视频 | 91精品国产免费久久国语蜜臀 | 精品午夜久久福利大片免费 | 色婷在线| 91在线精品老司机免费播放 | 国产成人+亚洲欧洲 | 免费一级特黄特色大片在线观看 | 精品在线网站 | 插鸡视频在线观看 | 亚洲国产成人在线 | 日韩亚洲国产激情在线观看 | 亚洲欧洲色图 | 极端 成熟 性别 视频 | 69欧美另类xxxxx高清 | 精品视频一区二区观看 | 免费在线观看成年人视频 |