0

我有一个包含 N 行和 2 列的 JTable 我需要实现一个自定义 CellEditor 类来访问每个单元格的数据输入

table.getCellEditor(int row, int column).getCellEditorValue()

我用过这个 CellEditor 类

class MyEditor extends DefaultCellEditor {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private JTextField textField;
        private boolean valueSet;
          public MyEditor() {
            super(new JTextField());
          }

          @Override
            public boolean isCellEditable(EventObject eo) {
                System.err.println("isCellEditable");
                if (eo instanceof KeyEvent) {
                    KeyEvent ke = (KeyEvent) eo;
                    System.err.println("key event: " + ke.getKeyChar());
                    textField.setText(String.valueOf(ke.getKeyChar()));
                    valueSet = true;
                } else {
                    valueSet = false;
                }
                return true;
            }
    }

但不足以访问正确单元格位置的数据......(似乎所有表格都被视为一个完整的单元格)

我发现的所有示例都与使用单元格编辑器在输入不正确但足够清晰可以帮助我解决问题的情况下阻止编辑单元格有关。

PS如果您想详细了解整个界面(不)如何工作,则整个代码是这样的:

public class CompileDataJob extends JFrame {
      private boolean DEBUG = false;
    private JPanel contentPane;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    CompileDataJob frame = new CompileDataJob();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    /**
     * Create the frame.
     */
    public CompileDataJob() {
        setTitle("Inserisci i parametri dei lavori");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 551, 293);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);

        JPanel panel_1 = new JPanel();
        final JTable table = new JTable(new MyTableModel());

        JButton btnNewButton = new JButton("    OK   ");
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try{
                    DataJobManager.azzeraListaLavori();
                    int numJob=DataJobManager.loadNumeroLavori();
                    LinkedList<Job> listaLavori=new LinkedList<Job>();
                    String id;
                    int time;
                    for (int rowIndex=0; rowIndex<numJob; rowIndex++){
                            id=(String)(table.getCellEditor(rowIndex,0).getCellEditorValue());
                            time=Integer.parseInt(((String)((table.getCellEditor(rowIndex, 1)).getCellEditorValue())));
                            Job l=new Job(id,time);
                            listaLavori.add(l);
                    }
                        DataJobManager.saveListaLavori(listaLavori);
                        CompileDataJob.this.dispose();
                        JOptionPane.showMessageDialog(CompileDataJob.this,"Data Saved");
                }catch(Exception ecc){
                    JOptionPane.showMessageDialog(CompileDataJob.this,"Error during the saving.");
                }
            }
        });
        panel_1.add(btnNewButton);

        JButton btnNewButton_1 = new JButton("Cancel");
        btnNewButton_1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                CompileDataJob.this.dispose();
            }
        });

        JPanel panel = new JPanel();



        table.setDefaultEditor(Object.class,new MyEditor());

        table.setPreferredScrollableViewportSize(new Dimension(500, 70));
        table.setFillsViewportHeight(true);
        table.getSelectionModel().addListSelectionListener(
                new ListSelectionListener() {
                    public void valueChanged(ListSelectionEvent event) {
                        int viewRow = table.getSelectedRow();
                        JLabel statusText=new JLabel();
                        if (viewRow < 0) {
                            //Selection got filtered away.
                            statusText.setText("");
                        } else {
                            int modelRow = 
                                table.convertRowIndexToModel(viewRow);
                            statusText.setText(
                                String.format("Selected Row in view: %d. " +
                                    "Selected Row in model: %d.", 
                                    viewRow, modelRow));
                        }
                    }
                }
        );


                //Create the scroll pane and add the table to it.
                JScrollPane scrollPane = new JScrollPane(table);

                        //Set up column sizes.
                        initColumnSizes(table);

        panel_1.add(btnNewButton_1);
        GroupLayout gl_contentPane = new GroupLayout(contentPane);
        gl_contentPane.setHorizontalGroup(
            gl_contentPane.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_contentPane.createSequentialGroup()
                    .addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING, false)
                        .addComponent(panel_1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(panel, GroupLayout.DEFAULT_SIZE, 525, Short.MAX_VALUE))
                    .addContainerGap())
        );
        gl_contentPane.setVerticalGroup(
            gl_contentPane.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_contentPane.createSequentialGroup()
                    .addComponent(panel, GroupLayout.PREFERRED_SIZE, 213, GroupLayout.PREFERRED_SIZE)
                    .addPreferredGap(ComponentPlacement.RELATED, 61, Short.MAX_VALUE)
                    .addComponent(panel_1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
        );
        GroupLayout gl_panel = new GroupLayout(panel);
        gl_panel.setHorizontalGroup(
            gl_panel.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_panel.createSequentialGroup()
                    .addGap(11)
                    .addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(12, Short.MAX_VALUE))
        );
        gl_panel.setVerticalGroup(
            gl_panel.createParallelGroup(Alignment.LEADING)
                .addGroup(gl_panel.createSequentialGroup()
                    .addGap(5)
                    .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE)
                    .addContainerGap())
        );
        panel.setLayout(gl_panel);
        contentPane.setLayout(gl_contentPane);



    }

    private void initColumnSizes(JTable table) {
        MyTableModel model = (MyTableModel)table.getModel();
        TableColumn column = null;
        Component comp = null;
        int headerWidth = 0;
        int cellWidth = 0;
        Object[] longValues = model.longValues;
        TableCellRenderer headerRenderer =
            table.getTableHeader().getDefaultRenderer();

        for (int i = 0; i < 2; i++) {
            column = table.getColumnModel().getColumn(i);

            comp = headerRenderer.getTableCellRendererComponent(
                                 null, column.getHeaderValue(),
                                 false, false, 0, 0);
            headerWidth = comp.getPreferredSize().width;

            comp = table.getDefaultRenderer(model.getColumnClass(i)).
                             getTableCellRendererComponent(
                                 table, longValues[i],
                                 false, false, 0, i);
            cellWidth = comp.getPreferredSize().width;

            if (DEBUG) {
                System.out.println("Initializing width of column "
                                   + i + ". "
                                   + "headerWidth = " + headerWidth
                                   + "; cellWidth = " + cellWidth);
            }

            column.setPreferredWidth(Math.max(headerWidth, cellWidth));
        }
    }

    class MyEditor extends DefaultCellEditor {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private JTextField textField;
        private boolean valueSet;
          public MyEditor() {
            super(new JTextField());
          }

          @Override
            public boolean isCellEditable(EventObject eo) {
                System.err.println("isCellEditable");
                if (eo instanceof KeyEvent) {
                    KeyEvent ke = (KeyEvent) eo;
                    System.err.println("key event: " + ke.getKeyChar());
                    textField.setText(String.valueOf(ke.getKeyChar()));
                    //textField.select(1,1);
                    //textField.setCaretPosition(1);
                    //textField.moveCaretPosition(1);
                    valueSet = true;
                } else {
                    valueSet = false;
                }
                return true;
            }
    }





    class MyTableModel extends AbstractTableModel {
        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        private String[] columnNames = {"Nome Job", "Durata"};
        int numJob=DataJobManager.loadNumeroLavori();
        private Object[][] data = getDatiDefaultTabella();

        public class Job {
            public int time; // Should n't this be a long?
            public String jobName;
        }

        public Object[][] getDatiDefaultTabella(){
            Object[][] tabella=new Object[numJob][2];
            for(int i=0; i<numJob; i++){
                for(int j=0; j<2; j++){
                    tabella[i][j]="inserisci dati";
                }
            }

            return tabella;
        }

        public Object[][] getTabella(){
            return data;
        }


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

        public int getRowCount() {
            return numJob;
        }

        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.
         */
        public Class getRowClass(int r) {
            return getValueAt(r, 0).getClass();
        }

        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.
            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.
     */

        public void run() {
            try {
                CompileDataJob frame = new CompileDataJob();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
}
4

2 回答 2

1

好吧,我想我明白了。我稍微优化了你的代码并删除了我不需要的东西。您可以再次添加它。

这是编译数据作业

public class CompileDataJob extends JFrame {
    final boolean DEBUG = false;
  private final JPanel contentPane;

  /**
   * Launch the application.
   */
  public static void main(String[] args) {
      EventQueue.invokeLater(new Runnable() {
          public void run() {
              try {
                  CompileDataJob frame = new CompileDataJob();
                  frame.setVisible(true);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      });
  }

  /**
   * Create the frame.
   */
  public CompileDataJob() {
      setTitle("Inserisci i parametri dei lavori");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setBounds(100, 100, 551, 293);
      contentPane = new JPanel();
      contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
      setContentPane(contentPane);

      JPanel panel_1 = new JPanel();
      final JTable table = new JTable(new MyTableModel());

      JButton add = new JButton(" ADD ");
      add.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            ((MyTableModel)table.getModel()).addRow(new Job(0, ""));
        }
      });

      JButton btnNewButton = new JButton("    OK   ");
      btnNewButton.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent e) {
              try{
                      DataJobManager.saveListaLavori(((MyTableModel)table.getModel()).getJobs());
                      CompileDataJob.this.dispose();
                      JOptionPane.showMessageDialog(CompileDataJob.this,"Data Saved");
              }catch(Exception ecc){
                  JOptionPane.showMessageDialog(CompileDataJob.this,"Error during the saving.");
              }
          }
      });
      panel_1.add(btnNewButton);
      panel_1.add(add);
      JButton btnNewButton_1 = new JButton("Cancel");
      btnNewButton_1.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent arg0) {
              CompileDataJob.this.dispose();
          }
      });

      JPanel panel = new JPanel();



