Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 交互式JTable_Java_Swing_Jtable - Fatal编程技术网

Java 交互式JTable

Java 交互式JTable,java,swing,jtable,Java,Swing,Jtable,我正在开发一个使用JTable的简单Java应用程序。我正在努力实现我所看到的。给定链接上的表的行为与我在表中想要的行为完全相同。我所做的与参考链接上显示的完全一样但是,当我运行应用程序时,我无法编辑第三列也是最后一列。 我想要的行为是,当用户在填写表中最后一列时按Enter键时,应用程序应该添加一个空行。 这是我的第一个类,实体类: public class Product { String productDescription; String productCode; double prod

我正在开发一个使用JTable的简单Java应用程序。我正在努力实现我所看到的。给定链接上的表的行为与我在表中想要的行为完全相同。我所做的与参考链接上显示的完全一样但是,当我运行应用程序时,我无法编辑第三列也是最后一列。 我想要的行为是,当用户在填写表中最后一列时按Enter键时,应用程序应该添加一个空行。

这是我的第一个类,实体类:

public class Product {
String productDescription;
String productCode;
double productPrice;
//dummy properties
int productQuantity;
double productTotalAmount;

 public Product() {
    this.productDescription = "";
    this.productCode = "";
    this.productPrice = 0;
    this.productTotalAmount = 0;
    this.productQuantity = 0;
}

public int getProductQuantity() {
    return productQuantity;
}

public void setProductQuantity(int productQuantity) {
    this.productQuantity = productQuantity;
}

public double getProductTotalAmount() {
    return productTotalAmount;
}

public void setProductTotalAmount(double productTotalAmount) {
    this.productTotalAmount = productTotalAmount;
}

public String getProductDescription() {
    return productDescription;
}

public void setProductDescription(String productDescription) {
    this.productDescription = productDescription;
}

public String getProductCode() {
    return productCode;
}

public void setProductCode(String productCode) {
    this.productCode = productCode;
}

public double getProductPrice() {
    return productPrice;
}

public void setProductPrice(double productPrice) {
    this.productPrice = productPrice;
}}
这是我的第二节课,桌子模型:

public class InteractiveTableModel extends AbstractTableModel{

// indexes
 public static final int PRODUCT_DESCRIPTION_INDEX = 0;
 public static final int PRODUCT_CODE_INDEX = 1;
 public static final int PRODUCT_PRICE_INDEX = 2;
 public static final int PRODUCT_QUANTITY_INDEX=3;
 public static final int PRODUCT_TOTAL_AMOUNT_INDEX=4;
 public static final int HIDDEN_INDEX = 5;

 protected String [] columnNames;
 protected Vector dataVector;

  //this constructor is responsible for initializing the columnmanes and the data of the table.
 public InteractiveTableModel(String[] columnNames) {
     this.columnNames = columnNames;
     dataVector = new Vector();
 }


@Override
 //this method returns the name of the column corresponding to the passed integer.
 public String getColumnName(int column) {
     return columnNames[column];
 }

  //this method is used to determine whether a cell is editable
 //this is for manuvouring to the next editable cell
 @Override

 public boolean isCellEditable(int row, int column) {
     if (column == HIDDEN_INDEX) return false;
     else return true;
 }

 @Override
      public Class getColumnClass(int column) {// returns a class representing the datatype of the data stored in that column
     switch (column) {
         case PRODUCT_DESCRIPTION_INDEX:
         case PRODUCT_CODE_INDEX:
            return String.class;
         case PRODUCT_QUANTITY_INDEX:
             return Integer.class;
         case PRODUCT_PRICE_INDEX:
         case PRODUCT_TOTAL_AMOUNT_INDEX:
             return double.class;
         default:
            return Object.class;
     }
 }

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

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

 @Override
 public Object getValueAt(int row, int column) {
     Product record = (Product)dataVector.get(row);//this will return a row in a vector
     //this is cast to AudioRecord so that we can extract the data that we want correspoinding to column number
     switch (column) {
         case PRODUCT_DESCRIPTION_INDEX:
            return record.getProductDescription();
         case PRODUCT_CODE_INDEX:
            return record.getProductCode();
         case PRODUCT_PRICE_INDEX:
            return record.getProductPrice();
         case PRODUCT_TOTAL_AMOUNT_INDEX:
            return record.getProductTotalAmount();
        case PRODUCT_QUANTITY_INDEX:
            return record.getProductQuantity();
         default:
            return new Object();
     }
 }

      //setting data in a cell
 @Override
 public void setValueAt(Object value, int row, int column) {
     Product record = (Product)dataVector.get(row);
     switch (column) {
         case PRODUCT_DESCRIPTION_INDEX:
            record.setProductDescription((String)value);
            break;
         case PRODUCT_CODE_INDEX:
            record.setProductCode((String)value);
            break;
         case PRODUCT_PRICE_INDEX:
            record.setProductPrice((Double)value);
            break;
         case PRODUCT_QUANTITY_INDEX:
            record.setProductQuantity((Integer)value);
             break;
           case PRODUCT_TOTAL_AMOUNT_INDEX:
            record.setProductTotalAmount((Double)value);
               break;
         default:
            System.out.println("invalid index");
     }
     fireTableCellUpdated(row, column);//this is for updating the cell
 }


 public boolean hasEmptyRow() {
     if (dataVector.isEmpty()) return false;
     Product productRecord = (Product)dataVector.get(dataVector.size() - 1);
     if (productRecord.getProductDescription().trim().equals("") &&
        productRecord.getProductCode().trim().equals("") &&
        (productRecord.getProductPrice()!=1 &&
         productRecord.getProductQuantity()!=1 &&
          productRecord.getProductTotalAmount()!=1))
     {
        return true;
     }
     else return false;
 }

 public void addEmptyRow() {
     dataVector.add(new Product());
     fireTableRowsInserted(
        dataVector.size() - 1,
        dataVector.size() - 1);
 }}
最后一节课如下:

 public final class InteractiveForm extends JPanel {

 public static final String[] columnNames = {
     "Quantity", "Product Code", "Product Description", "Product Price","Product Quantity",""
 };

 protected JTable table;
 protected JScrollPane scroller;
 protected InteractiveTableModel tableModel;

 public InteractiveForm() {
     initComponent();
 }

 public void initComponent() {
     tableModel = new InteractiveTableModel(columnNames);
     tableModel.addTableModelListener(new InteractiveForm.InteractiveTableModelListener());
     table = new JTable();
     table.setModel(tableModel);
     table.setSurrendersFocusOnKeystroke(true);
     if (!tableModel.hasEmptyRow()) {
         tableModel.addEmptyRow();
     }

     scroller = new javax.swing.JScrollPane(table);
     table.setPreferredScrollableViewportSize(new java.awt.Dimension(500, 300));
     TableColumn hidden = table.getColumnModel().getColumn(InteractiveTableModel.HIDDEN_INDEX);
     hidden.setMinWidth(2);
     hidden.setPreferredWidth(2);
     hidden.setMaxWidth(2);
     hidden.setCellRenderer(new InteractiveRenderer(InteractiveTableModel.HIDDEN_INDEX));

     setLayout(new BorderLayout());
     add(scroller, BorderLayout.CENTER);
 }


 public void highlightLastRow(int row) {
     int lastrow = tableModel.getRowCount();//return the number of rows - last row
     if (row == lastrow - 1) {
         table.setRowSelectionInterval(lastrow - 1, lastrow - 1);
     } else {
         table.setRowSelectionInterval(row + 1, row + 1);
     }

     table.setColumnSelectionInterval(0, 0);//setting it to the first column
 }

 class InteractiveRenderer extends DefaultTableCellRenderer {
     protected int interactiveColumn;

     public InteractiveRenderer(int interactiveColumn) {
         this.interactiveColumn = interactiveColumn;
     }

     @Override
     public Component getTableCellRendererComponent(JTable table,
        Object value, boolean isSelected, boolean hasFocus, int row,
        int column)
     {
         Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
         if (column == interactiveColumn && hasFocus) {
             if ((InteractiveForm.this.tableModel.getRowCount() - 1) == row &&
                !InteractiveForm.this.tableModel.hasEmptyRow())
             {
                 InteractiveForm.this.tableModel.addEmptyRow();//this is where we append a new row
             }

             highlightLastRow(row);//making it get focus and highlighted
         }

         return c;//returning the component
     }
 }

 public class InteractiveTableModelListener implements TableModelListener {
     @Override
     public void tableChanged(TableModelEvent evt) {
         if (evt.getType() == TableModelEvent.UPDATE) {
             int column = evt.getColumn();
             int row = evt.getFirstRow();
             System.out.println("row: " + row + " column: " + column);
             table.setColumnSelectionInterval(column + 1, column + 1);
             table.setRowSelectionInterval(row, row);
         }
     }
 }

 public static void main(String[] args) {
     try {
         UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
         JFrame frame = new JFrame("Interactive Form");
         frame.addWindowListener(new WindowAdapter() {
             @Override
             public void windowClosing(WindowEvent evt) {
                 System.exit(0);
             }
         });
         frame.getContentPane().add(new InteractiveForm());
         frame.pack();
         frame.setVisible(true);
     } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException | HeadlessException e) {
     }
 }}
