Adding button to jtable - java

I searched for tutorials for adding button in jtable and found a class file from, http://tips4java.wordpress.com/2009/07/12/table-button-column/ Where to set label for the button?
[code]
private void createTable(){
model = new DefaultTableModel();
editorTable.setModel(model);
model.addColumn("COL1");
model.addColumn("COL2");
model.addColumn("ADD");
model.addColumn("DELETE");
model.addRow(new Object[]{"DATA1", "DATA2"});
Action delete = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
editorTable = (JTable) e.getSource();
int modelRow = Integer.valueOf(e.getActionCommand());
((DefaultTableModel) editorTable.getModel()).removeRow(modelRow);
}
};
ButtonColumn bc = new ButtonColumn(editorTable, delete, 3);
bc.setMnemonic(KeyEvent.VK_D);
}
[/code]

It is set automatically in the table renderer and editor from the data in your DefaultTableModel. For example, for the table editor, the code is:
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column) {
...
editButton.setText( value.toString() );
editButton.setIcon( null );
...
}
where value is the value from your table model. See ButtonColumn.java for details.
EDIT: Since you are adding 4 columns, you should probably change your row data to
model.addRow(new Object[]{"DATA1", "DATA2", "DATA3", "DELETE"});
in order to see the delete buttons on the 4th column.

MyClass myClass = new MyClass();
jTable1.getColumnModel().getColumn(0).setCellEditor(myClass);
jTable1.getColumnModel().getColumn(0).setCellRenderer(myClass);
class MyClass extends AbstractCellEditor implements TableCellEditor, TableCellRenderer
{
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
{
JPanel panel=(JPanel)jTable1.getCellRenderer(row, column).getTableCellRendererComponent(table, value, isSelected, isSelected, row, column);
panel.setBackground(table.getSelectionBackground());
return panel;
}
#Override
public Object getCellEditorValue()
{
return null;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
AbstractAction action = new AbstractAction()
{
#Override
public void actionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(rootPane,"Row :"+jTable1.getSelectedRow()+" "+ e.getActionCommand() + " clicked");
}
};
JButton button1 = new JButton(action);
JButton button2 = new JButton(action);
button1.setText("Button1");
button2.setText("Button2");
JPanel panel = new JPanel();
panel.add(button1);
panel.add(button2);
panel.setBackground(table.getBackground());
return panel;
}
}
}

Related

Highlight a specifi row JTable

