I have a JTable with JCombobox editor for a certain column.
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
public class TablePanel extends JPanel {
public TablePanel() {
JTable table = new JTable(new MyTableModel());
setComboboxColumn(table.getColumnModel().getColumn(1));
add(new JScrollPane(table));
}
public void setComboboxColumn(TableColumn cbColumn) {
JComboBox<String> comboBox = new JComboBox<>();
comboBox.addItem("Item 1");
comboBox.addItem("Item 2");
comboBox.addItem("Item 3");
cbColumn.setCellEditor(new DefaultCellEditor(comboBox));
}
private static class MyTableModel extends AbstractTableModel {
private String[] columnNames = {"Normal cell", "Combobox cell"};
private Object[][] data = {
{"Cell 1", "Item 2"},
{"Cell 2", "Item 1"},
{"Cell 3", "Item 1"},
{"Cell 4", "Item 3"},
};
#Override
public int getColumnCount() {
return columnNames.length;
}
#Override
public int getRowCount() {
return data.length;
}
#Override
public String getColumnName(int col) {
return columnNames[col];
}
#Override
public Object getValueAt(int row, int col) {
return data[row][col];
}
#Override
public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
#Override
public boolean isCellEditable(int row, int col) {
return true;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
data[rowIndex][columnIndex] = aValue;
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("TablePanel");
frame.getContentPane().add(new TablePanel());
frame.pack();
frame.setVisible(true);
}
});
}
}
What happens now:
When I click for the first time on a cell of that column the combobox popup shows up immediately.
If I click other cells of the same column, the combobox shows up but the popup remains closed.
If I click on other cells and then back again on a cell of that column, the combobox popup shows up again immediately.
What I would like:
First click on the cell of that column: the combobox shows up, but the popup list remains closed.
Second click again on the same cell: the popup list shows up.
I know that I can use cellEditor.setClickCountToStart(2) but in this case the second click must be performed in a short time after the first one, and I would like to avoid this limit.
From the BasicComboPopup.Handler#mousePressed(...):
public void mousePressed(MouseEvent e) {
if (e.getSource() == list) {
return;
}
if (!SwingUtilities.isLeftMouseButton(e) || !comboBox.isEnabled())
return;
//...
togglePopup();
}
You might be able to use a AncestorListener:
When first click on the cell of that column, combobox.isEnabled()==false, so do not display popup, and later, AncestorListener#ancestorAdded() call combobox.setEnabled(true).
Second click again on the same cell: combobox.isEnabled()==true, the popup shows up.
If click on other cells: AncestorListener#ancestorRemoved() call combobox.setEnabled(false).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
public class ComboBoxCellEditorTogglePopupTest {
private JComboBox<String> makeComboBox() {
JComboBox<String> combobox = new JComboBox<>();
combobox.addItem("Item 1");
combobox.addItem("Item 2");
combobox.addItem("Item 3");
return combobox;
}
public JComponent makeUI() {
String[] columnNames = {"Default", "setEnabled", "String"};
Object[][] data = {
{"Item 1", "Item 1", "aaa"}, {"Item 2", "Item 3", "bbb"}
};
JTable table = new JTable(new DefaultTableModel(data, columnNames));
table.setRowHeight(20);
table.getColumnModel().getColumn(0).setCellEditor(
new DefaultCellEditor(makeComboBox()));
final JComboBox<String> combobox = makeComboBox();
combobox.setEnabled(false);
combobox.addAncestorListener(new AncestorListener() {
#Override public void ancestorAdded(AncestorEvent e) {
System.out.println("ancestorAdded");
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
combobox.setEnabled(true);
}
});
}
#Override public void ancestorRemoved(AncestorEvent e) {
System.out.println("ancestorRemoved");
combobox.setEnabled(false);
}
#Override public void ancestorMoved(AncestorEvent e) {}
});
table.getColumnModel().getColumn(1).setCellEditor(
new DefaultCellEditor(combobox));
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new ComboBoxCellEditorTogglePopupTest().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
Related
import java.awt.*;
import java.awt.event.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.table.*;
public class TableButtonCell extends JFrame {
private JPanel topPanel;
private JTable table;
public TableButtonCell() {
setTitle("JButton in JTable");
setSize(300,150);
topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
getContentPane().add(topPanel);
String [] columns = new String[] {"Text", "Button"};
String[][] data = new String[][]{
{"Line 1", ""},
{"Line 2", ""},
{"Line 3", ""}};
DefaultTableModel model = new DefaultTableModel(data,columns);
table = new JTable();
table.setModel(model);
table.getColumn("Button").setCellRenderer(new ButtonRenderer());
table.getColumn("Button").setCellEditor(new ButtonEditor());
JScrollPane scrollPane = new JScrollPane(table);
topPanel.add(scrollPane,BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
class ButtonRenderer extends JButton implements TableCellRenderer {
public ButtonRenderer() {
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setText((value == null) ? "Modify" : value.toString());
return this;
}
}
class ButtonEditor extends JButton implements TableCellEditor {
public ButtonEditor() {
JPopupMenu popup = new JPopupMenu();
JMenuItem item = new JMenuItem("Menu action 1");
item.addActionListener(this::menuAction);
item = new JMenuItem("Menu action 2");
item.addActionListener(this::menuAction);
setComponentPopupMenu(popup);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(null,"JButton clicked");
}
});
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
return this;
}
public Object getCellEditorValue() {
return null;
}
public void menuAction(ActionEvent ev) {
JOptionPane.showMessageDialog(null,"JButton clicked");
}
#Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean stopCellEditing() {
return true;
}
#Override
public void cancelCellEditing() {
}
#Override
public void addCellEditorListener(CellEditorListener l) {
}
#Override
public void removeCellEditorListener(CellEditorListener l) {
}
}
public static void main(String args[]) {
TableButtonCell f = new TableButtonCell();
f.setVisible(true);
}
}
The SSCE above creates a JTable with JButton as cell renderer/editor.
It's working fine & button action is triggered correclty
When trying to add a popup menu to the JButton, the menu is not shown when clicking mouse right button.
Looks like the table is consuming the Mouse right click event, so the JButton didn't receive & react to the event ?
Any clue ?
Thanks in advance for any guidance/help
Now it's working with the following code. Hope this may help some one else.
import java.awt.*;
import java.awt.event.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.table.*;
public class TableButtonCell extends JFrame {
private JPanel topPanel;
private JTable table;
public TableButtonCell() {
setTitle("JButton in JTable");
setSize(300,150);
topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
getContentPane().add(topPanel);
String [] columns = new String[] {"Text", "Button"};
String[][] data = new String[][]{
{"Line 1", "Button 1"},
{"Line 2", "Button 2"},
{"Line 3", "Button 3"},
{"Line 4", "Button 4"}};
DefaultTableModel model = new DefaultTableModel(data,columns);
table = new JTable();
table.setModel(model);
ButtonRendererEditor renderer = new ButtonRendererEditor(table, 1);
TableColumn tc = table.getColumn("Button");
tc.setCellRenderer(renderer);
tc.setCellEditor(renderer);
JScrollPane scrollPane = new JScrollPane(table);
topPanel.add(scrollPane,BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
class ButtonRendererEditor extends JButton implements TableCellRenderer, TableCellEditor {
int column;
public ButtonRendererEditor(JTable table, int column) {
this.column = column;
JPopupMenu popup = new JPopupMenu();
JMenuItem item = new JMenuItem("Menu action 1");
item.addActionListener(this::menuAction);
popup.add(item);
item = new JMenuItem("Menu action 2");
item.addActionListener(this::menuAction);
popup.add(item);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(null,"JButton clicked");
}
});
table.addMouseListener( new MouseAdapter() {
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
if (!e.isPopupTrigger())
return;
JTable source = (JTable)e.getSource();
int col = source.columnAtPoint(e.getPoint());
if (col != column)
return;
popup.show(e.getComponent(), e.getX(), e.getY());
}
});
}
public void menuAction(ActionEvent ev) {
JOptionPane.showMessageDialog(null,"Menu item clicked");
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setText((value == null) ? "" : value.toString());
return this;
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
setText((value == null) ? "" : value.toString());
return this;
}
public Object getCellEditorValue() {
return null;
}
#Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
#Override
public boolean stopCellEditing() {
return true;
}
#Override
public void cancelCellEditing() {
}
#Override
public void addCellEditorListener(CellEditorListener l) {
}
#Override
public void removeCellEditorListener(CellEditorListener l) {
}
}
public static void main(String args[]) {
TableButtonCell f = new TableButtonCell();
f.setVisible(true);
}
}
I want to remove selected row of JTable by pressing only Delete button.
When I press Delete, selected cell becomes editable and my action(on jframe) does not receive KeyEvent.
Please, run this demo to see the effect:
public class TestTableKeyBinding extends JFrame {
// private static final int MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
private JTable table;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TestTableKeyBinding test = new TestTableKeyBinding();
test.setVisible(true);
}
});
}
TestTableKeyBinding() {
super();
initUI();
addKeyBindings();
}
private void initUI() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] headers = new String[] { "apples", "bananas" };
String[][] data = new String[][] { { "1", "2" }, { "4", "6" }, { "5", "7" }, { "1", "3" }, { "2", "11" } };
table = new JTable(data, headers);
table.setRowSelectionAllowed(true);
this.add(new JScrollPane(table));
this.pack();
this.setSize(new Dimension(300, 400));
}
private void addKeyBindings() {
// root maps
InputMap im = this.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
ActionMap am = this.getRootPane().getActionMap();
// add custom action
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "save");
am.put("save", saveAction());
}
private AbstractAction saveAction() {
AbstractAction save = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(TestTableKeyBinding.this.table, "Action Triggered.");
table.editingCanceled(null);
table.editingStopped(null);
int selectedRow = table.getSelectedRow();
if (selectedRow != -1) {
((DefaultTableModel) table.getModel()).removeRow(selectedRow);
}
}
};
return save;
}
}
Thanks for help!
I have tested your code and made some changes as mentioned below. Now it's working fine.
private void addKeyBindings() {
KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
table.getActionMap().put("save", saveAction());
table.getInputMap(JComponent.WHEN_FOCUSED).put(keyStroke, "save");
}
Make one more change as mentioned below
table = new JTable(new DefaultTableModel(data,headers));
otherwise it will result in ClassCastException at below line
((DefaultTableModel) table.getModel()).removeRow(selectedRow);
Here is complete code:
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.table.DefaultTableModel;
public class TestTableKeyBinding extends JFrame {
private JTable table;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TestTableKeyBinding test = new TestTableKeyBinding();
test.setVisible(true);
}
});
}
TestTableKeyBinding() {
super();
initUI();
addKeyBindings();
}
private void initUI() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] headers = new String[] { "apples", "bananas" };
String[][] data = new String[][] { { "1", "2" }, { "4", "6" }, { "5", "7" }, { "1", "3" },
{ "2", "11" } };
table = new JTable(new DefaultTableModel(data,headers));
table.setRowSelectionAllowed(true);
this.add(new JScrollPane(table));
this.pack();
this.setSize(new Dimension(300, 400));
}
private void addKeyBindings() {
KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
table.getActionMap().put("save", saveAction());
table.getInputMap(JComponent.WHEN_FOCUSED).put(keyStroke, "save");
}
private AbstractAction saveAction() {
AbstractAction save = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(TestTableKeyBinding.this.table, "Action Triggered.");
table.editingCanceled(null);
table.editingStopped(null);
int selectedRow = table.getSelectedRow();
if (selectedRow != -1) {
((DefaultTableModel) table.getModel()).removeRow(selectedRow);
}
}
};
return save;
}
}
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.
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");
}
});
}
}
I accomplished this by enabling the editing and then making the component responsible for the edition ignore any changes. For this I created a TableCellEditor and intercepted the key types to the JTextField, the component used for editing.
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;
}
}
}
I tried both the answers here... but one problem at least is that you can tell when you've entered the "editing" mode.
This might be of interest... uses a combination of Editor magic and cheeky rendering to make it look like no editing is going on: editor's click-count-to-start is set to 1, and the component (JTextPane) delivered by the editor's method does setEditable( false ).
If this tickles your fancy, you might be interested at looking at my implementation of a JTable which adjusts (perfectly, harnessing the JTextPane's powerful wrapping power) the row height to the text, for individual rows, including when you change the columns: How to wrap lines in a jtable cell?
public class SelectableNonEditableTableTest {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame main_frame = new JFrame();
main_frame.setPreferredSize(new Dimension(1200, 300));
main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ArrayList<String> nonsense = new ArrayList<String>(
Arrays.asList(
"Lorem ipsum dolor sit amet, sed dolore vivendum ut",
"pri an soleat causae doctus.",
"Alienum abhorreant mea ea",
"cum malorum diceret ei. Pri oratio invidunt consequat ne.",
"Ius tritani detraxit scribentur et",
"has detraxit legendos intellegat at",
"quo oporteat constituam ex"));
JTable example_table = new JTable(10, 4);
example_table.setRowHeight( example_table.getRowHeight() * 2 );
DefaultCellEditor cell_editor = new SelectableNonEditableCellEditor(
new JTextField());
cell_editor.setClickCountToStart(1);
example_table.setDefaultEditor(Object.class, cell_editor);
TableCellRenderer renderer = new SelectableNonEditableTableRenderer();
example_table.setDefaultRenderer(Object.class, renderer);
for (int i = 0; i < 10; i++) {
example_table.setValueAt(nonsense.get(i % nonsense.size()),
i, i % 4);
}
main_frame.getContentPane().add(new JScrollPane(example_table));
main_frame.pack();
main_frame.setVisible(true);
}
});
}
}
class SelectableNonEditableCellEditor extends DefaultCellEditor {
public SelectableNonEditableCellEditor(JTextField textField) {
super(textField);
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int col) {
Component comp = super.getTableCellEditorComponent(table, value,
isSelected, row, col);
if (value instanceof java.lang.String) {
DefaultStyledDocument sty_doc = new DefaultStyledDocument();
try {
sty_doc.insertString(0, (String) value, null);
} catch (BadLocationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JTextPane jtp_comp = new JTextPane(sty_doc);
jtp_comp.setEditable(false);
return jtp_comp;
}
return comp;
}
}
class SelectableNonEditableTableRenderer extends JTextPane implements
TableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value instanceof DefaultStyledDocument) {
setDocument((DefaultStyledDocument) value);
} else {
setText((String) value);
}
return this;
}
}
Maybe you can implement your own TableCellRenderer that extends JTextField in your table.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Accessing a JTextField in JTableHeader
How to make JTableHeader as editable. F.e. i make ColumnHeader as JTextField. What must i do to make JTextField editable. See the example:
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.event.*;
public class Test extends JFrame {
String[][] cellValues = { { "v00", "v01", "v02" }, { "v10", "v11", "v12" },
{ "v20", "v21", "v22" }, { "v30", "v31", "v32" },
{ "v40", "v41", "v42" }, { "v50", "v51", "v52" } };
String[] columnNames = { "v00", "v01", "v02" };
javax.swing.JTable jTable1 = new javax.swing.JTable(cellValues, columnNames);
public Test() {
try {
jbInit();
} catch (Exception e) {
e.printStackTrace();
}
}
private void jbInit() throws Exception {
this.getContentPane().add(new JScrollPane(jTable1), null);
for (int i = 0; i < 3; i++)
jTable1.getColumnModel().getColumn(i)
.setHeaderRenderer(new Renderer());
}
public static void main(String[] args) {
Test frame = new Test();
frame.addWindowListener(new java.awt.event.WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
frame.pack();
frame.setVisible(true);
}
}
class Renderer extends JPanel implements TableCellRenderer {
JLabel label = new JLabel(" ");
JTextField field = new JTextField("%");
public Renderer() {
super(new BorderLayout());
add(label, BorderLayout.NORTH);
add(field, BorderLayout.CENTER);
setBorder(BorderFactory.createEtchedBorder());
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
label.setText(value.toString());
return (JComponent) this;
}
public String toString() {
return label.toString();
}
public void setText(String text) {
label.setText(text);
}
}
Here's a simple approach for making editable headers (no custom renderers or UIs required):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class JTableEditableHeaderDemo implements Runnable
{
private JTable table;
private JTableHeader header;
private JPopupMenu renamePopup;
private JTextField text;
private TableColumn column;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new JTableEditableHeaderDemo());
}
public JTableEditableHeaderDemo()
{
table = new JTable(10, 5);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
header = table.getTableHeader();
header.addMouseListener(new MouseAdapter(){
#Override
public void mouseClicked(MouseEvent event)
{
if (event.getClickCount() == 2)
{
editColumnAt(event.getPoint());
}
}
});
text = new JTextField();
text.setBorder(null);
text.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
renameColumn();
}
});
renamePopup = new JPopupMenu();
renamePopup.setBorder(new MatteBorder(0, 1, 1, 1, Color.DARK_GRAY));
renamePopup.add(text);
}
public void run()
{
JFrame f = new JFrame("Double-click header to edit");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new JScrollPane(table));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private void editColumnAt(Point p)
{
int columnIndex = header.columnAtPoint(p);
if (columnIndex != -1)
{
column = header.getColumnModel().getColumn(columnIndex);
Rectangle columnRectangle = header.getHeaderRect(columnIndex);
text.setText(column.getHeaderValue().toString());
renamePopup.setPreferredSize(
new Dimension(columnRectangle.width, columnRectangle.height - 1));
renamePopup.show(header, columnRectangle.x, 0);
text.requestFocusInWindow();
text.selectAll();
}
}
private void renameColumn()
{
column.setHeaderValue(text.getText());
renamePopup.setVisible(false);
header.repaint();
}
}
There is a complete solution under the following link, looks quite good at the first sight!
How do I create a JTable with editable headers?
I have JTable and it has a JCheckBox and a JComoboBox in two different columns. When I select a JCheckBox that corresponds to that row, the JComboBox should be disable. Kindly help me.
Simply disable editing of the cell based on your model. In your TableModel, override/implement the isCellEditable() method to return the "value" of the checkbox.
Although the following example is not based on JComboBox, it illustrates how to disable edition of a cell based on the value of a checkbox at the beginning of the row:
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class TestTable {
public JFrame f;
private JTable table;
public class TestTableModel extends DefaultTableModel {
public TestTableModel() {
super(new String[] { "Editable", "DATA" }, 3);
for (int i = 0; i < 3; i++) {
setValueAt(Boolean.TRUE, i, 0);
setValueAt(Double.valueOf(i), i, 1);
}
}
#Override
public boolean isCellEditable(int row, int column) {
if (column == 1) {
return (Boolean) getValueAt(row, 0);
}
return super.isCellEditable(row, column);
}
#Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 0) {
return Boolean.class;
} else if (columnIndex == 1) {
return Double.class;
}
return super.getColumnClass(columnIndex);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new TestTable().initUI();
}
});
}
protected void initUI() {
table = new JTable(new TestTableModel());
f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300, 300);
f.setLocationRelativeTo(null);
f.add(new JScrollPane(table));
f.setVisible(true);
}
}