I have a table with a column as JButton.
i set the renderer as follows
TableColumn col = colModel.getColumn(3);
col.setCellRenderer(new MyRenderer("Del"));
col.setCellEditor(new MultiTradeCellEditor(new JCheckBox()));
The renderer and cellEditor classes are
class MyRenderer extends JButton implements TableCellRenderer{
public MyRenderer(String text){
super(text);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
return this;
}
}
}
CellEditor class
class MultiTradeCellEditor extends DefaultCellEditor{
protected JButton button;
public MultiTradeCellEditor(JCheckBox checkBox) {
super(checkBox);
button = new JButton("Del");
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
selectionList.getList().remove(table.getSelectedRow());
table.repaint();
}
});
}
}
When i remove the row from the table. i do model.remove(table.getSelectedRow()). It removes the row except the JButton. I assume that button is part of a Renderer component so it doesnt get removed.
How can i do that ?
The Table Button Column example provides renderers and editor for a button as well as an example Action to delete a row from the table.
Odd.
Maybe a caching thing?
Try returning an empty label when there is no value?
class MyRenderer extends JComponent implements TableCellRenderer{
private String text;
public MyRenderer(String text){
this.text = text;
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value)
return new JButton(text);
else
return new JLabel();
}
}
}
Related
I'm using JXTable which has a setColumnControlVisible(true) which shows a button on the upper right corner above scroll, we can show and hide column by pressing it. I want to remember the changes when the app get close, but cannot figure it out yet, Here what I have tried so far. I check the src of JxTable, but didn't how to get the column index or column number which is hidden.
package paractice;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.table.AbstractTableModel;
import org.jdesktop.swingx.JXTable;
public class TableTest extends JFrame{
private static final long serialVersionUID = 1L;
private JXTable table;
public TableTest() {
setLayout(new BorderLayout());
table = new JXTable(new model());
//add(table.getTableHeader(), BorderLayout.NORTH);
add(new JScrollPane(table), BorderLayout.CENTER);
table.setColumnControlVisible(true);
setSize(700, 700);
}
public class model extends AbstractTableModel{
String[] columns = {"column1", "column2", "column3", "column4", "column5"};
#Override
public String getColumnName(int column) {
return columns[column];
}
#Override
public boolean isCellEditable(int arg0, int arg1) {
return super.isCellEditable(arg0, arg1);
}
#Override
public void setValueAt(Object arg0, int row, int col) {
super.setValueAt(arg0, row, col);
fireTableCellUpdated(row, col);
}
public int getColumnCount() {
return columns.length;
}
public int getRowCount() {
return 0;
}
public Object getValueAt(int arg0, int arg1) {
return null;
}
}
public static void main(String args[]) {
TableTest test = new TableTest();
test.setVisible(true);
}
}
but didn't how to get the column index or column number which is hidden.
Compare the TableModel with the JTableHeader.
Just create a simple loop to check all the columns name of the TableModel to see if the table contains that column. Something like:
for (int i = 0; i < model.getColumnCount(); i++)
{
Object name = model.getColumnName();
TableColumn column = table.getColumn( name );
if (column == null)
// column is hidden do your processing
}
Then the next time you display the table you can get the names of all hidden columns and then use:
table.removeColumn( table.getColumn( name ) );
I'm struggling with a at the first sight simple problem (and probably it is so...) - I have to disable certain button in the JTable upon value in one of the cells within the same row.
Below is my inner class for button rendering and editing:
private class CellButton {
class ButtonsPanel extends JPanel {
public JButton jbutton = new JButton("Accept!!");
public ButtonsPanel() {
super();
setOpaque(true);
jbutton.setFocusable(false);
jbutton.setRolloverEnabled(false);
jbutton.setSize(122, 30);
jbutton.setFont(new java.awt.Font("Tahoma", 3, 12));
jbutton.setForeground(new java.awt.Color(0, 102, 102));
add(jbutton);
}
private class ButtonsRenderer extends ButtonsPanel implements TableCellRenderer {
ButtonsPanel bp;
public ButtonsRenderer() {
super();
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
this.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
Object o = table.getModel().getValueAt(row, 8);
bp = (ButtonsPanel) o;
if (jTable5.getValueAt(row, 3).equals("NORMALNA")) {
bp.jbutton.setEnabled(false);
}
return this;
}
}
private class ButtonsEditor extends ButtonsPanel implements TableCellEditor {
ButtonsPanel bp;
public ButtonsEditor(final JTable table, final String tableName) {
super();
//DEBUG: view button click -> control key down + edit button(same cell) press -> remain selection color
MouseListener ml = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
ButtonModel m = ((JButton) e.getSource()).getModel();
if (m.isPressed() && table.isRowSelected(table.getEditingRow()) && e.isControlDown()) {
setBackground(table.getBackground());
}
}
};
jbutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
int row = table.convertRowIndexToModel(table.getEditingRow());
Object o = table.getModel().getValueAt(row, 0);
fireEditingStopped();
//update info status
setDmlUpdateStatusPrejeteInfo();
jDialog2.requestFocus();
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
fireEditingStopped();
}
});
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
this.setBackground(table.getSelectionBackground());
Object o = table.getModel().getValueAt(row, 8);
bp = (ButtonsPanel) o;
if (jTable5.getValueAt(row, 3).equals("NORMALNA")) {
bp.jbutton.setEnabled(false);
}
return this;
}
#Override
public Object getCellEditorValue() {
return "";
}
transient protected ChangeEvent changeEvent = null;
#Override
public boolean isCellEditable(EventObject e) {
return true;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
#Override
public boolean stopCellEditing() {
fireEditingStopped();
return true;
}
#Override
public void cancelCellEditing() {
fireEditingCanceled();
}
#Override
public void addCellEditorListener(CellEditorListener l) {
listenerList.add(CellEditorListener.class, l);
}
#Override
public void removeCellEditorListener(CellEditorListener l) {
listenerList.remove(CellEditorListener.class, l);
}
public CellEditorListener[] getCellEditorListeners() {
return listenerList.getListeners(CellEditorListener.class);
}
protected void fireEditingStopped() {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == CellEditorListener.class) {
// Lazily create the event:
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
((CellEditorListener) listeners[i + 1]).editingStopped(changeEvent);
}
}
}
protected void fireEditingCanceled() {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == CellEditorListener.class) {
// Lazily create the event:
if (changeEvent == null) {
changeEvent = new ChangeEvent(this);
}
((CellEditorListener) listeners[i + 1]).editingCanceled(changeEvent);
}
}
}
}
public ButtonsRenderer br() {
return new ButtonsRenderer();
}
public ButtonsEditor be(JTable jTable, String tableName) {
return new ButtonsEditor(jTable, tableName);
}
}
a) it's better not to call a Jbutton in the name Jbutton, it's just confusing
b) there are many way to disable a jbutton (make it disappear, remove it, resize it...) but the best one is probably this:
Jbutton.setEnabled(false);
c) I think you can use this very useful guide: http://www.macs.hw.ac.uk/guidebook/?name=JButton&page=1
I'm using GlazedLists' AutoCompleteSupport to wrap a JComboBox used as cell editor for a JTable and am facing a problem to get selectedItem when I type a value in the editor that is not in the model.
The problem appears inside the stopCellEditing method, after you type something in the ComboBox that is not in the list. Even if something was typed in the editor, when invoking getItem() from stopCellEditing, null will be returned. Please see like 65 from the code below.
I would like to get the item from the editor to be able to add it to the ComboBox model.
import ca.odell.glazedlists.GlazedLists;
import ca.odell.glazedlists.TextFilterator;
import ca.odell.glazedlists.swing.AutoCompleteSupport;
import java.awt.Component;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParsePosition;
import java.util.HashMap;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
public class TestComboBoxGlazedLists {
public static void main(String[] args) {
TestComboBoxGlazedLists test = new TestComboBoxGlazedLists();
test.go();
}
public void go() {
//create the frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// create and add a tabbed pane to the frame
JTabbedPane tabbedPane = new JTabbedPane();
frame.getContentPane().add(tabbedPane);
//create a table and add it to a scroll pane in a new tab
JTable table = new JTable(new DefaultTableModel(new Object[]{"A", "B"}, 5));
JScrollPane scrollPane = new JScrollPane(table);
tabbedPane.addTab("test", scrollPane);
// create a simple JComboBox and set is as table cell editor on column A
TestComboBoxGlazedLists.UserRepository rep = new TestComboBoxGlazedLists.UserRepository();
TestComboBoxGlazedLists.UserInfo[] comboElements = rep.getAllUsers();
DefaultComboBoxModel model = new DefaultComboBoxModel(comboElements);
JComboBox comboBox = new JComboBox(model);
// GlazedLists
DefaultCellEditor cellEditor = new DefaultCellEditor(comboBox) {
private Object originalValue;
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
originalValue = value;
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
#Override
public boolean stopCellEditing() {
JComboBox comboBox = (JComboBox) getComponent();
ComboBoxModel comboModel = comboBox.getModel();
// this value is null when the selected item is not from the list
Object editingValue = getCellEditorValue();
// Needed because your TableModel is empty
if (editingValue == null) {
return super.stopCellEditing();
}
int selectedIndex = -1;
int modelSize = comboModel.getSize();
for (int i = 0; i < modelSize; i++) {
if (editingValue.equals(comboModel.getElementAt(i))) {
selectedIndex = i;
}
}
// Selecting item from model
if (!(selectedIndex == -1)) {
return super.stopCellEditing();
}
if (!(editingValue instanceof TestComboBoxGlazedLists.UserInfo)) {
// Confirm addition of new value
int result = JOptionPane.showConfirmDialog(
comboBox.getParent(),
"Add (" + editingValue + ") to table?",
"Update Model",
JOptionPane.YES_NO_OPTION);
if (result == JOptionPane.YES_OPTION) {
TestComboBoxGlazedLists.UserInfo newUser = new TestComboBoxGlazedLists.UserInfo(editingValue.toString(), null);
comboBox.addItem(newUser);
comboBox.setSelectedItem(newUser);
return super.stopCellEditing();
}
}
return false;
}
};
// needs to be invoked from Event Dispatch Thread
SwingUtilities.invokeLater(new TestComboBoxGlazedLists.AutocompleteComboRunnable(table, comboBox));
// end GlazedLists
table.getColumn("A").setCellEditor(cellEditor);
table.getColumn("A").setCellRenderer(new TestComboBoxGlazedLists.CustomTableCellRenderer());
// pack and show frame
frame.pack();
frame.setVisible(true);
}
public class AutocompleteComboRunnable implements Runnable {
private JTable mTable;
private JComboBox mComboBox;
public AutocompleteComboRunnable(JTable table, JComboBox comboBox) {
mTable = table;
mComboBox = comboBox;
}
#Override
public void run() {
TextFilterator textFilterator = GlazedLists.textFilterator("firstName");
// ComboBoxCellEditor cellEditor = new ComboBoxCellEditor(comboBox);
TestComboBoxGlazedLists.UserRepository rep = new TestComboBoxGlazedLists.UserRepository();
AutoCompleteSupport support = AutoCompleteSupport.install(mComboBox,
GlazedLists.eventListOf(rep.getAllUsers()),
textFilterator,
new TestComboBoxGlazedLists.UserInfoFormat());
support.setStrict(false);
}
}
public class CustomTableCellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (value != null) {
// this is used to extract the data you want to display in the table from your "custom model"
TestComboBoxGlazedLists.UserInfo user = (TestComboBoxGlazedLists.UserInfo) value;
return super.getTableCellRendererComponent(table, user.getFirstName(), isSelected, hasFocus, row, column);
} else {
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}
public class UserInfo {
private String firstName;
private String lastName;
public UserInfo(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
public class UserRepository {
TestComboBoxGlazedLists.UserInfo[] comboElements;
HashMap<String, TestComboBoxGlazedLists.UserInfo> objectsMap;
public UserRepository() {
comboElements = new TestComboBoxGlazedLists.UserInfo[5];
comboElements[0] = new TestComboBoxGlazedLists.UserInfo("John", "Doe");
comboElements[1] = new TestComboBoxGlazedLists.UserInfo("Betty", "Doe");
comboElements[2] = new TestComboBoxGlazedLists.UserInfo("Elenor", "Smith");
comboElements[3] = new TestComboBoxGlazedLists.UserInfo("Helen", "Kelly");
comboElements[4] = new TestComboBoxGlazedLists.UserInfo("Joe", "Black");
objectsMap = new HashMap<>();
for (int i = 0; i < 5; i++) {
objectsMap.put(comboElements[i].getFirstName(), comboElements[i]);
}
}
public TestComboBoxGlazedLists.UserInfo getUserInfo(String name) {
return objectsMap.get(name);
}
public TestComboBoxGlazedLists.UserInfo[] getAllUsers() {
return comboElements;
}
}
private class UserInfoFormat extends Format {
#Override
public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
if (obj != null) {
toAppendTo.append(((TestComboBoxGlazedLists.UserInfo) obj).getFirstName());
}
return toAppendTo;
}
#Override
public Object parseObject(String source, ParsePosition pos) {
TestComboBoxGlazedLists.UserRepository rep = new TestComboBoxGlazedLists.UserRepository();
return rep.getUserInfo(source.substring(pos.getIndex()));
}
}
}
I have added the following JTable.
public final class EmployeeApp extends JPanel implements ActionListener, TableModelListener
{
private static JTable myTable;
private static JButton btnDelete;
public EmployeeApp()
{
CountryDAO countryDAO=new CountryDAO();
myTable = new JTable(new CountryAbstractTableModel(countryDAO.getList()));
JScrollPane myPane = new JScrollPane(myTable, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
add(myPane);
myTable.setPreferredScrollableViewportSize(new Dimension(1000, 200));
((CountryAbstractTableModel)myTable.getModel()).addTableModelListener(this);//<---
//Added TableModelListener.
}
#Override
public void tableChanged(TableModelEvent e)
{
int row = e.getFirstRow();
int column = e.getColumn();
CountryAbstractTableModel model = (CountryAbstractTableModel)e.getSource();
Object data = model.getValueAt(row, column);
System.out.println("The tableChanged() method called."); // This is never be seen on the console.
}
}
When a cell is edited, the tableChanged() method should be invoked but it never gets called.
I have extended AbstractTableModel as follows.
package admin.model;
import entity.Country;
import java.util.Iterator;
import java.util.List;
import javax.swing.table.AbstractTableModel;
public final class CountryAbstractTableModel extends AbstractTableModel
{
private List<Country> countries;
public CountryAbstractTableModel(List<Country> countries)
{
this.countries = countries;
}
#Override
public void setValueAt(Object value, int rowIndex, int columnIndex)
{
if(value instanceof Country)
{
Country newCountry=(Country) value;
Country oldCountry = countries.get(rowIndex);
switch (columnIndex)
{
case 2:
oldCountry.setCountryName(newCountry.getCountryName());
break;
case 3:
oldCountry.setCountryCode(newCountry.getCountryCode());
//break;
}
fireTableCellUpdated(rowIndex, columnIndex);
}
}
#Override
public Object getValueAt(int rowIndex, int columnIndex)
{
Country country = countries.get(rowIndex);
switch (columnIndex)
{
case 0:
return rowIndex+1;
case 1:
return country.getCountryId();
case 2:
return country.getCountryName();
case 3:
return country.getCountryCode();
}
return "";
}
#Override
public int getRowCount()
{
return countries.size();
}
#Override
public int getColumnCount()
{
return 4;
}
public void add(Country country)
{
int size = countries.size();
countries.add(country);
fireTableRowsInserted(size, size);
}
public void remove(List<Long>list)
{
Iterator<Country> iterator = countries.iterator();
while(iterator.hasNext())
{
Country country = iterator.next();
Iterator<Long> it = list.iterator();
while(it.hasNext())
{
if(country.getCountryId().equals(it.next()))
{
iterator.remove();
int index = countries.indexOf(country);
fireTableRowsDeleted(index, index);
break;
}
}
}
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex)
{
return columnIndex>1?true:false;
}
}
In which the setValueAt() method is called when the return key is pressed after editing a cell. Therefore, the tableChanged() method should be called after fireTableCellUpdated() gets called.
Since the first two columns are not editable, there is no need to set the values for them.
Why isn't the tableChanged() method invoked?
Unless you have specifically set a dedicated Country editor for that column, your test value instanceof Country is likely to be false. Most likely value is actually a String. Your setValueAt method should rather look like this:
#Override
public void setValueAt(Object value, int rowIndex, int columnIndex)
{
if(value instanceof String)
{
Country country = countries.get(rowIndex);
String newValue = (String) value;
switch (columnIndex)
{
case 2:
country.setCountryName(newValue); break;
case 3:
country.setCountryCode(newValue); break;
}
fireTableCellUpdated(rowIndex, columnIndex);
}
}
Of course, if the type of countryName and countryCode is not String, you should return appropriate values for the method TableModel.getColumnClass and test for appropriate types in setValueAt
Want to change color of only leaf of tree on one particular condition.
if (l_sel_node_object.getIsEnabled().trim().equalsIgnoreCase("N"))
defaultTreeCellRenderer.setBackgroundSelectionColor(Color.red);
but it is changing background of each selected node.Can anyone please help me out.
Only tested on Metal Look and Feel:
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
public class MainPanel {
public JPanel makeUI() {
JTree tree = new JTree();
tree.setCellRenderer(new RedTreeCellRenderer());
JPanel p = new JPanel(new BorderLayout(5, 5));
p.add(new JScrollPane(tree));
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 MainPanel().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
//*
class RedTreeCellRenderer extends DefaultTreeCellRenderer {
#Override public Component getTreeCellRendererComponent(
JTree tree, Object value, boolean isSelected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
JComponent c = (JComponent)super.getTreeCellRendererComponent(
tree, value, isSelected, expanded, leaf, row, hasFocus);
if(isSelected) {
c.setForeground(getTextSelectionColor());
if (leaf && value.toString().equalsIgnoreCase("red")) {
//<strong>
c.setOpaque(true);
//</strong>
c.setBackground(Color.RED);
} else {
c.setOpaque(false);
c.setBackground(getBackgroundSelectionColor());
}
} else {
c.setOpaque(false);
c.setForeground(getTextNonSelectionColor());
c.setBackground(getBackgroundNonSelectionColor());
}
return c;
}
}
/*/
class RedTreeCellRenderer2 extends DefaultTreeCellRenderer {
#Override public Component getTreeCellRendererComponent(
JTree tree, Object value, boolean isSelected,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
JComponent c = (JComponent)super.getTreeCellRendererComponent(
tree, value, isSelected, expanded, leaf, row, hasFocus);
if(isSelected) {
if(leaf) {
setParticularCondition(value.toString());
}
c.setForeground(getTextSelectionColor());
c.setBackground(getBackgroundSelectionColor());
} else {
c.setForeground(getTextNonSelectionColor());
c.setBackground(getBackgroundNonSelectionColor());
}
return c;
}
boolean particularCondition = false;
private void setParticularCondition(String str) {
particularCondition = str.equalsIgnoreCase("red");
}
#Override public Color getBackgroundSelectionColor() {
if(particularCondition) return Color.RED;
else return super.getBackgroundSelectionColor();
}
}
//*/