I have a JTable with 3 columns, the first column is a simple text, the other 2 columns are JComboBox. Column Name and Column Email both have a custom TableCellEditor and TableCellRenderer.
Sometimes when I click on a comboBox in a row that is not selected, the cell would not be drawn with the proper selected color (blue).
For illustration purposes, the TableCellRenderer draws pink cells, and TableCellEditor draws orange cells.
JTable returns false for isCellSelected(), more specifically returns false for isRowSelected(), at JTable editCellAt(). However when the renderer calls isCellSelected(), it returns true, so renderer is properly colored.
I can't figure out what's going wrong here.
My SSCCE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractCellEditor;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumnModel;
import org.iii.snsi.streamcenter.main.Main;
public class EditorNotSelectedColorFrame {
public JComponent makeUI() {
JTable table = new JTable();
DefaultTableModel model = new DefaultTableModel(new String[]{"COL 1", "COL 2", "COL 3"}, 0);
table.setModel(model);
for (int i = 0; i < 5; i++) {
Object[] row = new Object[3];
row[0] = new MyListItem(new String[]{"item a", "item b", "item c"});
row[1] = new MyListItem(new String[]{"item d", "item e", "item f"});
row[2] = new MyListItem(new String[]{"item g", "item h", "item i"});
model.addRow(row);
}
MyTableCellEditor editor = new MyTableCellEditor(Color.orange, Color.BLACK);
MyTableCellRenderer renderer = new MyTableCellRenderer(Color.pink, Color.BLACK);
TableColumnModel columnModel = table.getColumnModel();
columnModel.getColumn(0).setCellEditor(editor);
columnModel.getColumn(1).setCellEditor(editor);
columnModel.getColumn(2).setCellEditor(editor);
columnModel.getColumn(0).setCellRenderer(renderer);
columnModel.getColumn(1).setCellRenderer(renderer);
columnModel.getColumn(2).setCellRenderer(renderer);
JPanel panel = new JPanel(new BorderLayout());
panel.add(new JScrollPane(table));
return panel;
}
public static void main(String... args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new EditorNotSelectedColorFrame().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
class MyListItem<T> {
private ArrayList<T> items = new ArrayList<>();
private Integer selectedIndex = -1;
public MyListItem(T[] items) {
selectedIndex = -1;
this.items.addAll(Arrays.asList(items));
}
public ArrayList<T> getItems() {
return items;
}
public void setSelectedIndex(Integer selectedIndex) {
this.selectedIndex = selectedIndex;
}
public Integer getSelectedIndex() {
return selectedIndex;
}
}
class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private Color unselectedBackground;
private Color unselectedForeground;
private JMyComboBox comboBox;
private MyListItem myListItem;
public MyTableCellEditor(Color bg, Color fg) {
unselectedBackground = bg;
unselectedForeground = fg;
comboBox = new JMyComboBox(bg, fg);
comboBox.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
stopCellEditing();
}
});
}
#Override
public Object getCellEditorValue() {
int idx = comboBox.getSelectedIndex();
if (idx > -1) {
myListItem.setSelectedIndex(comboBox.getSelectedIndex());
}
return myListItem;
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
comboBox.removeAllItems();
if (value instanceof MyListItem) {
myListItem = (MyListItem) value;
for (Object item : myListItem.getItems()) {
comboBox.addItem(item.toString());
}
comboBox.setSelectedIndex(myListItem.getSelectedIndex());
} else {
myListItem = null;
}
if (isSelected) {
comboBox.setForeground(table.getSelectionForeground());
comboBox.setBackground(table.getSelectionBackground());
} else {
comboBox.setForeground(unselectedForeground);
comboBox.setBackground(unselectedBackground);
}
return comboBox;
}
}
class MyTableCellRenderer extends DefaultTableCellRenderer {
private Color unselectedBackground;
private Color unselectedForeground;
private JMyComboBox comboBox;
public MyTableCellRenderer(Color bg, Color fg) {
super();
unselectedBackground = bg;
unselectedForeground = fg;
comboBox = new JMyComboBox(bg, fg);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
comboBox.removeAllItems();
if (value instanceof MyListItem) {
MyListItem cellItem = (MyListItem) value;
for (Object item : cellItem.getItems()) {
comboBox.addItem(item.toString());
}
comboBox.setSelectedIndex(cellItem.getSelectedIndex());
}
if (isSelected) {
comboBox.setForeground(table.getSelectionForeground());
comboBox.setBackground(table.getSelectionBackground());
} else {
comboBox.setForeground(unselectedForeground);
comboBox.setBackground(unselectedBackground);
}
return comboBox;
}
}
class JMyComboBox extends JComboBox<String> {
private MyComboBoxEditor editor = new MyComboBoxEditor();
private MyComboBoxRenderer renderer = new MyComboBoxRenderer();
public JMyComboBox(Color bg, Color fg) {
super();
setEditable(true);
setEditor(editor);
setRenderer(renderer);
editor.setColors(bg, fg);
renderer.setColors(bg, fg);
}
#Override
public void setBackground(Color bg) {
super.setBackground(bg);
if (editor != null) {
editor.setColors(bg, getForeground());
}
}
#Override
public void setForeground(Color fg) {
super.setForeground(fg);
if (editor != null) {
editor.setColors(getBackground(), fg);
}
}
}
class MyComboBoxEditor extends BasicComboBoxEditor {
private JLabel label = new JLabel();
public MyComboBoxEditor() {
super();
label.setOpaque(true);
}
public void setColors(Color background, Color foreground) {
label.setBackground(background);
label.setForeground(foreground);
}
#Override
public void setItem(Object anObject) {
super.setItem(anObject);
label.setText(((JTextField) super.getEditorComponent()).getText());
}
#Override
public Component getEditorComponent() {
return label;
}
}
class MyComboBoxRenderer extends DefaultListCellRenderer {
private Color unselectedBackground;
private Color unselectedForeground;
public void setColors(Color background, Color foreground) {
this.unselectedBackground = background;
this.unselectedForeground = foreground;
}
#Override
public Component getListCellRendererComponent(JList<?> list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (!isSelected) {
if (unselectedBackground != null) {
setBackground(unselectedBackground);
}
if (unselectedForeground != null) {
setForeground(unselectedForeground);
}
}
return this;
}
}
Related
My image uploading function is totally working. But I cannot upload image row by row. At this moment when I upload a image it will added into whole 5th column. How to put my buttons into an array and upload image in a row by row?
**Note: Button working as a file uploader.
Here is the image
enter image description here
Here is the code :
NewFrame.java
package test4;
import java.awt.Color;
import java.awt.Component;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.ListCellRenderer;
import javax.swing.UIManager;
import javax.swing.filechooser.FileSystemView;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
public class NewJFrame extends javax.swing.JFrame {
static String fileoriginal="C:/Users/Praneeth Thisal/Documents/NetBeansProjects/Copyfile/src/copyfile/";
public NewJFrame() {
initComponents();
tablemodel();
}
void tablemodel(){
Color choices[] = { Color.red, Color.yellow, Color.green, Color.white, Color.orange };
ComboTableCellRenderer renderer = new ComboTableCellRenderer();
JComboBox comboBox = new JComboBox(choices);
comboBox.setRenderer(renderer);
TableCellEditor editor = new DefaultCellEditor(comboBox);
TableModel model = new ColorTableModel();
jTable1.setModel(model);
TableColumn column = jTable1.getColumnModel().getColumn(5);
column.setCellRenderer(renderer);
column.setCellEditor(editor);
TableColumn column1 = jTable1.getColumnModel().getColumn(3);
column1.setCellRenderer(new ButtonRenderer());
TableColumn column2 = jTable1.getColumnModel().getColumn(4);
column2.setCellRenderer(new ImageRenderer());
column1.setCellEditor(
new ButtonEditor(new JCheckBox()));
jTable1.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
jTable1.getColumnModel().getColumn(0).setPreferredWidth(27);
jTable1.getColumnModel().getColumn(1).setPreferredWidth(120);
jTable1.getColumnModel().getColumn(2).setPreferredWidth(100);
jTable1.getColumnModel().getColumn(3).setPreferredWidth(90);
jTable1.getColumnModel().getColumn(4).setPreferredWidth(90);
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null, null, null, null, null},
{null, null, null, null, null, null},
{null, null, null, null, null, null},
{null, null, null, null, null, null}
},
new String [] {
"Title 1", "Title 2", "Title 3", "Title 4", "Title 5", "Title 6"
}
));
jScrollPane1.setViewportView(jTable1);
getContentPane().add(jScrollPane1, new org.netbeans.lib.awtextra.AbsoluteConstraints(25, 160, 730, 275));
java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setBounds((screenSize.width-795)/2, (screenSize.height-651)/2, 795, 651);
}// </editor-fold>
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewJFrame().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable jTable1;
// End of variables declaration
}
class ImageRenderer extends DefaultTableCellRenderer {
JLabel lbl = new JLabel();
ImageIcon icon = new ImageIcon(new ImageIcon(NewJFrame.fileoriginal+"test.jpg").getImage().getScaledInstance(40, 40, Image.SCALE_DEFAULT));
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
lbl.setText((String) value);
lbl.setIcon(icon);
return lbl;
}
}
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) {
value="Upload";
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(UIManager.getColor("Button.background"));
// setText("dsda1");
}
setText((value == null) ? "" : value.toString());
return this;
}
}
/**
* #version 1.0 11/09/98
*/
class ButtonEditor extends DefaultCellEditor {
protected JButton button;
private String label;
private boolean isPushed;
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (isSelected) {
button.setForeground(table.getSelectionForeground());
button.setBackground(table.getSelectionBackground());
} else {
button.setForeground(table.getForeground());
button.setBackground(table.getBackground());
}
label = (value == null) ? "" : value.toString();
//label="DDD";
button.setText("Upload");
isPushed = true;
return button;
}
public Object getCellEditorValue() {
if (isPushed) {
//
JFileChooser jfc = new JFileChooser(FileSystemView.getFileSystemView().getHomeDirectory());
int returnValue = jfc.showOpenDialog(null);
// int returnValue = jfc.showSaveDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = jfc.getSelectedFile();
System.out.println(selectedFile.getAbsolutePath());
File source = new File(selectedFile.getAbsolutePath());
try{
NewJFrame.fileoriginal="C:/Users/Praneeth Thisal/Documents/NetBeansProjects/Copyfile/src/copyfile/";
copyFileUsingStream(source, new File(NewJFrame.fileoriginal+"test"+".jpg"));
System.out.println("Done");
NewJFrame nf = new NewJFrame();
nf.setVisible(true);
}
catch(IOException e){
e.printStackTrace();
}
}
// JOptionPane.showMessageDialog(button, label + ": Ouch!");
System.out.println(label + "Uploaded Successfully!!");
}
isPushed = false;
return new String(label);
}
private static void copyFileUsingStream(File source, File dest) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
is.close();
os.close();
}
}
public boolean stopCellEditing() {
isPushed = false;
return super.stopCellEditing();
}
protected void fireEditingStopped() {
super.fireEditingStopped();
}
}
ComboTableCellRenderer.java
package test4;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultListCellRenderer;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListCellRenderer;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
class ComboTableCellRenderer implements ListCellRenderer, TableCellRenderer {
DefaultListCellRenderer listRenderer = new DefaultListCellRenderer();
DefaultTableCellRenderer tableRenderer = new DefaultTableCellRenderer();
private void configureRenderer(JLabel renderer, Object value) {
if ((value != null) && (value instanceof Color)) {
if (value.equals(Color.red)) {
renderer.setText("0");
} else if(value.equals(Color.orange)) {
renderer.setText("10");
}
else if(value.equals(Color.yellow)) {
renderer.setText("20");
}
else if(value.equals(Color.green)) {
renderer.setText("30");
}
else if(value.equals(Color.white)) {
renderer.setText("N/A");
}
renderer.setBackground((Color)value);
} else {
renderer.setText((String) value);
}
}
public Component getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
listRenderer = (DefaultListCellRenderer) listRenderer.getListCellRendererComponent(list, value,
index, isSelected, cellHasFocus);
configureRenderer(listRenderer, value);
return listRenderer;
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
tableRenderer = (DefaultTableCellRenderer) tableRenderer.getTableCellRendererComponent(table,
value, isSelected, hasFocus, row, column);
configureRenderer(tableRenderer, value);
return tableRenderer;
}
}
class ColorTableModel extends AbstractTableModel {
Object rowData[][] = {
{ "1","","","","", Color.red, "30" },
{ "2","","","","", Color.red, "30" },
{ "3","","","","", Color.red, "30" },
{ "4","","","","", Color.red, "30" },
{ "5","","","","", Color.red, "30" }, };
String columnNames[] = { "Index","Item","Reason","Image","Image 1","Marks","Allocated Marks" };
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int column) {
return columnNames[column];
}
public int getRowCount() {
return rowData.length;
}
public Object getValueAt(int row, int column) {
return rowData[row][column];
}
public Class getColumnClass(int column) {
return (getValueAt(0, column).getClass());
}
public void setValueAt(Object value, int row, int column) {
rowData[row][column] = value;
}
public boolean isCellEditable(int row, int column) {
return (column != 0);
}
}
I have the following Code that Buttons are within cells
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
/**
* #version 1.0 11/09/98
*/
public class JButtonTableExample extends JFrame {
public JButtonTableExample() {
super("JButtonTable Example");
DefaultTableModel dm = new DefaultTableModel();
dm.setDataVector(new Object[][] { { "button 1", "foo" },
{ "button 2", "bar" } }, new Object[] { "Button", "String" });
JTable table = new JTable(dm);
table.setFont(new Font("Comic Sans MA",0,20));
table.setRowHeight(35);
table.getColumn("Button").setCellRenderer(new ButtonRenderer());
table.getColumn("Button").setCellEditor(
new ButtonEditor(new JCheckBox()));
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll);
setSize(400, 100);
setVisible(true);
}
public static void main(String[] args) {
JButtonTableExample frame = new JButtonTableExample();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
/**
* #version 1.0 11/09/98
*/
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) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(UIManager.getColor("Button.background"));
}
setText((value == null) ? "" : value.toString());
return this;
}
}
/**
* #version 1.0 11/09/98
*/
class ButtonEditor extends DefaultCellEditor {
protected JButton button;
private String label;
private boolean isPushed;
public ButtonEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton();
button.setFont(new Font("Comic Sans MS",0,25));
buttonButtonEditor
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
}
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
if (isSelected) {
button.setForeground(table.getSelectionForeground());
button.setBackground(table.getSelectionBackground());
} else {
button.setForeground(table.getForeground());
button.setBackground(table.getBackground());
}
label = (value == null) ? "" : value.toString();
button.setText(label);
isPushed = true;
return button;
}
public Object getCellEditorValue() {
if (isPushed) {
//
//
JOptionPane.showMessageDialog(button, label + ": Ouch!");
// System.out.println(label + ": Ouch!");
}
isPushed = false;
return new String(label);
}
public boolean stopCellEditing() {
isPushed = false;
return super.stopCellEditing();
}
protected void fireEditingStopped() {
super.fireEditingStopped();
}
}
I tried to change the font of the buttons by adding the following line of code to the ButtonEditor class
button.setFont(new Font("Comic Sans MS",0,25));
But it doesn't Work!!
What should I do to change the font of those buttons
Edit your ButtonRenderer class as follows:
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) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(UIManager.getColor("Button.background"));
}
setText((value == null) ? "" : value.toString());
setFont(new Font("Times New Roman", 0, 10)); //Add this line
return this;
}
}
Font was always being reset to the table's model, so you were needing to add that line to force the model to respect the change.
And your output should be:
I want to change the action of the button to delete. I have this code:
package buttonexample;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
public class ButtonExample {
public JTable table;
public static void main(String[] args) {
final ButtonExample example = new ButtonExample();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
example.createAndShowGUI();
}
});
}
private void createAndShowGUI() {
JFrame frame = new JFrame("Button Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
table = new JTable(new JTableModel());
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
TableCellRenderer buttonRenderer = new JTableButtonRenderer();
//table.getColumn("Button1").setCellRenderer(buttonRenderer);
table.getColumn("Button2").setCellRenderer(buttonRenderer);
table.addMouseListener(new JTableButtonMouseListener(table));
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.getContentPane().setPreferredSize(new Dimension(500, 200));
frame.pack();
frame.setVisible(true);
}
public static class JTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private static final String[] COLUMN_NAMES = new String[] {"Id", "Stuff", "Asdfsdf", "Button2"};
private static final Class<?>[] COLUMN_TYPES = new Class<?>[] {Integer.class, String.class, String.class, JButton.class};
#Override public int getColumnCount() {
return COLUMN_NAMES.length;
}
#Override public int getRowCount() {
return 4;
}
#Override public String getColumnName(int columnIndex) {
return COLUMN_NAMES[columnIndex];
}
#Override public Class<?> getColumnClass(int columnIndex) {
return COLUMN_TYPES[columnIndex];
}
#Override public Object getValueAt(final int rowIndex, final int columnIndex) {
switch (columnIndex) {
case 0: return rowIndex;
case 1: return "Text for "+rowIndex;
case 2: return "Column for "+rowIndex;
case 3: final JButton button = new JButton(COLUMN_NAMES[columnIndex]);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
// When this is clicked the whole row will be deleted.
JOptionPane.showMessageDialog(JOptionPane.getFrameForComponent(button),
"Button clicked for row "+rowIndex);
}
});
return button;
default: return "Error";
}
}
}
private static class JTableButtonRenderer implements TableCellRenderer {
#Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JButton button = (JButton)value;
if (isSelected) {
button.setForeground(table.getSelectionForeground());
button.setBackground(table.getSelectionBackground());
} else {
button.setForeground(table.getForeground());
button.setBackground(UIManager.getColor("Button.background"));
}
return button;
}
}
private static class JTableButtonMouseListener extends MouseAdapter {
private final JTable table;
public JTableButtonMouseListener(JTable table) {
this.table = table;
}
public void mouseClicked(MouseEvent e) {
int column = table.getColumnModel().getColumnIndexAtX(e.getX());
int row = e.getY()/table.getRowHeight();
if (row < table.getRowCount() && row >= 0 && column < table.getColumnCount() &&
column >= 0) {
Object value = table.getValueAt(row, column);
if (value instanceof JButton) {
((JButton)value).doClick();
}
}
}
}
}
But the (DefaultTableModel)someTable.getModel(); model.removeRow(row); I can't make it work because the table model does not have any name and I don't know what to name it. I have tried initializing a table model and I get error saying non-static variable model cannot be reference to a static context. Is there a way to delete the row in a static context?
The example by camickr is probably a more reusable solution, but for the sake of education...
Rendering of cells is the domain of the view
Model's should never contain components, especially if you're thinking about rendering them to the screen, this is simply the wrong approach to take...
You need to set up a TableCellEditor which will act as the means by which you can retrieve notification of the edit actions (mouse click or keypress)
This is a basic example, for simplicity, I've used a DefaultTableModel as it has a nice removeRow method, but conceivably, you could use any TableModel, so long as you provided the means to remove a row and modified by the editor to support it...
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import javax.swing.AbstractCellEditor;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.event.CellEditorListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
public class ButtonExample {
public JTable table;
public static void main(String[] args) {
final ButtonExample example = new ButtonExample();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
example.createAndShowGUI();
}
});
}
private void createAndShowGUI() {
JFrame frame = new JFrame("Button Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
table = new JTable(new ExampleTableModel());
JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);
table.getColumn("action").setCellRenderer(new ButtonCellRenderer());
table.getColumn("action").setCellEditor(new ButtonCellEditor());
frame.getContentPane().add(scrollPane, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
}
public static class ExampleTableModel extends DefaultTableModel {
public ExampleTableModel() {
super(new Object[]{"id", "stuff", "blah", "action"}, 0);
for (int index = 0; index < 10; index++) {
addRow(new Object[]{index, "Text for " + index, "Na na", index});
}
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 3;
}
}
public static class ButtonCellRenderer extends JButton implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value != null) {
setText("Delete row " + value.toString());
} else {
setText("Delete Me");
}
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(UIManager.getColor("Button.background"));
}
return this;
}
}
public static class ButtonCellEditor extends AbstractCellEditor implements TableCellEditor {
private JButton editor;
private Object value;
private int row;
private JTable table;
public ButtonCellEditor() {
editor = new JButton();
editor.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (table != null) {
fireEditingStopped();
TableModel model = table.getModel();
if (model instanceof DefaultTableModel) {
((DefaultTableModel) model).removeRow(row);
}
}
}
});
}
#Override
public boolean isCellEditable(EventObject e) {
return true;
}
#Override
public Object getCellEditorValue() {
return value;
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
this.table = table;
this.row = row;
this.value = value;
if (value != null) {
editor.setText("Delete row " + value.toString());
} else {
editor.setText("Delete Me");
}
if (isSelected) {
editor.setForeground(table.getSelectionForeground());
editor.setBackground(table.getSelectionBackground());
} else {
editor.setForeground(table.getForeground());
editor.setBackground(UIManager.getColor("Button.background"));
}
return editor;
}
}
}
Take a closer look at How to Use Tables for more details
This is just a personal preference, but I prefer to use a toolbar or menu item and key bindings to provide this support. Buttons in a table just seem so...dated - IMHO
I created JTable that contains information about employees. In this JTable I added the column called "Qualifications". This column is represented by JComboBox (different content at each row). For instance:
Row 1 | JComboBox(){"Programmer","Web"}
Row 2 | JComboBox(){"Writer","Editor"}
The JComboBox content is taken from the List<String> employees[row].getQualification().
The problem is that the selected item in Row 1 and Row 2 is "Programmer", however "Programmer" should not appear in Row 2. Only when I click on JComboBox, the correct list appears, i.e. Row 2 - {"Writer","Editor"}.
TableColumn column = table.getColumnModel().getColumn(5);
column.setCellRenderer(getRenderer());
private TableCellRenderer getRenderer() {
return new TableCellRenderer() {
private JComboBox<String> box = new JComboBox<String>();
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
for (String q : employees[row].getQualification())
box.addItem(q);
box.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
box.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
return box;
}
};
}
Override the getCellEditor() method of the JTable. Something like:
import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class TableComboBoxByRow extends JPanel
{
List<TableCellEditor> editors = new ArrayList<TableCellEditor>(3);
public TableComboBoxByRow()
{
setLayout( new BorderLayout() );
// Create the editors to be used for each row
String[] items1 = { "Red", "Blue", "Green" };
JComboBox<String> comboBox1 = new JComboBox<String>( items1 );
DefaultCellEditor dce1 = new DefaultCellEditor( comboBox1 );
editors.add( dce1 );
String[] items2 = { "Circle", "Square", "Triangle" };
JComboBox<String> comboBox2 = new JComboBox<String>( items2 );
DefaultCellEditor dce2 = new DefaultCellEditor( comboBox2 );
editors.add( dce2 );
String[] items3 = { "Apple", "Orange", "Banana" };
JComboBox<String> comboBox3 = new JComboBox<String>( items3 );
DefaultCellEditor dce3 = new DefaultCellEditor( comboBox3 );
editors.add( dce3 );
// Create the table with default data
Object[][] data =
{
{"Color", "Red"},
{"Shape", "Square"},
{"Fruit", "Banana"},
{"Plain", "Text"}
};
String[] columnNames = {"Type","Value"};
DefaultTableModel model = new DefaultTableModel(data, columnNames);
JTable table = new JTable(model)
{
// Determine editor to be used by row
public TableCellEditor getCellEditor(int row, int column)
{
int modelColumn = convertColumnIndexToModel( column );
if (modelColumn == 1 && row < 3)
return editors.get(row);
else
return super.getCellEditor(row, column);
}
};
JScrollPane scrollPane = new JScrollPane( table );
add( scrollPane );
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("Table Combo Box by Row");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new TableComboBoxByRow() );
frame.setSize(200, 200);
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
JComboBox-es appear only on a click
because you use them as CellEditor, which apper only when you edit cells. If you want to display your column cells as JComboBox everytime, you need to use TableCellRenderer, read about that. Here is simple example of JComboBox as renderer :
import java.awt.Component;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class TestFrame extends JFrame{
public TestFrame(){
init();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
private void init() {
JTable t = new JTable(3,3);
TableColumn column = t.getColumnModel().getColumn(2);
column.setCellRenderer(getRenderer());
add(new JScrollPane(t));
}
private TableCellRenderer getRenderer() {
return new TableCellRenderer() {
private JComboBox<String> box = new JComboBox<String>(new String[]{"1","2"});
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
box.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
box.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
return box;
}
};
}
public static void main(String... s){
new TestFrame();
}
}
Thanks to #alex2410, I cleaned up the code and wrapped it into a ComboTable class which should do the job for you. instantiate ComboTable class with a hashmap of each row values (the demo assumes 2 columns, but you can add more). Note MyMap.of is just a wrapper for java 9 Map.of since I was using Java 8 at that time. same for MyList.of
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.EventObject;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.DefaultCellEditor;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.CellEditorListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import rs.code.utils.MyList;
import rs.code.utils.MyMap;
public class Test extends JFrame
{
private static final long serialVersionUID = 1L;
public ComboTable table = new ComboTable(MyMap.of("Gender", MyList.of("male", "female"), "City", MyList.of("london", "bedord"), "orientation", MyList.of("left", "right")));
public Test()
{
super("EachRow Editor Example");
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll, BorderLayout.CENTER);
setPreferredSize(new Dimension(400, 120));
setLocation(150, 100);
pack();
setVisible(true);
}
public static void main(String[] args)
{
Test frame = new Test();
frame.addWindowListener(new WindowAdapter()
{
#Override
public void windowClosing(WindowEvent e)
{
System.out.println(frame.table.getSelectedValues().toString());
System.exit(0);
}
});
}
}
class ComboTable extends JTable
{
private static final long serialVersionUID = 1L;
protected Map<Integer, ComboCellEditor> editors = new LinkedHashMap<>();
public ComboTable(Map<String, List<String>> rows)
{
setModel(new DefaultTableModel(new String[] {"Attribute", "Value"}, rows.size()));
setRowHeight(20);
EachRowEditor rowEditor = new EachRowEditor(this);
int i = 0;
for(String key : rows.keySet())
{
getModel().setValueAt(key, i, 0);
editors.put(i++, new ComboCellEditor(createComboBox(rows.get(key))));
}
getColumn("Value").setCellEditor(rowEditor);
getColumn("Value").setCellRenderer(getRenderer());
}
public Map<Integer, ComboCellEditor> getEditors()
{
return editors;
}
public Map<String, String> getSelectedValues()
{
Map<String, String> values = new LinkedHashMap<>();
for(int i=0;i<getModel().getRowCount();i++)
{
values.put(getModel().getValueAt(i, 0).toString(), editors.get(i).getComboBox().getSelectedItem().toString());
}
return values;
}
private JComboBox<String> createComboBox(List<String> elements)
{
JComboBox<String> comboBox = new JComboBox<>();
for (String element : elements)
{
comboBox.addItem(element);
}
comboBox.setSelectedIndex(0);
comboBox.addComponentListener(new ComponentAdapter()
{
#Override
public void componentShown(ComponentEvent e)
{
final JComponent c = (JComponent) e.getSource();
SwingUtilities.invokeLater(new Runnable()
{
#SuppressWarnings("rawtypes")
#Override
public void run()
{
c.requestFocus();
System.out.println(c);
if (c instanceof JComboBox)
{
System.out.println(((JComboBox) c).getSelectedItem());
}
}
});
}
});
return comboBox;
}
private TableCellRenderer getRenderer()
{
return new TableCellRenderer()
{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
editors.get(row).getComboBox().setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
editors.get(row).getComboBox().setForeground(isSelected ? table.getSelectionForeground() : table.getForeground());
return editors.get(row).getComboBox();
}
};
}
}
class ComboCellEditor extends DefaultCellEditor
{
private static final long serialVersionUID = 1L;
private final JComboBox<String> comboBox;
public ComboCellEditor(JComboBox<String> comboBox)
{
super(comboBox);
this.comboBox = comboBox;
}
public JComboBox<String> getComboBox()
{
return comboBox;
}
}
class EachRowEditor implements TableCellEditor
{
private TableCellEditor editor;
private final TableCellEditor defaultEditor;
private final ComboTable table;
public EachRowEditor(ComboTable table)
{
this.table = table;
defaultEditor = new DefaultCellEditor(new JTextField());
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
return editor.getTableCellEditorComponent(table, value, isSelected, row, column);
}
public Object getCellEditorValue()
{
return editor.getCellEditorValue();
}
public boolean stopCellEditing()
{
return editor.stopCellEditing();
}
public void cancelCellEditing()
{
editor.cancelCellEditing();
}
public boolean isCellEditable(EventObject anEvent)
{
selectEditor((MouseEvent) anEvent);
return editor.isCellEditable(anEvent);
}
public void addCellEditorListener(CellEditorListener l)
{
editor.addCellEditorListener(l);
}
public void removeCellEditorListener(CellEditorListener l)
{
editor.removeCellEditorListener(l);
}
public boolean shouldSelectCell(EventObject anEvent)
{
selectEditor((MouseEvent) anEvent);
return editor.shouldSelectCell(anEvent);
}
protected void selectEditor(MouseEvent e)
{
int row;
if (e == null)
{
row = table.getSelectionModel().getAnchorSelectionIndex();
}
else
{
row = table.rowAtPoint(e.getPoint());
}
editor = table.getEditors().get(row);
if (editor == null)
{
editor = defaultEditor;
}
}
}
I have a question for JTable.
When I select a cell and then there are same value cell in JTable which I chose, that cells highlight background red color.
I don't know what to do....
P.S: I am sorry, I do not know how to enter the code in here...;;
You can implement ListSelectionListener to track selection changes in a table. Then implement TableCellRenderer that would change background of a cell with the same value of a selected object. Check out How to Use Tables for more details on JTable, renderers and selection.
Here is a very simple example that demonstrates this idea:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.Color;
import java.awt.Component;
public class TableDemo {
private static void createAndShowGUI() {
JFrame frame = new JFrame("TableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPanel = new JPanel();
String[] columnNames = { "Column1", "Column2" };
Object[][] data = { { "1", "3" }, { "2", "5" }, { "7", "1" },
{ "5", "3" } };
JTable table = new JTable();
MyModel model = new MyModel(Color.RED, table.getBackground());
model.setDataVector(data, columnNames);
table.setModel(model);
table.setColumnSelectionAllowed(true);
table.setDefaultRenderer(Object.class, new TestCellRenderer());
SelectionListener listener = new SelectionListener(table);
table.getSelectionModel().addListSelectionListener(listener);
table.getColumnModel().getSelectionModel()
.addListSelectionListener(listener);
JScrollPane scrollPane = new JScrollPane(table);
contentPanel.add(scrollPane);
contentPanel.setOpaque(true);
frame.add(contentPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
static class TestCellRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
Component c = super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
MyModel model = (MyModel) table.getModel();
c.setBackground(model.getCellColor(row, column));
return c;
}
}
static class MyModel extends DefaultTableModel {
private Object selectedObject;
private Color selectedColor;
private Color normalColor;
public MyModel(Color selectedColor, Color normalColor) {
this.selectedColor = selectedColor;
this.normalColor = normalColor;
}
public Color getCellColor(int row, int column) {
if (getValueAt(row, column).equals(selectedObject))
return selectedColor;
return normalColor;
}
public void setSelectedObject(Object selectedObject) {
this.selectedObject = selectedObject;
fireTableRowsUpdated(0, getRowCount());
}
}
static class SelectionListener implements ListSelectionListener {
private JTable table;
SelectionListener(JTable table) {
this.table = table;
}
public void valueChanged(ListSelectionEvent e) {
int rowIndex = table.getSelectedRow();
int colIndex = table.getSelectedColumn();
if (!e.getValueIsAdjusting() && colIndex != -1 && rowIndex != -1) {
((MyModel) table.getModel()).setSelectedObject(table
.getValueAt(rowIndex, colIndex));
}
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Here is a result:
EDIT: solution using renderer only, without table model
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.Color;
import java.awt.Component;
public class TableDemo {
private static void createAndShowGUI() {
JFrame frame = new JFrame("TableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel contentPanel = new JPanel();
String[] columnNames = { "Column1", "Column2" };
Object[][] data = { { "1", "3" }, { "2", "5" }, { "7", "1" },
{ "5", "3" } };
JTable table = new JTable(new DefaultTableModel(data, columnNames));
table.setColumnSelectionAllowed(true);
TestCellRenderer renderer = new TestCellRenderer();
table.setDefaultRenderer(Object.class, renderer);
SelectionListener listener = new SelectionListener(table);
table.getSelectionModel().addListSelectionListener(listener);
table.getColumnModel().getSelectionModel()
.addListSelectionListener(listener);
JScrollPane scrollPane = new JScrollPane(table);
contentPanel.add(scrollPane);
contentPanel.setOpaque(true);
frame.add(contentPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
static class TestCellRenderer extends DefaultTableCellRenderer {
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
Component c = super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
int columnIndex = table.getSelectedColumn();
int rowIndex = table.getSelectedRow();
if (columnIndex != -1 && rowIndex != -1){
Object selectedValue = table.getValueAt(rowIndex, columnIndex);
if (value.equals(selectedValue)) {
c.setBackground(Color.RED);
} else {
c.setBackground(table.getBackground());
}
}
return c;
}
}
static class SelectionListener implements ListSelectionListener {
private JTable table;
SelectionListener(JTable table) {
this.table = table;
}
public void valueChanged(ListSelectionEvent e) {
int rowIndex = table.getSelectedRow();
int colIndex = table.getSelectedColumn();
if (!e.getValueIsAdjusting() && colIndex != -1 && rowIndex != -1){
table.repaint();
}
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}