使用多个自定义表模型,避免重复代码

使用多个自定义表模型,避免重复代码,第1张

使用多个自定义表模型,避免重复代码

像其他Swing模型(即DefaultComboBoxModel,DefaultListModel)一样,我们可以使用泛型来创建灵活且可重用的表模型,还提供与用户定义的POJO一起使用的API。

该表模型将具有以下特殊功能:

  • 它从
    AbstractTableModel
    利用表模型事件处理的优势扩展而来。
  • CustomerTableModel
    上面显示的不同,此表模型必须是抽象的,因为它不能重写
    getValueAt()
    方法:仅仅因为我们不知道该表模型将处理的类或数据类型,重写上述方法的任务留给了子类。
  • 它继承了的空
    setValueAt()
    实现
    AbstractTableModel
    。这是有道理的,因为
    isCellEditable()
    它也从该类继承并始终返回
    false
  • 的默认实现
    getColumnClass()
    也被继承,并且始终返回
    Object.class

这些功能使此表模型真正易于实现,具体取决于我们的要求:

  • 如果我们需要显示一个只读表,那么我们必须重写2种方法top:
    getValueAt()
    getColumnClass()
    (这是推荐的,但不是强制性的)。
  • 如果我们的表需要可编辑,那么我们必须重写top的4种方法:上面提到的两个加号
    isCellEditable()
    setValueAt()

让我们看一下表模型的代码:

import java.util.ArrayList;import java.util.Collections;import java.util.List;import javax.swing.table.AbstractTableModel;public abstract class DataObjectTableModel<T> extends AbstractTableModel {    private final List<String> columnNames;    private final List<T> data;    public DataObjectTableModel() {        this.data = new ArrayList<>();        this.columnNames = new ArrayList<>();    }    public DataObjectTableModel(List<String> columnIdentifiers) {        this();        if (columnIdentifiers != null) { this.columnNames.addAll(columnIdentifiers);        }    }    @Override    public int getRowCount() {        return this.data.size();    }    @Override    public int getColumnCount() {        return this.columnNames.size();    }    @Override    public String getColumnName(int columnIndex) {        return this.columnNames.get(columnIndex);    }    public void setColumnNames(List<String> columnNames) {        if (columnNames != null) { this.columnNames.clear(); this.columnNames.addAll(columnNames); fireTableStructureChanged();        }    }    public List<String> getColumnNames() {        return Collections.unmodifiableList(this.columnNames);    }    public void addDataObject(T dataObject) {        int rowIndex = this.data.size();        this.data.add(dataObject);        fireTableRowsInserted(rowIndex, rowIndex);    }    public void addDataObjects(List<T> dataObjects) {        if (!dataObjects.isEmpty()) { int firstRow = data.size(); this.data.addAll(dataObjects); int lastRow = data.size() - 1; fireTableRowsInserted(firstRow, lastRow);        }    }    public void insertDataObject(T dataObject, int rowIndex) {        this.data.add(rowIndex, dataObject);        fireTableRowsInserted(rowIndex, rowIndex);    }    public void deleteDataObject(int rowIndex) {        if (this.data.remove(this.data.get(rowIndex))) { fireTableRowsDeleted(rowIndex, rowIndex);        }    }    public void notifyDataObjectUpdated(T domainObject) {        T[] elements = (T[])data.toArray();        for (int i = 0; i < elements.length; i++) { if(elements[i] == domainObject) {     fireTableRowsUpdated(i, i); }        }    }    public T getDataObject(int rowIndex) {        return this.data.get(rowIndex);    }    public List<T> getDataObjects(int firstRow, int lastRow) {        List<T> subList = this.data.subList(firstRow, lastRow);        return Collections.unmodifiableList(subList);    }    public List<T> getDataObjects() {        return Collections.unmodifiableList(this.data);    }    public void clearTableModelData() {        if (!this.data.isEmpty()) { int lastRow = data.size() - 1; this.data.clear(); fireTableRowsDeleted(0, lastRow);        }    }}

因此,采用此表模型和

Customer
类,一个完整的实现将如下所示:

String[] header = new String[] {"Entry date", "Name", "Address", "Phone number"};DataObjectTableModel<Customer> model = new DataObjectTableModel<>(Arrays.asList(header)) {    @Override    public Class<?> getColumnClass(int columnIndex) {        switch (columnIndex) { case 0: return Date.class; case 1: return String.class; case 2: return String.class; case 3: return String.class;     default: throw new ArrayIndexOutOfBoundsException(columnIndex);        }    }    @Override    public Object getValueAt(int rowIndex, int columnIndex) {        Customer customer = getDataObject(rowIndex);        switch (columnIndex) { case 0: return customer.getEntryDate(); case 1: return customer.getName(); case 2: return customer.getAddress(); case 3: return customer.getPhoneNumber();     default: throw new ArrayIndexOutOfBoundsException(columnIndex);        }    }    @Override    public boolean isCellEditable(int rowIndex, int columnIndex) {        return true;    }    @Override    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {        if (columnIndex < 0 || columnIndex >= getColumnCount()) { throw new ArrayIndexOutOfBoundsException(columnIndex);        } else { Customer customer = getDataObject(rowIndex); switch (columnIndex) {     case 0: customer.setEntryDate((Date)aValue); break;     case 1: customer.setName((String)aValue); break;     case 2: customer.setAddress((String)aValue); break;     case 3: customer.setPhoneNumber((String)aValue); break; } fireTableCellUpdated(rowIndex, columnIndex);        }    }};

如我们所见,在几行代码(LOC <50)中,我们有一个完整的实现。


它适用于JPA实体吗?

只要实体具有公共获取者和设置者,它就起作用。与JPA实现不同,此表模型不适用于反射,因此我们必须使用类的公共接口来实现

getValueAt()
setValueAt()
方法来访问对象属性。

它可以与JDBC一起使用吗?

不,不是。我们将不得不将结果集包装到域类中,并使用如上所述的类提供的接口。

它适用于Java默认类吗?

是的,它确实。再次使用class提供的界面。例如,让

java.io.File
我们上课,我们可以实现以下表模型实现:

String[] header = new String[] {    "Name",    "Full path",    "Last modified",    "Read",    "Write",    "Execute",    "Hidden",    "Directory"};DataObjectTableModel<File> model = new DataObjectTableModel<File>(Arrays.asList(header)) {    @Override    public Class<?> getColumnClass(int columnIndex) {        switch (columnIndex) { case 0: return String.class; case 1: return String.class; case 2: return Date.class; case 3: return Boolean.class; case 4: return Boolean.class; case 5: return Boolean.class; case 6: return Boolean.class; case 7: return Boolean.class;     default: throw new ArrayIndexOutOfBoundsException(columnIndex);        }    }    @Override    public Object getValueAt(int rowIndex, int columnIndex) {        File file = getDataObject(rowIndex);        switch (columnIndex) { case 0: return file.getName(); case 1: return file.getAbsolutePath(); case 2: return new Date(file.lastModified()); case 3: return file.canRead(); case 4: return file.canWrite(); case 5: return file.canExecute(); case 6: return file.isHidden(); case 7: return file.isDirectory();     default: throw new ArrayIndexOutOfBoundsException(columnIndex);        }    }};


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5083141.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-16
下一篇 2022-11-16

发表评论

登录后才能评论

评论列表(0条)

保存