//      table.setDefaultEditor(Object.class,new MyEditor());

      table.setPreferredScrollableViewportSize(new Dimension(500, 70));
      table.setFillsViewportHeight(true);

              //Create the scroll pane and add the table to it.
              JScrollPane scrollPane = new JScrollPane(table);


      panel_1.add(btnNewButton_1);
      GroupLayout gl_contentPane = new GroupLayout(contentPane);
      gl_contentPane.setHorizontalGroup(
          gl_contentPane.createParallelGroup(Alignment.LEADING)
              .addGroup(gl_contentPane.createSequentialGroup()
                  .addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING, false)
                      .addComponent(panel_1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                      .addComponent(panel, GroupLayout.DEFAULT_SIZE, 525, Short.MAX_VALUE))
                  .addContainerGap())
      );
      gl_contentPane.setVerticalGroup(
          gl_contentPane.createParallelGroup(Alignment.LEADING)
              .addGroup(gl_contentPane.createSequentialGroup()
                  .addComponent(panel, GroupLayout.PREFERRED_SIZE, 213, GroupLayout.PREFERRED_SIZE)
                  .addPreferredGap(ComponentPlacement.RELATED, 61, Short.MAX_VALUE)
                  .addComponent(panel_1, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
      );
      GroupLayout gl_panel = new GroupLayout(panel);
      gl_panel.setHorizontalGroup(
          gl_panel.createParallelGroup(Alignment.LEADING)
              .addGroup(gl_panel.createSequentialGroup()
                  .addGap(11)
                  .addComponent(scrollPane, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                  .addContainerGap(12, Short.MAX_VALUE))
      );
      gl_panel.setVerticalGroup(
          gl_panel.createParallelGroup(Alignment.LEADING)
              .addGroup(gl_panel.createSequentialGroup()
                  .addGap(5)
                  .addComponent(scrollPane, GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE)
                  .addContainerGap())
      );
      panel.setLayout(gl_panel);
      contentPane.setLayout(gl_contentPane);



  }
}

这是工作

public class Job {
    public int time = 500; // Should n't this be a long?
    public String jobName;
    public boolean processed = false;

    public Job(int time, String jobName) {
        this.time = time;
        this.jobName = jobName;
    }

    public boolean isProcessed() {
        return processed;
    }
}

这是您的 TableModel,它是可优化的,但可以工作......

class MyTableModel extends AbstractTableModel {
    private static final long serialVersionUID = 1L;
    private final List<Job> objects = new ArrayList<Job>();
    private final String[] columnNames = { "Nome Job", "Durata", "processed" };

    private final Class<?>[] metaModell = new Class[]{String.class, Integer.class, Boolean.class};

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

    public int getRowCount() {
        return objects.size();
    }

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

    public Object getValueAt(int row, int col) {
        if (row >= objects.size()) 
            return null;
        Job job = getRow(row);
        switch (col) {
            case 0:
                return job.jobName;
            case 1:
                return job.time;
            case 2:
                return job.isProcessed();
        }
        return null;
    }

    private Job getRow(int row) {
        return objects.get(row);
    }

    @Override
    public Class<?> getColumnClass(int c) {
        if (c < metaModell.length)
            return metaModell[c];
        return Object.class;
    }

    @Override
    public boolean isCellEditable(int row, int col) {
        return col >= 0 && col < columnNames.length;
    }

    @Override
    public void setValueAt(Object value, int row, int col) {
        Job job = getRow(row);
        switch (col) {
            case 0:
                job.jobName = (String) value;
                break;
            case 1:
                job.time = (Integer) value;
                break;
//          case 2:
//              job.processed = (Boolean) value;
//              break;
        }
        fireTableDataChanged();
    }

    public List<Job> getJobs() {
        return objects;
    }

    public void addRow(Job job) {
        this.objects.add(job);
        fireTableDataChanged();
    }
}

正如您将看到的,我从编辑器中删除了所有 MyEditor 内容和复杂的 getValues。相反,我向表模型添加了一个方法addJob()和。getJobs

于 2012-04-10T14:38:50.367 回答
0

好的,你的类确实定义了一个 CellEditor,但它没有做任何 DefaultEditor 不会做的事情。

此外,你不要把它粘在一起。您的 JTable 不知道它应该使用哪个 CellEditor。您必须告诉您的表使用您的编辑器实现。有多种方法可以做到这一点(例如,为类设置默认渲染器,由您的 tablemodel 返回)。您还可以将 CellEditor 直接分配给列( column.setCellEditor(new MyCellEditor());--> http://docs.oracle.com/javase/tutorial/uiswing/components/table.html

于 2012-04-09T18:19:07.780 回答