I know there are previous topics for a similar problem but even with it I wasn't able to resolve my problem.
So the thing is, when I add a new empty row to my JTable I want to highlight it in gray. So it works for the first one but when I try to add a second row, the second will be white...
I tried to debbug but without success, I didn't find my mistake.
Here is the class to highlight a row :
class GrayWhiteRenderer extends DefaultTableCellRenderer {
private int rowToColored;
GrayWhiteRenderer(int rowToColored) {
this.rowToColored = rowToColored;
Color color = UIManager.getColor ( "table.row" );
}
#Override
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);
if (UIManager.getColor ( "table.row" )==Color.GRAY) {
c.setBackground(Color.GRAY.brighter());
}
else if(row == rowToColored) {
c.setBackground(Color.GRAY.brighter());
} else {
c.setBackground(Color.WHITE);
}
return c;
}
}
I store the index of all new row in rowToAdd at the begining of it (for exemple : [19, 20, 21, -1, -1, ...]. -1 is to know when I have to stop looking if I have to highlight more) :
while(rowToAdd[k]!=-1) {
System.out.println("rowToAdd[k] : "+rowToAdd[k]);
dataTable.setDefaultRenderer(Object.class, new GrayWhiteRenderer(rowToAdd[k]));
k++;
}
And here is a class to test it :
package Graphic;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
class Test implements Runnable, ActionListener {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Test());
}
JTable table;
#Override
public void run() {
JFrame frame = new JFrame("Custom Cell Renderer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
table = new JTable(new DefaultTableModel(0, 2) {
#Override
public Class<?> getColumnClass(int c) {
return Object.class;
}
});
class GrayWhiteRenderer extends DefaultTableCellRenderer {
private int rowToColored;
GrayWhiteRenderer(int rowToColored) {
this.rowToColored = rowToColored;
}
#Override
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);
if (UIManager.getColor ( "table.row" )==Color.GRAY) {
c.setBackground(Color.GRAY.brighter());
}
else if(row == rowToColored) {
c.setBackground(Color.GRAY.brighter());
} else {
c.setBackground(Color.WHITE);
}
return c;
}
}
table.setDefaultRenderer(Object.class, new GrayWhiteRenderer(table.getRowCount()));
table.setTableHeader(null);
JButton btn = new JButton("Add Row");
btn.addActionListener(this);
JToolBar bar = new JToolBar();
bar.setFloatable(false);
bar.add(btn);
JPanel content = new JPanel(new BorderLayout());
content.add(bar, BorderLayout.NORTH);
content.add(new JScrollPane(table), BorderLayout.CENTER);
frame.setContentPane(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent ae) {
int nextRow = table.getRowCount();
DefaultTableModel model = (DefaultTableModel)table.getModel();
model.addRow(new Object[] { "" + nextRow, "" + nextRow });
for(int i=0; i<model.getColumnCount(); i++) {
table.setDefaultRenderer(Object.class, new GrayWhiteRenderer(i));
}
}
}
So, I've fixed your example. Here is your code with my comments
#Override
public void actionPerformed(ActionEvent ae) {
int nextRow = table.getRowCount();
DefaultTableModel model = (DefaultTableModel) table.getModel();
model.addRow(new Object[] {"" + nextRow, "" + nextRow});
// the correct row is: nextRow. No loop required here.
table.setDefaultRenderer(Object.class, new GrayWhiteRenderer(nextRow));
}
I would also correct your renderer to provide selection highlight
class GrayWhiteRenderer extends DefaultTableCellRenderer {
private int rowToColored;
GrayWhiteRenderer(int rowToColored) {
this.rowToColored = rowToColored;
}
#Override
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);
// As I know there is no value is registered for "table.row" in UIManager
// so I've skipped the first condition
if (row == rowToColored) {
c.setBackground(Color.GRAY.brighter());
} else {
// use correct color depended on whether the cell is selected or not!
c.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
}
return c;
}
}

Add margin to JTable column (Mac)

I have a JTable looking like this:
Is it possible to add a margin for the column text?
I have tried to add a TableCellRenderer and add an EmptyBorder. Problem: the background color gets white like this:
Any idea how to add margin and keep the default background color?
public class JTableColumnMargin extends JFrame {
public JTableColumnMargin() {
Object rowData[][] = { { "Row1-Column1", "Row1-Column2", "Row1-Column3" }, { "Row2-Column1", "Row2-Column2", "Row2-Column3" } };
Object columnNames[] = { "Column One", "Column Two", "Column Three" };
JTable table = new JTable(rowData, columnNames);
for (int i = 0; i < table.getColumnCount(); i++) {
table.getTableHeader().getColumnModel().getColumn(i).setHeaderRenderer(new HeaderRenderer(table));
}
JScrollPane scrollPane = new JScrollPane(table);
this.add(scrollPane, BorderLayout.CENTER);
this.setSize(500, 150);
this.setVisible(true);
}
private static class HeaderRenderer implements TableCellRenderer {
private DefaultTableCellRenderer renderer;
private HeaderRenderer(JTable table) {
renderer = (DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer();
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
Component c = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
JLabel label = (JLabel) c;
label.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
return label;
}
}
public static void main(String[] args) {
new JTableColumnMargin();
}
}
Delegating to the original renderer basically is the right direction to go, just slightly differently:
use a compoundBorder of the original and the emptyBorder
nudge the original renderer to re-set the border to its original by making the padded border a UIResource
Something like:
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
JComponent comp = (JComponent) originalRenderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
Border originalBorder = comp.getBorder();
comp.setBorder(new CompoundBorderUIResource(originalBorder,
BorderFactory.createEmptyBorder(0, 20, 0, 0)));
return comp;
}
It's brittle, though, as LAFs might ignore your setting: the trick works fine for WinLAF, but not at all for Nimbus - so don't know the outcome on Mac.
Try to use next header Renderer:
private static class HeaderRenderer extends JLabel implements TableCellRenderer {
private HeaderRenderer() {
setBorder(BorderFactory.createCompoundBorder(UIManager.getBorder("TableHeader.cellBorder"),BorderFactory.createEmptyBorder(0, 10, 0, 10)));
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
setText(value.toString());
return this;
}
}

