Java 自定义可更改的、意外的行为

Java 自定义可更改的、意外的行为,java,swing,jtable,Java,Swing,Jtable,为了创建自定义JTable结构,我从一个非常简单的项目开始,以便更好地理解。不幸的是,一旦我开始定制东西,我就会有奇怪的行为,我希望你能帮助我理解它们。多谢各位 以下是我的小项目: public class Tableau extends JFrame { public Tableau() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(800,600); setCont

为了创建自定义JTable结构,我从一个非常简单的项目开始,以便更好地理解。不幸的是,一旦我开始定制东西,我就会有奇怪的行为,我希望你能帮助我理解它们。多谢各位

以下是我的小项目:

public class Tableau extends JFrame {

    public Tableau() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(800,600);
        setContentPane(new Panel());
        setVisible(true);
    }

    public static void main(String[] args) {
        new Tableau();
    }
    private static class Panel extends JPanel {
        private JTable table = new Table(4, 4);
        public Panel() {
            add(table);
        }
    }

    private static class Table extends JTable {
        private Renderer randerer = new Renderer();
        public Table(int row, int col) {
            super(new Model(row, col));
            setAutoResizeMode(AUTO_RESIZE_OFF);
            setDefaultRenderer(String.class, randerer);
            setDefaultEditor(String.class, randerer);
        }

        private class Renderer implements TableCellRenderer, TableCellEditor {
            String previousContent = "";
            JTextPane rendererComponent = new JTextPane();
            public Renderer() {
                super();setOpaque(true);
            }
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                rendererComponent.setText((String)value);
                rendererComponent.setBorder(hasFocus ? BorderFactory.createLineBorder(Color.RED) : null);
                rendererComponent.setBackground(isSelected ? Color.PINK : Color.GREEN);
                FontMetrics fm = rendererComponent.getFontMetrics(rendererComponent.getFont());
                if(((String)value).length()!=0) {rendererComponent.setPreferredSize(new Dimension(fm.stringWidth((String)value),fm.getHeight()));}
                else {rendererComponent.setPreferredSize(new Dimension(20, fm.getHeight()));}
                return rendererComponent;
            }

            @Override
            public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
                rendererComponent.setText((String)value);
                rendererComponent.setBackground(isSelected ? table.getSelectionBackground() : Color.MAGENTA);
                if(isSelected) {rendererComponent.selectAll();}
                previousContent = (String)value;
                return rendererComponent;
            }

            @Override
            public Object getCellEditorValue() {
                return rendererComponent.getText();
            }

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

            @Override
            public boolean shouldSelectCell(EventObject anEvent) {
                return true;
            }

            @Override
            public boolean stopCellEditing() {
                fireEditingStoppedEvent();
                return true;
            }

            @Override
            public void cancelCellEditing() {
                rendererComponent.setText(previousContent);
                fireEditingCanceledEvent();
            }

            protected void fireEditingStoppedEvent() {
                for(CellEditorListener l : listeners) {l.editingStopped(new ChangeEvent(this));}
            }

            protected void fireEditingCanceledEvent() {
                for(CellEditorListener l : listeners) {l.editingCanceled(new ChangeEvent(this));}
            }

            private List<CellEditorListener> listeners = new LinkedList<CellEditorListener>();
            @Override
            public void addCellEditorListener(CellEditorListener l) {
                listeners.add(l);
            }

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

        }
    }

    private static class Model implements TableModel {
//        private ColumnModel colonnes = new ColumnModel();
        private List<List<Cellule>> colonnes = new LinkedList<List<Cellule>>();
        private int rowCount = 0;
//        private List<Cellule> cellules = new LinkedList<Cellule>();

        private static class Cellule {
            public Cellule() {}
            public Cellule(Object content) {this.content = content;}
            private Object content;
            private Object getContent() {return content;}
            private void setContent(Object newContent) {content = newContent;}
        }

        public Model(int row, int col) {
            for(int j=0; j<col; j++) {
                insertColumn(j);
            }
            for(int i=0; i<row; i++) {
                insertRow(i);
            }
        }

        @Override
        public int getRowCount() {
            return rowCount;
        }

        @Override
        public int getColumnCount() {
            return colonnes.size();
        }

        @Override
        public String getColumnName(int columnIndex) {
            String result = "";
            for (; columnIndex >= 0; columnIndex = columnIndex / 26 - 1) {
                result = (char)((char)(columnIndex%26)+'A') + result;
            }
            return result;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return colonnes.isEmpty() ? Object.class : getValueAt(columnIndex, 0).getClass();
        }

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

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return colonnes.get(columnIndex).get(rowIndex).getContent();
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            colonnes.get(columnIndex).get(rowIndex).setContent(aValue);
            fireTableChanged(new TableModelEvent(this, rowIndex, rowIndex, columnIndex, TableModelEvent.UPDATE));
        }

        protected void fireTableChanged(TableModelEvent e) {
            for(TableModelListener l : listeners) {
                l.tableChanged(null);
            }
        }

        public void insertColumn(int index) {
            List<Cellule> newColumn = new LinkedList<Cellule>();
            for(int i = 0; i<getRowCount(); i++) {
                Cellule newCell = new Cellule("");
                newColumn.add(newCell);
            }
            colonnes.add(index, newColumn);
            fireTableChanged(new TableModelEvent(this, 0, getRowCount(), index, TableModelEvent.INSERT));
        }

        public void insertRow(int index) {
            for(List<Cellule> colonne : colonnes) {
                Cellule newCell = new Cellule("");
                colonne.add(index, newCell);
            }
            rowCount++;
            fireTableChanged(new TableModelEvent(this, index, index, TableModelEvent.ALL_COLUMNS, TableModelEvent.INSERT));
        }

        public void removeColumn(int index) {
            colonnes.remove(index);
            fireTableChanged(new TableModelEvent(this, 0, getRowCount(), index, TableModelEvent.DELETE));
        }

        public void removeRow(int index) {
            for(List<Cellule> row : colonnes) {
                row.remove(index);
            }
            rowCount--;
            fireTableChanged(new TableModelEvent(this, index, index, TableModelEvent.ALL_COLUMNS, TableModelEvent.DELETE));
        }

        private List<TableModelListener> listeners = new LinkedList<TableModelListener>();
        @Override
        public void addTableModelListener(TableModelListener l) {
            listeners.add(l);
        }

        @Override
        public void removeTableModelListener(TableModelListener l) {
            listeners.remove(l);
        }

    }

}
基本上,我们有一个JFrame类表,其中包含一个JPanel类面板,其中包含一个JTable类表。此表使用TableModel类模型和JTextPane类呈现器,用于呈现和编辑表内容

