如何在禁用编辑的JTable单元格中选择文本?(How do I make it possible to select text in a JTable cell with editing disabled?)

想象一下,我正在用Java构建一个IRC客户端,我想在聊天视图中使用富文本来显示IRC颜色和彩色刻痕。 我想用JTable构建它。 我可以这样做,但文字是不可选择的。 使表格可编辑没有意义。

我也调查过:

TextArea - 没有富文本格式 JEdi​​tPane - 无法追加,只能取代哪些是性能不佳的明智之举 JList - 无法选择文本

所以我有一张桌子工作,我只需要在不使其可编辑的情况下选择文本。 我也只想要文本内容,并且在复制文本选择时没有HTML被复制到剪贴板中。

我尝试过setRowSelectionAllowed() , setColumnSelectionEnabled()和setCellSelectionEnabled()以及setSelectionMode的各种迭代,表模型为isCellEditable()返回false。 什么都没有使文本可选。

编辑:根据答案1我错误的文本编辑器窗格,所以我正在尝试这些解决方案。

Imagine I'm building an IRC client with Java and I'd like rich text in the chat view to show IRC colors and colored nicks. I'd like to build this with a JTable. I can do that, but the text is then not selectable. Making the table editable doesn't make sense.

I've also investigated:

TextArea - no rich text formatting JEditPane - can't append, only replace which is bad performance wise JList - can't select text

So I got a table working I just need the text to be selectable without making it editable. I'd also would only like the text contents, and none of the HTML to be copied into the clipboard upon copying the text selection.

I have tried various iterations of setRowSelectionAllowed(), setColumnSelectionEnabled() and setCellSelectionEnabled() and setSelectionMode the table model returns false for isCellEditable(). Nothing has made the text selectable.

EDIT: as per answer 1 I was wrong about text editor panes so I'm trying those solutions.

最满意答案

我不知道你为什么不想使用JTextPane或JEditorPane 。 您按文档插入文本。 这里的示例 - > 如何使用编辑器窗格和文本窗格 。

但是为了你的目的,你可以做一些像这样的事情。 我重写changeSelection以在单击时changeSelection文本,单元格是可编辑的,但其cellEditors不可编辑。