Netbeans GUI: JTable with Double cell adds to current entry when typing instead of replacing

I have a GUI designed as a Form in Netbeans 7.2. I have a JTable with the troublesome behavior. The table model is designed with Right-Click -> Properties -> Model and setting up 1 row and 12 columns with types Long and Double for editable number fields.
Now if I navigate to such a cell which contain e.g. "0.0" and just start typing "123" I get "0.0123" instead of "123". I would like it to work that if you just start typing you start with a blank value - and if the entry is "clicked" then you start editing the cell and whatever you type is inserted at the cursor location.
Can this be done easily?
I found https://stackoverflow.com/a/8493016/53897 to work.
The way to add the code, is to right-click the JTable in the Navigator, and choose "Code Customizer". In the line for new javax.swing.JTable() change the drop down box to "custom creation" and you can now edit that snippet including adding the {...#Override public void changeSelection(...)...} needed for this.
whats wrong with standard Swing JTable and DefaultTableModel
sure there are missing some ideas for productions code (make the things better)..., selectAll for Editor, cell alingment, background, foreground, stripping, font, Look and Feels etc... (most of custom Look and Feels doesn't works correctly with built-in Components pallette in Netbeans Swing Framework),
SwingX have got Components pallette for Netbeans, better and safest way, maybe you have look at ...
import java.awt.*;
import java.awt.event.*;
import java.text.NumberFormat;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.table.*;
public class EditorTest {
private JScrollPane getTableComponent() {
String[] colNames = {"Stock", "Price", "Shares", "Quantity", "Action", "Action", "Holder"
};
final Object[][] data = {{"MSFT", Double.valueOf(12.21), Integer.valueOf(10),
Integer.valueOf(0), "Buy", "Sell", "Bill"}, {"IBM", Double.valueOf(13.21), Integer.valueOf(12),
Integer.valueOf(0), "Buy", "Sell", "Tim"}, {"ORACLE", Double.valueOf(21.22), Integer.valueOf(11),
Integer.valueOf(0), "Buy", "Sell", "Tom"}
};
DefaultTableModel model = new DefaultTableModel(data, colNames) {
private static final long serialVersionUID = 1L;
#Override
public Class getColumnClass(int col) {
return data[0][col].getClass();
}
};
JTable table = new JTable(model);
TableColumnModel colModel = table.getColumnModel();
colModel.getColumn(1).setCellRenderer(new DoubleRenderer());
colModel.getColumn(3).setCellRenderer(new SpinnerRenderer());
colModel.getColumn(4).setCellRenderer(new ButtonRenderer());
colModel.getColumn(5).setCellRenderer(new ButtonRenderer());
colModel.getColumn(3).setCellEditor(new SpinnerEditor());
colModel.getColumn(4).setCellEditor(new ButtonEditorA(table));
colModel.getColumn(5).setCellEditor(new ButtonEditorA(table));
table.setCellSelectionEnabled(true);
Dimension d = table.getPreferredSize();
table.setPreferredScrollableViewportSize(d);
return new JScrollPane(table);
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new EditorTest().getTableComponent());
f.pack();
f.setLocation(100, 100);
f.setVisible(true);
}
}
class SpinnerEditor extends AbstractCellEditor implements TableCellEditor {
private static final long serialVersionUID = 1L;
private SpinnerNumberModel model = new SpinnerNumberModel(0, 0, null, 1);
private JSpinner spinner = new JSpinner(model);
private int clickCountToStart = 1;
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
spinner.setValue(((Integer) value).intValue());
return spinner;
}
public Object getCellEditorValue() {
return (Integer) spinner.getValue();
}
#Override
public boolean isCellEditable(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
return ((MouseEvent) anEvent).getClickCount() >= clickCountToStart;
}
return true;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
#Override
public boolean stopCellEditing() {
return super.stopCellEditing();
}
#Override
public void cancelCellEditing() {
super.cancelCellEditing();
}
}
class ButtonEditorA extends AbstractCellEditor implements TableCellEditor, ActionListener {
private static final long serialVersionUID = 1L;
private JTable table;
private JButton button = new JButton();
private NumberFormat nf = NumberFormat.getCurrencyInstance();
private int clickCountToStart = 1;
public ButtonEditorA(JTable table) {
this.table = table;
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
StringBuilder sb = new StringBuilder();
int row = table.getEditingRow();
int col = table.getEditingColumn();
//System.out.printf("row = %d col = %d%n", row, col);
sb.append((String) table.getValueAt(row, 6));
sb.append(" has ");
sb.append(((col == 4) ? "bought " : "sold "));
sb.append(((Integer) table.getValueAt(row, 3)).toString());
sb.append(" shares of " + (String) table.getValueAt(row, 0));
sb.append(" at " + nf.format(((Double) table.getValueAt(row, 1)).doubleValue()));
stopCellEditing();
System.out.println(sb.toString());
}
public Component getTableCellEditorComponent(JTable table,
Object value,
boolean isSelected,
int row, int column) {
button.setText(value.toString());
return button;
}
public Object getCellEditorValue() {
return button.getText();
}
#Override
public boolean isCellEditable(EventObject anEvent) {
if (anEvent instanceof MouseEvent) {
return ((MouseEvent) anEvent).getClickCount() >= clickCountToStart;
}
return true;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
#Override
public boolean stopCellEditing() {
return super.stopCellEditing();
}
#Override
public void cancelCellEditing() {
super.cancelCellEditing();
}
}
class SpinnerRenderer implements TableCellRenderer {
private SpinnerNumberModel model = new SpinnerNumberModel(0, 0, null, 1);
private JSpinner spinner = new JSpinner(model);
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, int column) {
spinner.setValue(((Integer) value).intValue());
return spinner;
}
}
class ButtonRendererA implements TableCellRenderer {
private JButton button = new JButton();
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
button.setText(value.toString());
return button;
}
}
class DoubleRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1L;
private NumberFormat nf = NumberFormat.getCurrencyInstance();
public DoubleRenderer() {
setHorizontalAlignment(RIGHT);
}
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setText(nf.format(((Double) value).doubleValue()));
return this;
}
}