我与上面链接表的唯一区别是添加了我自己的变量,这些变量不应该使它不起作用


如何使我的表的行为与相同?

您正在设置空值。它可以与Double.class一起工作,而不是Double.class

    public class Product {
    String productDescription;
    String productCode;
    Double productPrice;
    //dummy properties
    Double productQuantity;
    Double productTotalAmount;
..
    @Override
        public Class getColumnClass(int column) {// returns a class representing the datatype of the data stored in that column
       switch (column) {
           case PRODUCT_DESCRIPTION_INDEX:
           case PRODUCT_CODE_INDEX:
              return String.class;
           case PRODUCT_QUANTITY_INDEX:
           case PRODUCT_PRICE_INDEX:
           case PRODUCT_TOTAL_AMOUNT_INDEX:
               return Double.class;
           default:
              return Object.class;
       }
    }
...
更新
与装箱/拆箱有关的东西。我知道该由谁来修理,但我仍然不知道真正的原因

首先,修改模型不是一个单元格渲染的责任,这是一个非常糟糕的主意,为此,您需要深入研究键绑定和单元格/行选择models@MadProgrammer如何进行键绑定和单元格/行选择模型?示例代码和链接将有助于搜索“如何使用密钥绑定”,直到我女儿决定睡觉,这就是我所能做的。我不确定隐藏列的目的是什么,但尽我所能,你不需要它。表模型应该包装数据…只是说…您的表模型应该返回column@PbxMan这很好!!!但这不会影响表中的数据吗?因为我希望表采用双精度、整数和字符串?还有,难道没有办法不把我的数据类型转换成字符串就可以工作吗?@Giovanrich看起来你可以。检查更新。我仍然不知道真正的原因。我认为这是因为API不处理原语,而只处理对象。我需要更深入的挖掘来回答这个问题。@PbxMan和更新它也起了作用。请允许我说声谢谢,我被困在这里了。我还必须使用整数。你们真是太棒了,更新真的很有效。我认为隐藏列用于设置逻辑“此列不可编辑”。因此,这意味着每当光标位于该列时,
isCellEditable()
返回false,如下所示:
public boolean isCellEditable(int行,int列){if(column==HIDDEN_INDEX)返回false;else返回true;}