以下是我的问题:

1如果我单击一个单元格,它将变为白色,我不明白在给定渲染器代码的情况下,这是如何可能的。。。。如果我写了什么,首先,单元格中没有显示任何内容,但是,当我移动焦点时,文本会出现

2如果我单击一个单元格,然后使用箭头键移动焦点,那么选择似乎是正确的。红色边框显示正确,等等。为什么我只单击而不使用箭头时选择不正确


谢谢

这实际上是4个独立的问题,其中一些问题可以在文档中得到回答。我将从这里删除它,用我的尝试创建一个新问题。1和2都是相互关联的,是我最感兴趣的。3只是有一个意见,但我可以删除它。谢谢3在教程中有答案,有一种简单的方法可以更改选择操作。1关于为什么会有一堆TableCellEditor关于列表中的循环,2有多少JTables已经与一个模型JTable表链接;,因为您需要在renderer/editor类中传递JTable,3然后JTextPane可以是局部变量,而不是扩展的原因,4 putClientPropertyterminateEditOnFocusLost,Boolean.TRUE;==stopCellEditing,那么stopCellEditing是反生产力的5返回冒号的原因是什么?行数:colonnes.get0.size;,单元格可以有空值太6通知表模型是错误的,顺便说一句fireTableChanged重置tablemodel,不是好主意,你可以很简单地丢失所有自定义TableCellRenderer/编辑器。。。。等