JTable cellEditor stays after table data model change

I have set a cell editor for one of the columns to be a JSpinner and it works, but when the data in the data model changes the editor i enabled before is still enabled nad it shows the value form the old row (it does not exist or it is in a different place in the changed data).
How can i make the editor for the selected cell disappear saving the entered value when the data changes?
this one could be good code for your SSCCE
import java.awt.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class SpinnerColumn extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
private static final long serialVersionUID = 1L;
private JSpinner editSpinner, renderSpinner;
private JTable table;
private String[] list;
private Border originalBorder;
public SpinnerColumn(JTable table, int column) {
editSpinner = new JSpinner();
renderSpinner = new JSpinner();
originalBorder = editSpinner.getBorder();
editSpinner.setBorder(new LineBorder(Color.BLUE));
this.table = table;
table.getColumnModel().getColumn(column).setCellEditor(this);
}
public SpinnerColumn(String[] list, JTable table, int column) {
editSpinner = new JSpinner();
editSpinner.setModel(new SpinnerListModel(list));
renderSpinner = new JSpinner();
originalBorder = editSpinner.getBorder();
editSpinner.setBorder(new LineBorder(Color.BLUE));
this.list = list;
this.table = table;
table.getColumnModel().getColumn(column).setCellEditor(this);
}
#Override
public Object getCellEditorValue() {
return editSpinner.getValue();
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
int row, int column) {
if (list != null) {
editSpinner.setValue(list[0]);
} else {
editSpinner.setValue(0);
}
if (value != null) {
editSpinner.setValue(value);
}
return editSpinner;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
if (hasFocus) {
renderSpinner.setBorder(new LineBorder(Color.BLUE));
} else {
renderSpinner.setBorder(originalBorder);
}// *** here's where we set the spinner's value
if (value == null) {
renderSpinner.setValue(0);
} else {
int intValue = ((Integer) value).intValue();
renderSpinner.setValue(intValue);
}
return renderSpinner;
}
#Override
public boolean isCellEditable(EventObject evt) {
return true;
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("SpinnerColumn");
JPanel panel = new JPanel(new GridLayout(1, 1));
JTable table = new JTable(5, 1);
SpinnerColumn spinnerColumn = new SpinnerColumn(table, 0);
table.setDefaultRenderer(Object.class, spinnerColumn);
panel.add(table);
frame.setContentPane(panel);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
}

