3

我想设计这个 JTable。

在此处输入图像描述

目标是用户能够通过双击单元格来编辑它们。任何更改都应该能够在以后保存并存储在数据库中。

我的代码如下:

public class BirthGUI extends JFrame implements TableModelListener {

//..//

//-------------------- BIRTH TABLE --------------------

                table = new JTable();
                table.setModel(myModel);
                myModel.reloadBirthJTable();

                table.getColumnModel().getColumn(0).setPreferredWidth(100);
                table.getColumnModel().getColumn(1).setPreferredWidth(80);
                table.getColumnModel().getColumn(2).setPreferredWidth(115);
                table.setRowHeight(20);

                JScrollPane scroller = new JScrollPane(table );
                table.setBounds(49, 85, 295, 374);

                            table.getModel().addTableModelListener(this);


                panel.add(scroller,BorderLayout.CENTER); 

        @Override
        public void tableChanged(TableModelEvent e) {
            System.out.println("TableModelEvent triggered!");
            int row = e.getFirstRow();
            int column = e.getColumn();
            Object test = myModel.getValueAt(row, column);      
            System.out.println("row: " + row + " column: " + column);   
            System.out.println(test.toString());
        }

和我的表模型:

public class BirthTableModel extends DefaultTableModel {

        private String[] columnNames = {"Date", "Children", "Complications/Comments"};      //column header labels
        private Object[][] data = new Object[20][3];
        private  List<Birth>  list;

        public void reloadBirthJTable() {
            System.out.println("loading birth table..");
            for(int i=0; i<20; i++){
                data[i][0] = "";
                data[i][1] = "";
                data[i][2] = "";
                this.addRow(data);
            }
        }

        public void clearJTable() {
            this.setRowCount(0);
        }

        @Override
        public void addRow(Object[] arg0) {
            // TODO Auto-generated method stub
            super.addRow(arg0);
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            return data[row][col];
        }


        public Class getColumnClass(int c) {
            for(int rowIndex = 0; rowIndex < getRowCount(); rowIndex++) { 
                Object[] row = data[rowIndex];
                if (row[c] != null) {
                    return getValueAt(rowIndex, c).getClass();
                }
            }
            return String.class;
        } 

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        @Override
        public boolean isCellEditable(int row, int col) {
            return true;

        }
    }

问题是,虽然单元格在我双击它们并触发 tableChanged() 后是可编辑的,但一旦单元格失去焦点,我对它们所做的任何更改都会被删除......

我在修改单元格时的输出是这样的:

loading birth table..
TableModelEvent triggered!
row: 1 column: 0

TableModelEvent triggered!
row: 0 column: 0

所以test好像是空的。。

4

1 回答 1

5

建议:

  • 由于您希望您的模型包含 Birth 对象的列表或数组,因此我会让 BirthTableModel 扩展 AbstractTableModel,而不是 DefaultTableModel。
  • 这将要求您覆盖类的抽象方法。
  • 并且fire***(...)每当您更改模型保存的数据时,您都会调用通知方法。
  • 并根据 Robin 的评论,实现 setValueAt 方法。
  • 我也会实现一个addRow(...)方法。
  • 避免尝试设置任何组件的边界。这会使一个类很难更新、修改或改进。让布局管理器为您完成这项繁重的工作。

我所说的 AbstractTableModel 的一个例子:

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.*;

public class TestTableModel {
   public static void main(String[] args) {
      BirthTableModel2 dm2 = new BirthTableModel2();
      JTable table = new JTable(dm2);
      JOptionPane.showMessageDialog(null, new JScrollPane(table));

      dm2.reloadBirthJTable();
      JOptionPane.showMessageDialog(null, new JScrollPane(table));
   }

}


// I had to guess at this class
class Birth {
   private Date date;
   private String children;
   private String comments;

   public Birth(Date date, String children, String comments) {
      this.date = date;
      this.children = children;
      this.comments = comments;
   }

   public Date getDate() {
      return date;
   }

   public String getChildren() {
      return children;
   }

   public String getComments() {
      return comments;
   }

   public void setDate(Date date) {
      this.date = date;
   }

   public void setChildren(String children) {
      this.children = children;
   }

   public void setComments(String comments) {
      this.comments = comments;
   }

}

@SuppressWarnings("serial")
class BirthTableModel2 extends AbstractTableModel {
   public final static String[] COLUMN_NAMES = { "Date", "Children",
   "Complications/Comments" }; // column header labels
   private List<Birth> birthList = new ArrayList<>();

   @Override
   public Class<?> getColumnClass(int columnIndex) {
      if (columnIndex == 0) {
         return Date.class;
      }
      return super.getColumnClass(columnIndex);
   }

   @Override
   public int getColumnCount() {
      return COLUMN_NAMES.length;
   }

   @Override
   public String getColumnName(int column) {
      return COLUMN_NAMES[column];
   }

   @Override
   public int getRowCount() {
      return birthList.size();
   }

   public void reloadBirthJTable() {
      System.out.println("loading birth table..");
      clearModel();
      for (int i = 0; i < 20; i++) {
         addRow();
      }
   }

   public void clearModel() {
      birthList.clear();
      fireTableDataChanged();
   }

   public void addRow() {
      birthList.add(new Birth(null, "", ""));
      fireTableRowsInserted(getRowCount() - 1, getRowCount() - 1);
   }

   @Override
   public boolean isCellEditable(int rowIndex, int columnIndex) {
      return true;
   }

   @Override
   public Object getValueAt(int rowIndex, int colIndex) {
      if (rowIndex < 0 || rowIndex >= getRowCount()) {
         // throw exception
      }
      if (colIndex < 0 || colIndex >= getColumnCount()) {
         // throw exception
      }
      Birth birth = birthList.get(rowIndex);
      switch (colIndex) {
      case 0:
         return birth.getDate();

      case 1:
         return birth.getChildren();

      case 2:
         return birth.getComments();
      }
      return null;
   }

   @Override
   public void setValueAt(Object aValue, int rowIndex, int colIndex) {
      if (rowIndex < 0 || rowIndex >= getRowCount()) {
         // throw exception
      }
      if (colIndex < 0 || colIndex >= getColumnCount()) {
         // throw exception
      }

      Birth birth = birthList.get(rowIndex);
      switch (colIndex) {
      case 0:
         birth.setDate((Date)aValue);
         break;
      case 1:
         birth.setChildren(aValue.toString());
         break;
      case 2:
         birth.setComments(aValue.toString());
      }
      fireTableRowsUpdated(rowIndex, rowIndex);

   }
}
于 2013-06-09T18:18:16.920 回答