Jtable How Prepareeditor Works

JTable how prepareEditor works

I think the prepareRenderer(...) code should be:

        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);

if ((column == 2 || column == 3) && (Boolean)getValueAt(row, 0)) {
return c;
}

// if (column == 0 || column == 1 || (Boolean) getValueAt(row, 0)) {
if (column == 0 || column == 1) {
return c;
}

return Box.createRigidArea(c.getPreferredSize());
}

Then you should get rid of the prepareEditor(...) code. Instead you should have more logic in the isCellEditable(...) method. Something like:

        public boolean isCellEditable(int row, int column) {

if (column == 0) return true;

if (column == 1 || column == 4 || column == 5) return false;

return (Boolean)getValueAt(row, 0);
}

jFileChooser as cell editor in a table

The tutorial approach is correct. See this example that use an undecorated JButton to evoke the actual editor. Instead of PopupDialog, you'll use JFileChooser.

Addendum: To apply the editor to any cell(s) individually, override prepareEditor() for the desired row and column, as discussed here.

Set Condition for JTable, Java

You should handle this within your domain (e.g. add a constraint wherever you maintain your data loaded into the tableModel) and limit the amount of senior managers there. This is business logic, don't implement it in your GUI.

Select all data when start editing JTable Cell

You can create a custom TableCellEditor for your table. This class will have an instance variable of a TextField, lets call it textField. Then the getTableCellEditorComponent method could look like this:

public Component getTableCellEditorComponent(JTable table, Object value, 
boolean isSelected, int row, int column ) {
textField.setText(value.toString());
textField.selectAll();
return textField;
}

JTable - multi-type column

You should implement your custom TableCellRenderer and TableCellEditor.

Then retrieve the TableColumn you need to customize and set your class where you implemented those interfaces.

TableColumn column = table.getColumnModel().getColumn(vColIndex);
column.setCellRenderer(new YourCustomCellRenderer());
column.setCellEditor(new YourCustomCellEditor());

JTable valuechanged then change cell color

Tables use a TableCellRenderer to paint values on the screen. The editors and renderers don't actually have anything to do with each other (from a painting point of view).

So once the editor has been dismissed (accepted or cancelled), the cell is repainted using the assigned TableCellRenderer

You need to supply, in your table model, some way to determine which rows have been updated and change the state of the renderer to match.

FYI- The DefaultTableCellRenderer uses a JLabel as it's base renderer, so it is transparent by default; you will need to make it opaque to make it render properly.

Check out Using custom renderers for more details

Update with example

This is nothing more then a proof of concept. It will not meet your absolute requirements and you should take a serious look at the tutorial linked above.

Example image

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;

public class TableEdit {

public static void main(String[] args) {
new TableEdit();
}

public TableEdit() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}

JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}

public class TestPane extends JPanel {

public TestPane() {
setLayout(new BorderLayout());
JTable table = new JTable(new MyTableModel());
table.setSurrendersFocusOnKeystroke(true);
TableColumnModel model = table.getColumnModel();
model.getColumn(1).setCellRenderer(new MyTableCellRenderer());
add(new JScrollPane(table));
}

@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}

public class MyData {

private String key;
private String value;
private boolean changed;

public MyData(String key, String value) {
this.key = key;
this.value = value;
this.changed = false;
}

public String getKey() {
return key;
}

public String getValue() {
return value;
}

public void setValue(String newValue) {
if (value == null ? newValue != null : !value.equals(newValue)) {
value = newValue;
changed = true;
}
}

public boolean hasChanged() {
return changed;
}
}

public class MyTableModel extends AbstractTableModel {

private List<MyData> data;

public MyTableModel() {
data = new ArrayList<>(25);
for (int index = 0; index < 5; index++) {
data.add(new MyData("A" + (index + 1), "B" + (index + 1)));
}
}

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

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

@Override
public Object getValueAt(int rowIndex, int columnIndex) {
MyData myData = data.get(rowIndex);
Object value = null;
switch (columnIndex) {
case 0:
value = myData.getKey();
break;
case 1:
value = myData.getValue();
break;
}
return value;
}

@Override
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}

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

public boolean hasChanged(int rowIndex) {
MyData myData = data.get(rowIndex);
return myData.hasChanged();
}

@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
MyData myData = data.get(rowIndex);
myData.setValue(aValue == null ? null : aValue.toString());
}
}

public class MyTableCellRenderer extends DefaultTableCellRenderer {

@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setOpaque(isSelected);
TableModel model = table.getModel();
if (model instanceof MyTableModel) {
MyTableModel myModel = (MyTableModel) model;
if (myModel.hasChanged(row)) {
if (!isSelected) {
setBackground(Color.RED);
setOpaque(true);
}
}
}
return this;
}
}
}

Trouble detecting mouse click in JTable

