首页 文章

JTable删除行

提问于
浏览
1

我有一个列 JTable ,我设置了一个自定义 TableCellRenderer 和一个自定义 TableCellEditor ,它返回一个包含JTextField,JLabel,JButtons和JProgressBar的JPanel

当我尝试从表模型中删除一行时,这是一个扩展AbstractTableModel的类 . 这是删除行的方法 .

public void removeRow(int row) {
 myList.remove(row);
 fireTableRowsDeleted(row, row);
}

TableModel.fireTableRowsDeleted(int row)不起作用,因为我的表在视图中一直显示已删除的行 . 另一方面,方法TableModel.fireTableStructureChanged();正确更新JTable . 我应该使用哪一个?我检查了DefaultTableModel.removeRow(int row)方法,它只使用fireTableRowsDeleted(int row);.

public class TableTest {

    final static MyObjectTableModel model = new MyObjectTableModel();
    final static JTable table = new JTable(model);
    private static Map<Integer, Future> mapSubmittedReadProgress = new HashMap<Integer, Future>();
    final static StartProgressActionListener progressActionListener = new StartProgressActionListener();

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TableTest().createGUI();
            }
        });
    }

    public static class MyObjectTableModel extends AbstractTableModel {

        private LinkedList<MyObject> myList;

        public MyObjectTableModel() {
            super();
            myList = new LinkedList<MyObject>();
        }

        public MyObjectTableModel(SortedSet<MyObject> myObjects) {
            super();
            this.myList = new LinkedList<MyObject>(myObjects);
        }

        public void addRow(MyObject myObject) {
            myList.add(myObject);
            fireTableRowsInserted(myList.size() - 1, myList.size() - 1);
        }

        public void removeRow(int row) {
            myList.remove(row);
            fireTableRowsDeleted(row, row);
//      fireTableStructureChanged();
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            myList.set(rowIndex, (MyObject) aValue);
            fireTableCellUpdated(rowIndex, 0);
        }

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

        @Override
        public int getColumnCount() {
            return 1;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            switch (columnIndex) {
                case 0:
                    return MyObject.class;
                default:
                    throw new IllegalArgumentException("invalid column: " + columnIndex);
            }
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            switch (columnIndex) {
                case 0:
                    return myList.get(rowIndex);
                default:
                    throw new IllegalArgumentException("invalid column: " + columnIndex);
            }
        }

        public MyObject getMyObjectAt(int row) {
            return myList.get(row);
        }

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

        public int getIndexOf(MyObject myObject) {
            return myList.indexOf(myObject);
        }
    }

    private static void createGUI() {
        JFrame f = new JFrame("TableTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        for (int i = 0; i < 16; i++) {
            MyObject myObject = new MyObject();
            myObject.setText1("" + i);
            model.addRow(myObject);
        }
        table.setOpaque(false);
        table.setShowGrid(false);
        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
//        table.getSelectionModel().addListSelectionListener(new SelectionListener());
        table.setDefaultRenderer(MyObject.class, new MyTableCellRenderer());
        table.setDefaultEditor(MyObject.class, new MyTableCellEditor());
        table.setFillsViewportHeight(true);
        f.add(new JScrollPane(table));

        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor {

        private MyObjectPanel myObjectPanel = new MyObjectPanel(model, table);
        private transient List<CellEditorListener> listeners;

        public MyTableCellEditor() {
            myObjectPanel.addStartProgressActionListener(progressActionListener);
            listeners = new ArrayList<>();
        }

        @Override
        public boolean isCellEditable(EventObject e) {
            return true;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            MyObject myObject = (MyObject) value;
            myObjectPanel.setMyObject(myObject, row);
            return myObjectPanel;
        }

        @Override
        public Object getCellEditorValue() {
            MyObject myObject = myObjectPanel.getMyObject();
            return myObject;
        }

        @Override
        public void addCellEditorListener(CellEditorListener l) {
            listeners.add(l);
        }

        @Override
        public void removeCellEditorListener(CellEditorListener l) {
            listeners.remove(l);
        }

        @Override
        protected void fireEditingStopped() {
            ChangeEvent ce = new ChangeEvent(this);
            for (int i = listeners.size() - 1; i >= 0; i--) {
                ((CellEditorListener) listeners.get(i)).editingStopped(ce);
            }
        }
    }

    private static class MyTableCellRenderer implements TableCellRenderer {

        private MyObjectPanel myObjectPanel = new MyObjectPanel(model, table);

        public MyTableCellRenderer() {
            myObjectPanel.addStartProgressActionListener(progressActionListener);
//            setOpaque(false);
            int cWidth = table.getWidth();
//            setSize(new Dimension(cWidth, 1000));
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            MyObject myObject = (MyObject) value;
            myObjectPanel.setMyObject(myObject, row);
            table.setRowHeight(row, myObjectPanel.getPreferredSize().height);
            return myObjectPanel;
        }
    }

    private static class StartProgressActionListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            if(table.isEditing()) {
                table.getCellEditor().stopCellEditing();
            }
            final ExecutorService executor = Executors.newFixedThreadPool(1);
            Runnable progressRunnable = new ProgressRunnable(table.getSelectedRow());
            final Future<?> submit = executor.submit(progressRunnable);
            mapSubmittedReadProgress.put(table.getSelectedRow(), submit);
        }
    }

    private static class ProgressRunnable implements Runnable {

        private ExecutorService executor;
        private long beT;
        private int dur = 30; // s
        private int progress = 0;
        private int row;

        public ProgressRunnable(int row) {
            this.row = row;
            beT = System.currentTimeMillis();
        }

        @Override
        public void run() {
            boolean abort = false;
            int i = 0;
            while (i <= dur && !abort) {
                final long curT = System.currentTimeMillis();
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    abort = true;
                    executor.shutdown();
                }
                if (Thread.currentThread().isInterrupted()) {
                    abort = true;
                    executor.shutdown();
                }
                progress = (int) Math.round(100 * ((double) (curT - beT) / 1000) / dur);
                MyObject myObject = new MyObject();
                myObject.setProgress(progress);
                table.setValueAt(myObject, row, 0);
                i++;
            }
        }
    }
}

