【问题标题】:change Jtable Cell Value更改 Jtable 单元格值
【发布时间】:2013-02-14 03:18:12
【问题描述】:

我有一个 jtable 保存书籍文件记录并显示它们。

我创建了一个“借用”按钮,当单击未借用的行时,该行的“借用状态”应更改为“是”。

我使用这个代码,但没有改变!

public class user_AllBooks extends AbstractTableModel{
BookInformation book_info=new BookInformation();
String[] columns=new String[]{"Book Name","Book Date", "Book ID","Borrow Status"};
ArrayList<BookInformation> bData=new ArrayList<BookInformation>();

public user_AllBooks(){
    try{
        BufferedReader br=new BufferedReader(new FileReader("AllBookRecords.txt"));
        String line;
        while((line = br.readLine()) != null){
            bData.add(initializeBookData(line));
        }
        br.close();
    }
    catch(IOException ioe){

    }
}

public BookInformation initializeBookData(String myline){
    BookInformation book_infos=new BookInformation();
    String[] celledLine=myline.split("     ");
    book_infos.setBookName(celledLine[0]);
    book_infos.setBookDate(celledLine[1]);
    book_infos.setBookID(celledLine[2]);
    book_infos.setBorrowStatus(celledLine[3]);
    return book_infos;
}

@Override
public String getColumnName(int col){
    return columns[col];
}

@Override
public int getRowCount() {
    if(bData != null){
        return bData.size();
    }
    else{
        return 0;
    }
}

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

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
    BookInformation bookInf=bData.get(rowIndex);
    Object value;

    switch(columnIndex){     
        case 0:
            value=bookInf.getBookName();
            break;
        case 1:
            value=bookInf.getBookDate();
            break;
        case 2:
            value=bookInf.getBookID();
            break;
        case 3:
            value=bookInf.getBorrowStatus();
            break;
        default :
            value="...";
    }
    return value;    
}
}

二等:

public class user_AllBooksM extends JFrame implements ActionListener{
user_AllBooks uAllBooks=new user_AllBooks();
final JTable bTable=new JTable(uAllBooks);
JButton borrowButton;
public user_AllBooksM(){
    setTitle("All Books");
    exitButton=new JButton("Exit");
    borrowButton=new JButton("Borrow");
    borrowButton.addActionListener(this);
    JPanel Bpanel=new JPanel();
    Bpanel.setLayout(new FlowLayout());
    JScrollPane sp=new JScrollPane(bTable);
    Bpanel.add(sp);
    Bpanel.add(borrowButton);
    this.add(Bpanel);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setBounds(300, 60, 550, 550);
    this.setResizable(false);
    this.setVisible(true);
}

@Override
public void actionPerformed(ActionEvent event) {
        borrowInitialize(bTable.getSelectedRow());  
}

public void  borrowInitialize(int row){
    if(uAllBooks.getValueAt(row, 3).equals("yes")) {
        JOptionPane.showMessageDialog(null, "This Book Was Borrowed");
    }
    else{
        uAllBooks.setValueAt("Yes", row, 3);
        uAllBooks.fireTableRowsUpdated(row, row);
    }
}

public static void main(String[] args){
    new user_AllBooksM();
}

}

谢谢。

【问题讨论】:

  • 您尚未在 user_AllBooks 中覆盖 setValueAt 。你应该

标签: java swing jtable


【解决方案1】:

要覆盖setValueAt,您应该使用:

@Override
public void setValueAt(Object value, int row, int col)
{
    BookInformation book_infos = bData.get(row);
    if (col==0)
    book_infos.setBookName((String)value);
    else if (col==1)
    book_infos.setBookDate((String)value);
    else if (col==2)
    book_infos.setBookID((String)value);
    else if (col==3)
    book_infos.setBorrowStatus((String)value);
    fireTableCellUpdated(row,col);
}

在类user_AllBooks中定义这个方法

【讨论】:

  • 应该没有必要在 setValueAt 中调用 fireTableDataChanged,因为一个普通的可编辑表会为你做这件事。使用 setBorrowed 方法可能会更好
  • @MadProgrammer :我添加此方法是为了确保更改后的值肯定会反映在表中。是不必要的电话吗?
  • 此方法是否专门用于 setBorrow?
  • 此方法是否专门用于 setBorrow?
  • @Sajjad-HiFriend:这个方法是通用的,可以用来改变JTable任意单元格的值。
【解决方案2】:

您已经覆盖了 getValueAt 方法。所以它总是从你的bData arraylist 返回值。

public Object getValueAt(int rowIndex, int columnIndex) {
    BookInformation bookInf=bData.get(rowIndex);

因此,您还需要在表模型中实现 setValueAt 方法,以便更改 bData 数组列表中的实际数据。

另请注意,bTable.getSelectedRow() 将根据视图为您提供选定的行。在模型中,如果表已排序,索引可能会有所不同。

【讨论】:

    【解决方案3】:

    您可以使用TableModel#setValueAt,但您还要负责更新表格,这会破坏 MCV 模型。

    相反,您可以将setBorrowed 方法添加到您的user_AllBooks 类中。

    public void setBorrowed(int row, boolean borrowed) {
        BookInformation book = bData.get(row);
        book.setBorrowedState(borrowed);
        fireTableCellUpdated(row, 3);
    }
    

    【讨论】:

    • -1,这是 setValueAt() 方法的工作。首先它更新包含模型数据的数据结构。然后 TableModel 负责在单元格内容发生变化时通知表格。 TableModel 通过调用 fireTableCellUpdated(...) 方法来执行此操作,与您在此处所做的相同。这可以被认为是调用 setValueAt(borrowed, row, 3) 的便捷方法。
    • @camickr 谢谢你至少告诉我为什么我是个混蛋;) - 不胜感激。我查看了DefaultTableModel,它确实使用了fireTableCellUpdated。我担心的是(我希望你能在这里帮助我),在使用 AbstractTableModel 时我从来不需要调用它,因为表似乎会自动更新。触发另一个事件是否过大,可能导致双重重绘? (当然在大多数情况下它是一个单元格,只是对另一个观点感到好奇)
    • 编辑器中的数据使用 setValueAt(...) 方法保存到模型中。然后从表格中删除编辑器,从而重新绘制单元格。因此,即使 setValueAt(...) 方法没有触发更新事件,您也正确地认为表格将用新值重新绘制。但是,当数据发生变化时,通知 View 肯定是 Model 的职责。双重重绘是由JTable实现编辑代码的方式引起的。
    • @camickr 我同意触发事件是模型的责任(抽象实现使用protected 方法的事实是一个很好的建议)。好或坏,这就是答案所说的,我所做的(好或坏)假设是setValue 不会触发事件,在这种情况下,我们需要模型中的方法可以。这里的坏处是需要强制转换模型,这是一个有效的问题,好处是知道模型正在向客户端提供通知(通过fireTabelCellUpdated)。如果这是有道理的:P(我不认为你错了 - 只是寻求澄清)
    • setValueAt(...) 应该触发该事件,因为表中的任何列都可能被更新。对模型的所有更新都应通过此方法完成,因此它应该触发事件。您不需要为每一列创建一个特殊的方法。也可以直接更改 TableModel,而无需使用表格编辑器。所以 setValueAt(...) 方法不能假定它是从表编辑器调用的。我不确定您所说的“铸造模型”是什么意思?
    猜你喜欢
    • 2018-08-20
    • 1970-01-01
    • 2012-09-24
    • 2011-08-06
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 2012-09-06
    相关资源
    最近更新 更多