想象一下,我正在使用Java构建一个IRC客户端,我想在聊天视图中使用富文本来显示IRC颜色和彩色刻痕。我想用JTable来构建它。我可以这样做,但文字是不可选择的。使表格可编辑没有意义。
我也曾调查过:
所以我有一张桌子工作,我只需要在不使其可编辑的情况下选择文本。我也只想要文本内容,并且在复制文本选择时没有HTML被复制到剪贴板中。
我尝试了setRowSelectionAllowed()
,setColumnSelectionEnabled()
和setCellSelectionEnabled()
以及setSelectionMode
的各种迭代,表模型为isCellEditable()
返回false。什么都没有使文本可选。
编辑:根据答案1我对文本编辑器窗格的看法不对,所以我正在尝试这些解决方案。
答案 0 :(得分:2)
我不知道你为什么不想使用JTextPane
或JEditorPane
。您按文档插入文本。这里的例子 - > How to use Editor Panes and Text Panes
但为了您的目的,您可以做一些类似的事情。我重写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");
}
});
}
}
答案 1 :(得分:1)
我通过启用编辑然后使负责编辑的组件忽略任何更改来完成此操作。为此我创建了一个TableCellEditor并截获了JTextField的键类型,这是用于编辑的组件。
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
public class TableCellSelectionTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run()
{
new TableCellSelectionTest().initUI();
}
});
}
public void initUI()
{
JFrame frame = new JFrame();
int N = 5;
int M = 3;
Object[][] data = new Object[N][M];
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
data[i][j] = "This is the cell (" + i + ", " + j +")";
}
}
String[] columnNames = { "Column 1", "Column 2", "Column 3" };
DefaultTableModel model = new DefaultTableModel(data, columnNames);
final MyTableCellEditor editor = new MyTableCellEditor();
JTable table = new JTable(model) {
@Override
public TableCellEditor getCellEditor(int row, int column)
{
return editor;
}
};
frame.add(new JScrollPane(table), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
class MyTableCellEditor extends AbstractCellEditor implements
TableCellEditor
{
Object _value;
@Override
public Object getCellEditorValue()
{
return _value;
}
@Override
public Component getTableCellEditorComponent(JTable table,
Object value, boolean isSelected, int row, int column)
{
_value = value;
JTextField textField = new JTextField(_value.toString());
textField.addKeyListener(new KeyAdapter()
{
public void keyTyped(KeyEvent e) {
e.consume(); //ignores the key
}
@Override
public void keyPressed(KeyEvent e)
{
e.consume();
}});
textField.setEditable(false); //this is functionally irrelevent, makes slight visual changes
return textField;
}
}
}
答案 2 :(得分:1)
我在这里尝试了两个答案......但至少有一个问题是你可以告诉你何时进入“编辑”模式。
这可能是有意义的......使用编辑魔术和厚脸皮渲染的组合使其看起来没有进行编辑:编辑器的点击计数到开始设置为1,{{1}由编辑器方法提供的ybg
component
。
如果这引起你的兴趣,你可能会对我JTextPane
的实现感兴趣,setEditable( false )
可以调整(完全利用JTable
强大的包装能力)行高到文本,对于单个行,包括更改列时:How to wrap lines in a jtable cell?
JTextPane
答案 3 :(得分:0)
也许你可以实现自己的TableCellRenderer来扩展表中的JTextField。