@camickr - thank you for the answer. I overrode the prepareEditor method as suggested which updates the ListModel in the combo box as required.

    JTable typeTable = new JTable() {
@Override
public Component prepareEditor(TableCellEditor editor, int row, int column) {

if (column == SUBTYPE_COLUMN) {
// User has entered a subtype cell
// Get value of the adjacent type cell
updateCBOSubtypeDataModel(myTableModel.getValueAt(row, TYPE_COLUMN);
}
return super.prepareEditor(editor, row, column);
}
};

and

private void updateCBOSubtypeDataModel(TypeObject newType) {
myComboBoxListModel.removeAllElements();
myComboBoxListModel.addAll(getListOfSubtypesForThisType(newType));
}

Working nicely. Thanks.

How to change background color of an edited cell in JTable?

First, get the table's default selection background color:

Color color = UIManager.getColor("Table.selectionBackground");

Second, override prepareEditor(), as shown in this example, and set the background color of the editor component to match:

@Override
public Component prepareEditor(TableCellEditor editor, int row, int col) {
Component c = super.prepareEditor(editor, row, col);
c.setBackground(color);
return c;
}

Addendum: While technically correct, note that the editor component's color is typically managed by the corresponding UI delegate while active. An unfortunate choice may result in poor contrast and impaired usability. Thorough testing on target Look & Feels is warranted.

strange behavior of customized JPanel inside a JTable

Somehow I managed to solve it. Thank you @Oliver Watkins for your kind help.

As summary to my fix, I added
rendererJPanel = (CustomJPanel) value; for both getTableCellRendererComponent() and getTableCellEditorComponent()

Comple code :

CustomJTableTest.java

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;

public class CustomJTableTest extends JPanel
{

TableModel customRendererEditorTableModel = new TableModel();
JTable table;

public CustomJTableTest()
{
setLayout(new BorderLayout());

table = new JTable(customRendererEditorTableModel);
table.setPreferredScrollableViewportSize(new Dimension(500, 600));
table.setRowSelectionAllowed(false);
table.setRowHeight(300);
table.getColumn("Custom JPanel").setCellRenderer(new CustomJPanelRenderer());
table.getColumn("Custom JPanel").setCellEditor(new CustomJPanelEditor());

JScrollPane scrollPane = new JScrollPane(table);
add(scrollPane);

JButton showControl = new JButton("Show Controls");
showControl.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
// row 2
TableCellEditor tableCellEditor = table.getColumnModel().getColumn(1).getCellEditor();
java.awt.Component component = table.prepareEditor(tableCellEditor, 1, 1);
if (component instanceof CustomJPanel)
{
CustomJPanel customJPanel = (CustomJPanel) component;
customJPanel.setControlsVisible(true);
}

// row 1
java.awt.Component component2 = table.prepareEditor(tableCellEditor, 0, 1);
if (component2 instanceof CustomJPanel)
{
CustomJPanel customJPanel = (CustomJPanel) component2;
customJPanel.setControlsVisible(true);
}

customRendererEditorTableModel.fireTableDataChanged();
}
});
add(new JScrollPane(showControl), BorderLayout.SOUTH);
}

private static void createAndShowGUI()
{
JFrame frame = new JFrame("Custom JPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JComponent newContentPane = new CustomJTableTest();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}

CustomJPanel.java

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.*;

public class CustomJPanel extends JPanel
{

JPanel colorPanel = new JPanel(new BorderLayout());
JButton jButton = new JButton("Change Color");
JSlider jSlider = new JSlider(JSlider.VERTICAL);

public CustomJPanel()
{
jButton.setOpaque(true);
jButton.addActionListener(new ActionListener()
{

@Override
public void actionPerformed(ActionEvent e)
{
Random randomGenerator = new Random();
int randomInt = randomGenerator.nextInt(4);

switch (randomInt)
{
case (0):
colorPanel.setBackground(Color.BLUE);
break;
case (1):
colorPanel.setBackground(Color.BLACK);
break;
case (2):
colorPanel.setBackground(Color.CYAN);
break;
default:
colorPanel.setBackground(Color.GREEN);
break;
}
}
});
jSlider.setOpaque(true);
setLayout(new BorderLayout());
add(colorPanel, BorderLayout.CENTER);
add(jButton, BorderLayout.SOUTH);
add(jSlider, BorderLayout.EAST);

jSlider.setVisible(false);
jButton.setVisible(false);
}

public void setControlsVisible(boolean visible)
{
jSlider.setVisible(visible);
jButton.setVisible(visible);
}
}

CustomerJPanelRenderer

import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;

public class CustomJPanelRenderer implements TableCellRenderer
{

CustomJPanel rendererJPanel;

public CustomJPanelRenderer()
{
rendererJPanel = new CustomJPanel();
}

@Override
public java.awt.Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
rendererJPanel = (CustomJPanel) value;
return rendererJPanel;
}
}

CustomJPanelEditor.java

import javax.swing.AbstractCellEditor;
import javax.swing.JTable;
import javax.swing.table.TableCellEditor;

public class CustomJPanelEditor extends AbstractCellEditor implements TableCellEditor
{
CustomJPanel customJPanel;

public CustomJPanelEditor()
{
customJPanel = new CustomJPanel();
}

@Override
public java.awt.Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
customJPanel = (CustomJPanel) value;
return customJPanel;
}

@Override
public Object getCellEditorValue()
{
return customJPanel;
}
}

TableModel.java

import javax.swing.table.AbstractTableModel;

public class TableModel extends AbstractTableModel
{

private String[] columnNames =
{
"First Column",
"Custom JPanel",
};
private Object[][] data =
{
{"Foo", new CustomJPanel()},
{"Bar", new CustomJPanel()}
};

public int getColumnCount()
{
return columnNames.length;
}

public int getRowCount()
{
return data.length;
}

public String getColumnName(int col)
{
return columnNames[col];
}

public Object getValueAt(int row, int col)
{
return data[row][col];
}

public Class getColumnClass(int c)
{
return getValueAt(0, c).getClass();
}

public boolean isCellEditable(int row, int col)
{
return col >= 1;
}

public void setValueAt(Object value, int row, int col)
{
data[row][col] = value;
fireTableCellUpdated(row, col);
}

}


Related Topics



Leave a reply



Submit