public class JTableTest { private final DefaultCellEditor cellEditor; private final JTextField textfield; private JPanel panel; private MyTableModel tableModel = new MyTableModel(); private JTable table = new JTable() { @Override public TableCellEditor getCellEditor(int row, int column) { return JTableTest.this.cellEditor; } @Override public void changeSelection( final int row, final int column, final boolean toggle, final boolean extend) { super.changeSelection(row, column, toggle, extend); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if ((getCellEditor(row, column) != null && !editCellAt(row, column))) { JTextField textfield=(JTextField)JTableTest.this.cellEditor.getComponent(); textfield.selectAll(); } } }); } }; public JTableTest() { JScrollPane scroll = new JScrollPane(table); table.setModel(tableModel); panel = new JPanel(new BorderLayout()); panel.add(scroll, BorderLayout.CENTER); textfield = new JTextField(); textfield.setEditable(Boolean.FALSE); textfield.setBorder(null); cellEditor = new DefaultCellEditor(textfield); tableModel.insertValue(new ItemRow("nonEditable", "Editable")); } private class ItemRow { private String column1; private String column2; public ItemRow(String column1, String column2) { this.column1 = column1; this.column2 = column2; } public String getColumn1() { return column1; } public void setColumn1(String column1) { this.column1 = column1; } public String getColumn2() { return column2; } public void setColumn2(String column2) { this.column2 = column2; } } private class MyTableModel extends AbstractTableModel { public static final int COLUMN1_INDEX = 0; public static final int COLUMN2_INDEX = 1; private final List<ItemRow> data = new ArrayList<>(); private final String[] columnsNames = { "Column1", "Column2",}; private final Class<?>[] columnsTypes = { String.class, String.class }; public MyTableModel() { super(); } @Override public Object getValueAt(int inRow, int inCol) { ItemRow row = data.get(inRow); Object outReturn = null; switch (inCol) { case COLUMN1_INDEX: outReturn = row.getColumn1(); break; case COLUMN2_INDEX: outReturn = row.getColumn2(); break; default: throw new RuntimeException("invalid column"); } return outReturn; } @Override public void setValueAt(Object inValue, int inRow, int inCol) { System.out.println("Gets called "); if (inRow < 0 || inCol < 0 || inRow >= data.size()) { return; } ItemRow row = data.get(inRow); switch (inCol) { case COLUMN1_INDEX: row.setColumn1(inValue.toString()); break; case COLUMN2_INDEX: row.setColumn2(inValue.toString()); break; } fireTableCellUpdated(inRow, inCol); } @Override public int getRowCount() { return data.size(); } @Override public int getColumnCount() { return columnsTypes.length; } @Override public String getColumnName(int inCol) { return this.columnsNames[inCol]; } @Override public Class<?> getColumnClass(int columnIndex) { return this.columnsTypes[columnIndex]; } /** * * @param row */ public void insertValue(ItemRow row) { data.add(row); fireTableRowsInserted(data.size() - 1, data.size() - 1); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } } private static void createAndShowGUI(final Container container, final String title) { //Create and set up the window. JFrame frame = new JFrame(title); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(Boolean.TRUE); frame.add(container); //Display the window. frame.pack(); frame.setVisible(true); } public static void main(String args[]) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(new JTableTest().panel, "Test"); } }); } }

I don't know why you don't want to use a JTextPane or JEditorPane. You insert text by its document. Examples here --> How to use Editor Panes and Text Panes.

But for your purpose you can for example do something like this. I override changeSelection to selectAll text when is clicking, the cells are editable but its cellEditors are not editable.

public class JTableTest { private final DefaultCellEditor cellEditor; private final JTextField textfield; private JPanel panel; private MyTableModel tableModel = new MyTableModel(); private JTable table = new JTable() { @Override public TableCellEditor getCellEditor(int row, int column) { return JTableTest.this.cellEditor; } @Override public void changeSelection( final int row, final int column, final boolean toggle, final boolean extend) { super.changeSelection(row, column, toggle, extend); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { if ((getCellEditor(row, column) != null && !editCellAt(row, column))) { JTextField textfield=(JTextField)JTableTest.this.cellEditor.getComponent(); textfield.selectAll(); } } }); } }; public JTableTest() { JScrollPane scroll = new JScrollPane(table); table.setModel(tableModel); panel = new JPanel(new BorderLayout()); panel.add(scroll, BorderLayout.CENTER); textfield = new JTextField(); textfield.setEditable(Boolean.FALSE); textfield.setBorder(null); cellEditor = new DefaultCellEditor(textfield); tableModel.insertValue(new ItemRow("nonEditable", "Editable")); } private class ItemRow { private String column1; private String column2; public ItemRow(String column1, String column2) { this.column1 = column1; this.column2 = column2; } public String getColumn1() { return column1; } public void setColumn1(String column1) { this.column1 = column1; } public String getColumn2() { return column2; } public void setColumn2(String column2) { this.column2 = column2; } } private class MyTableModel extends AbstractTableModel { public static final int COLUMN1_INDEX = 0; public static final int COLUMN2_INDEX = 1; private final List<ItemRow> data = new ArrayList<>(); private final String[] columnsNames = { "Column1", "Column2",}; private final Class<?>[] columnsTypes = { String.class, String.class }; public MyTableModel() { super(); } @Override public Object getValueAt(int inRow, int inCol) { ItemRow row = data.get(inRow); Object outReturn = null; switch (inCol) { case COLUMN1_INDEX: outReturn = row.getColumn1(); break; case COLUMN2_INDEX: outReturn = row.getColumn2(); break; default: throw new RuntimeException("invalid column"); } return outReturn; } @Override public void setValueAt(Object inValue, int inRow, int inCol) { System.out.println("Gets called "); if (inRow < 0 || inCol < 0 || inRow >= data.size()) { return; } ItemRow row = data.get(inRow); switch (inCol) { case COLUMN1_INDEX: row.setColumn1(inValue.toString()); break; case COLUMN2_INDEX: row.setColumn2(inValue.toString()); break; } fireTableCellUpdated(inRow, inCol); } @Override public int getRowCount() { return data.size(); } @Override public int getColumnCount() { return columnsTypes.length; } @Override public String getColumnName(int inCol) { return this.columnsNames[inCol]; } @Override public Class<?> getColumnClass(int columnIndex) { return this.columnsTypes[columnIndex]; } /** * * @param row */ public void insertValue(ItemRow row) { data.add(row); fireTableRowsInserted(data.size() - 1, data.size() - 1); } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return true; } } private static void createAndShowGUI(final Container container, final String title) { //Create and set up the window. JFrame frame = new JFrame(title); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLocationByPlatform(Boolean.TRUE); frame.add(container); //Display the window. frame.pack(); frame.setVisible(true); } public static void main(String args[]) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(new JTableTest().panel, "Test"); } }); } }

更多推荐