Change the background color of a row in a JTable

I have a JTable with 3 columns. I've set the TableCellRenderer for all the 3 columns like this (maybe not very effective?).
for (int i = 0; i < 3; i++) {
myJTable.getColumnModel().getColumn(i).setCellRenderer(renderer);
}
The getTableCellRendererComponent() returns a Component with a random background color for each row.
How could I change the background to an other random color while the program is running?
Resumee of Richard Fearn's answer , to make each second line gray:
jTable.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()
{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
final Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
c.setBackground(row % 2 == 0 ? Color.LIGHT_GRAY : Color.WHITE);
return c;
}
});
One way would be store the current colour for each row within the model. Here's a simple model that is fixed at 3 columns and 3 rows:
static class MyTableModel extends DefaultTableModel {
List<Color> rowColours = Arrays.asList(
Color.RED,
Color.GREEN,
Color.CYAN
);
public void setRowColour(int row, Color c) {
rowColours.set(row, c);
fireTableRowsUpdated(row, row);
}
public Color getRowColour(int row) {
return rowColours.get(row);
}
#Override
public int getRowCount() {
return 3;
}
#Override
public int getColumnCount() {
return 3;
}
#Override
public Object getValueAt(int row, int column) {
return String.format("%d %d", row, column);
}
}
Note that setRowColour calls fireTableRowsUpdated; this will cause just that row of the table to be updated.
The renderer can get the model from the table:
static class MyTableCellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
MyTableModel model = (MyTableModel) table.getModel();
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
c.setBackground(model.getRowColour(row));
return c;
}
}
Changing a row's colour would be as simple as:
model.setRowColour(1, Color.YELLOW);
The other answers given here work well since you use the same renderer in every column.
However, I tend to believe that generally when using a JTable you will have different types of data in each columm and therefore you won't be using the same renderer for each column. In these cases you may find the Table Row Rendering approach helpfull.
This is basically as simple as repainting the table. I haven't found a way to selectively repaint just one row/column/cell however.
In this example, clicking on the button changes the background color for a row and then calls repaint.
public class TableTest {
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final Color[] rowColors = new Color[] {
randomColor(), randomColor(), randomColor()
};
final JTable table = new JTable(3, 3);
table.setDefaultRenderer(Object.class, new TableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
JPanel pane = new JPanel();
pane.setBackground(rowColors[row]);
return pane;
}
});
frame.setLayout(new BorderLayout());
JButton btn = new JButton("Change row2's color");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
rowColors[1] = randomColor();
table.repaint();
}
});
frame.add(table, BorderLayout.NORTH);
frame.add(btn, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
private static Color randomColor() {
Random rnd = new Random();
return new Color(rnd.nextInt(256),
rnd.nextInt(256), rnd.nextInt(256));
}
}
The call to getTableCellRendererComponent(...) includes the value of the cell for which a renderer is sought.
You can use that value to compute a color. If you're also using an AbstractTableModel, you can provide a value of arbitrary type to your renderer.
Once you have a color, you can setBackground() on the component that you're returning.

Categories