MyObject:

public class MyObject {
    private String text1;
    private String text2;
    private int progress;

    public String getText1() {
        return text1;
    }

    public void setText1(String text1) {
        this.text1 = text1;
    }

    public String getText2() {
        return text2;
    }

    public void setText2(String text2) {
        this.text2 = text2;
    }

    public int getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        this.progress = progress;
    }
}

MyObjectPanel:

public class MyObjectPanel extends javax.swing.JPanel {

private int row;
private MyObjectTableModel model;
private JTable table;

/**
 * Creates new form MyObjectPanel
 */
public MyObjectPanel() {
    initComponents();
}

MyObjectPanel(MyObjectTableModel model, JTable table) {
    this.model = model;
    this.table = table;
    initComponents();
}

/**
 * This method is called from within the constructor to initialize the form.
 * WARNING: Do NOT modify this code. The content of this method is always
 * regenerated by the Form Editor.
 */
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {

    jTextField1 = new javax.swing.JTextField();
    jTextField2 = new javax.swing.JTextField();
    jProgressBar1 = new javax.swing.JProgressBar();
    btnStart = new javax.swing.JButton();
    btnStop = new javax.swing.JButton();
    btnClose = new javax.swing.JButton();

    btnStart.setText("Start");

    btnStop.setText("Stop");

    btnClose.setText("Close");
    btnClose.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            btnCloseActionPerformed(evt);
        }
    });

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
    this.setLayout(layout);
    layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jTextField1)
            .addComponent(jTextField2)
            .addComponent(jProgressBar1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
            .addComponent(btnStart)
            .addGap(18, 18, 18)
            .addComponent(btnStop)
            .addGap(18, 18, 18)
            .addComponent(btnClose)
            .addGap(0, 199, Short.MAX_VALUE)))
            .addContainerGap()));
    layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jTextField1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
            .addComponent(jTextField2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGap(18, 18, 18)
            .addComponent(jProgressBar1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addGap(18, 18, 18)
            .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
            .addComponent(btnStart)
            .addComponent(btnStop)
            .addComponent(btnClose))
            .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
}// </editor-fold>

private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {
    System.out.println("getMyObjectRow() : " + getMyObjectRow());
    table.getCellEditor().stopCellEditing();
    model.removeRow(getMyObjectRow());
}
// Variables declaration - do not modify
private javax.swing.JButton btnClose;
private javax.swing.JButton btnStart;
private javax.swing.JButton btnStop;
private javax.swing.JProgressBar jProgressBar1;
private javax.swing.JTextField jTextField1;
private javax.swing.JTextField jTextField2;
// End of variables declaration

void setMyObject(MyObject myObject, int row) {
    this.row = row;
    jTextField1.setText(myObject.getText1());
    jTextField2.setText(myObject.getText2());
    jProgressBar1.setValue(myObject.getProgress());
}

int getMyObjectRow() {
    return this.row;
}

MyObject getMyObject() {
    MyObject myObject = new MyObject();
    myObject.setText1(jTextField1.getText());
    myObject.setText2(jTextField2.getText());
    myObject.setProgress(jProgressBar1.getValue());
    return myObject;
}

void addStartProgressActionListener(ActionListener progressActionListener) {
    btnStart.addActionListener(progressActionListener);
}

编辑:工作SSCCE使用面板的netbeans GUI构建器显示结束问题 . 它似乎是一个索引问题,但无法稍后在进度条工作时尝试发布完整的例子 .

编辑2:当单元格获得焦点时,我的进度条没有更新时出现问题 . 关闭问题已经解决 .

1 回答

  • 1

    我试过了你的 TableModel 并且运行正常 . 您的代码中的其他位置必定存在问题 . 我找不到 MyObject ,因此默认渲染器使用 Object#toString() 显示空的渲染器 .

    public class TableTest {
    
        private static class MyObject {
            // empty
        }
    
        private static class MyObjectTableModel extends AbstractTableModel {
            // no change
        }
    
        private static void createGUI() {
            JFrame f = new JFrame("TableTest");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            final MyObjectTableModel model = new MyObjectTableModel();
            for (int i = 0; i < 16; i++) {
                model.addRow(new MyObject());
            }
            JTable table = new JTable(model);
            f.add(new JScrollPane(table));
            f.add(new JButton(new AbstractAction("Remove") {
                @Override
                public void actionPerformed(ActionEvent e) {
                    model.removeRow(0);
                }
            }), BorderLayout.SOUTH);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new TableTest().createGUI();
                }
            });
        }
    }
    

相关问题