I'm very new to programming, and I can't add JCheckbox to the JList. There is no error but nothing is displayed.
JFrame f=new JFrame();
String[] labels={"a","b","c","d","e"};
JCheckBox[] ch=new JCheckBox[labels.length];
JList list=new JList();
for (int i = 0; i < labels.length; i++) {
ch[i]=new JCheckBox("CheckBox"+i);
list.add(ch[i]);
}
JScrollPane pane=new JScrollPane(list);
f.add(pane);
f.setVisible(true);
As an alternative to the JTable solution that trashgod posted, you can also create the appearance of JCheckBoxes in a JList by:
Use a custom renderer for your JList that will show each item as a JCheckBox
Use a custom object in your JList that maintains it's boolean "checked" state
Add a MouseListener to the JList that will set/unset the checked state of each item.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class JCheckBoxListDemo implements Runnable
{
private JList jlist;
public static void main(String args[])
{
SwingUtilities.invokeLater(new JCheckBoxListDemo());
}
public void run()
{
Object[] items = new CheckListItem[] {
new CheckListItem("Apple"),
new CheckListItem("Banana"),
new CheckListItem("Carrot"),
new CheckListItem("Date"),
new CheckListItem("Eggplant"),
new CheckListItem("Fig"),
new CheckListItem("Guava"),
};
jlist = new JList(items);
jlist.setCellRenderer(new CheckBoxListRenderer());
jlist.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
jlist.setVisibleRowCount(5);
jlist.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent event)
{
selectItem(event.getPoint());
}
});
KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0);
Object mapKey = keyStroke.toString();
jlist.getInputMap().put(keyStroke, mapKey);
jlist.getActionMap().put(mapKey, new AbstractAction()
{
public void actionPerformed(ActionEvent event)
{
toggleSelectedItem();
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(jlist));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private void selectItem(Point point)
{
int index = jlist.locationToIndex(point);
if (index >= 0)
{
CheckListItem item = (CheckListItem)jlist.getModel().getElementAt(index);
item.setSelected(!item.isSelected());
jlist.repaint(jlist.getCellBounds(index, index));
}
}
private void toggleSelectedItem()
{
int index = jlist.getSelectedIndex();
if (index >= 0)
{
CheckListItem item = (CheckListItem)jlist.getModel().getElementAt(index);
item.setSelected(!item.isSelected());
jlist.repaint(jlist.getCellBounds(index, index));
}
}
private class CheckListItem
{
private Object item;
private boolean selected;
public CheckListItem(Object item)
{
this.item = item;
}
#SuppressWarnings("unused")
public Object getItem()
{
return item;
}
public boolean isSelected()
{
return selected;
}
public void setSelected(boolean isSelected)
{
this.selected = isSelected;
}
#Override
public String toString()
{
return item.toString();
}
}
private class CheckBoxListRenderer extends JCheckBox
implements ListCellRenderer
{
public Component getListCellRendererComponent(JList comp, Object value,
int index, boolean isSelected, boolean hasFocus)
{
setEnabled(comp.isEnabled());
setSelected(((CheckListItem) value).isSelected());
setFont(comp.getFont());
setText(value.toString());
if (isSelected)
{
setBackground(comp.getSelectionBackground());
setForeground(comp.getSelectionForeground());
}
else
{
setBackground(comp.getBackground());
setForeground(comp.getForeground());
}
return this;
}
}
}
A JList renderer can draw a checkbox, but JList does not support a cell editor. Instead, consider a one-column JTable. The default renderer & editor for a column of type Boolean.class is a JCheckBox, for example.
Here is what you might be looking for:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class CheckBo
{
public static void main(String[] args)
{
JFrame f=new JFrame();
String[]labels={"a","b","c","d","e"};
JCheckBox[]ch=new JCheckBox[labels.length];
final DefaultListModel model = new DefaultListModel();
JList list=new JList(model);
list.setCellRenderer(new CheckListRenderer());
for (int i = 0; i < labels.length; i++) {
//ch[i]=new JCheckBox("CheckBox"+i);
model.addElement(new CheckListItem("CheckBox"+i));
}
JScrollPane pane=new JScrollPane(list);
list.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent event)
{
JList list = (JList) event.getSource();
// Get index of item clicked
int index = list.locationToIndex(event.getPoint());
CheckListItem item = (CheckListItem)
list.getModel().getElementAt(index);
// Toggle selected state
item.setSelected(! item.isSelected());
// Repaint cell
list.repaint(list.getCellBounds(index, index));
}
});
f.add(pane);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
static class CheckListItem
{
private String label;
private boolean isSelected = false;
public CheckListItem(String label)
{
this.label = label;
}
public boolean isSelected()
{
return isSelected;
}
public void setSelected(boolean isSelected)
{
this.isSelected = isSelected;
}
public String toString()
{
return label;
}
}
static class CheckListRenderer extends JCheckBox implements ListCellRenderer
{
public Component getListCellRendererComponent(JList list, Object value, int index,boolean isSelected, boolean hasFocus)
{
setEnabled(list.isEnabled());
setSelected(((CheckListItem)value).isSelected());
setFont(list.getFont());
setBackground(list.getBackground());
setForeground(list.getForeground());
setText(value.toString());
return this;
}
}
}
Source for above code is this
Related
import java.awt.*;
import java.awt.event.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.table.*;
public class TableButtonCell extends JFrame {
private JPanel topPanel;
private JTable table;
public TableButtonCell() {
setTitle("JButton in JTable");
setSize(300,150);
topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
getContentPane().add(topPanel);
String [] columns = new String[] {"Text", "Button"};
String[][] data = new String[][]{
{"Line 1", ""},
{"Line 2", ""},
{"Line 3", ""}};
DefaultTableModel model = new DefaultTableModel(data,columns);
table = new JTable();
table.setModel(model);
table.getColumn("Button").setCellRenderer(new ButtonRenderer());
table.getColumn("Button").setCellEditor(new ButtonEditor());
JScrollPane scrollPane = new JScrollPane(table);
topPanel.add(scrollPane,BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
class ButtonRenderer extends JButton implements TableCellRenderer {
public ButtonRenderer() {
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setText((value == null) ? "Modify" : value.toString());
return this;
}
}
class ButtonEditor extends JButton implements TableCellEditor {
public ButtonEditor() {
JPopupMenu popup = new JPopupMenu();
JMenuItem item = new JMenuItem("Menu action 1");
item.addActionListener(this::menuAction);
item = new JMenuItem("Menu action 2");
item.addActionListener(this::menuAction);
setComponentPopupMenu(popup);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(null,"JButton clicked");
}
});
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
return this;
}
public Object getCellEditorValue() {
return null;
}
public void menuAction(ActionEvent ev) {
JOptionPane.showMessageDialog(null,"JButton clicked");
}
#Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
// TODO Auto-generated method stub
return false;
}
#Override
public boolean stopCellEditing() {
return true;
}
#Override
public void cancelCellEditing() {
}
#Override
public void addCellEditorListener(CellEditorListener l) {
}
#Override
public void removeCellEditorListener(CellEditorListener l) {
}
}
public static void main(String args[]) {
TableButtonCell f = new TableButtonCell();
f.setVisible(true);
}
}
The SSCE above creates a JTable with JButton as cell renderer/editor.
It's working fine & button action is triggered correclty
When trying to add a popup menu to the JButton, the menu is not shown when clicking mouse right button.
Looks like the table is consuming the Mouse right click event, so the JButton didn't receive & react to the event ?
Any clue ?
Thanks in advance for any guidance/help
Now it's working with the following code. Hope this may help some one else.
import java.awt.*;
import java.awt.event.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.table.*;
public class TableButtonCell extends JFrame {
private JPanel topPanel;
private JTable table;
public TableButtonCell() {
setTitle("JButton in JTable");
setSize(300,150);
topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
getContentPane().add(topPanel);
String [] columns = new String[] {"Text", "Button"};
String[][] data = new String[][]{
{"Line 1", "Button 1"},
{"Line 2", "Button 2"},
{"Line 3", "Button 3"},
{"Line 4", "Button 4"}};
DefaultTableModel model = new DefaultTableModel(data,columns);
table = new JTable();
table.setModel(model);
ButtonRendererEditor renderer = new ButtonRendererEditor(table, 1);
TableColumn tc = table.getColumn("Button");
tc.setCellRenderer(renderer);
tc.setCellEditor(renderer);
JScrollPane scrollPane = new JScrollPane(table);
topPanel.add(scrollPane,BorderLayout.CENTER);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
class ButtonRendererEditor extends JButton implements TableCellRenderer, TableCellEditor {
int column;
public ButtonRendererEditor(JTable table, int column) {
this.column = column;
JPopupMenu popup = new JPopupMenu();
JMenuItem item = new JMenuItem("Menu action 1");
item.addActionListener(this::menuAction);
popup.add(item);
item = new JMenuItem("Menu action 2");
item.addActionListener(this::menuAction);
popup.add(item);
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
JOptionPane.showMessageDialog(null,"JButton clicked");
}
});
table.addMouseListener( new MouseAdapter() {
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
if (!e.isPopupTrigger())
return;
JTable source = (JTable)e.getSource();
int col = source.columnAtPoint(e.getPoint());
if (col != column)
return;
popup.show(e.getComponent(), e.getX(), e.getY());
}
});
}
public void menuAction(ActionEvent ev) {
JOptionPane.showMessageDialog(null,"Menu item clicked");
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setText((value == null) ? "" : value.toString());
return this;
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
setText((value == null) ? "" : value.toString());
return this;
}
public Object getCellEditorValue() {
return null;
}
#Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
#Override
public boolean stopCellEditing() {
return true;
}
#Override
public void cancelCellEditing() {
}
#Override
public void addCellEditorListener(CellEditorListener l) {
}
#Override
public void removeCellEditorListener(CellEditorListener l) {
}
}
public static void main(String args[]) {
TableButtonCell f = new TableButtonCell();
f.setVisible(true);
}
}
I am dynamically creating JTextField based on click event on '+' button. Below is screen shot.
The problem is when I click '+' button, fields created but not shown on JFrame. When I put the cursor on next row under 'item Name', text field becomes visible.
Where is the problem?
Below is my code.
CreateBill()
{
jf = new JFrame("Create Bill");
jf.getContentPane().setLayout(null);
jf.setExtendedState(JFrame.MAXIMIZED_BOTH);
jf.setBounds(0, 0, d1.width, d1.height);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createRow(); // This will create first row by default.
jf.pack();
jf.setVisible(true);
}
private void createRow() {
textField = new JTextField();
textField.setToolTipText("item name");
textField.setBounds(143, 46+j, 288, 20);
textField.setColumns(10);
textField.getDocument().addDocumentListener(new DocumentListener()
{
#Override
public void insertUpdate(DocumentEvent e) {
updatePrice();
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
updatePrice();
}
});
AutoCompleteDecorator.decorate(textField, names, true);
jf.getContentPane().add(comboComplete);
jf.getContentPane().add(textField);
comboComplete.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e)
{
String ItemSel = textField.getText().trim();
for(Item s:items)
{
if(s.getItemName().equals(ItemSel))
{
textField_1.setText(String.valueOf(s.getUnitPrice()));
}
}
}
});
textFields.add(textField);
textField_1 = new JTextField();
textField_1.setEditable(false);
textField_1.setBounds(639, 46+j, 175, 20);
jf.getContentPane().add(textField_1);
textField_1.setColumns(10);
qty = new JTextField();
qty.setBounds(455, 46+j, 156, 20);
jf.getContentPane().add(qty);
qty.setColumns(10);
qty.getDocument().addDocumentListener(new DocumentListener()
{
#Override
public void insertUpdate(DocumentEvent e) {
getTotal();
}
#Override
public void removeUpdate(DocumentEvent e) {
}
#Override
public void changedUpdate(DocumentEvent e) {
getTotal();
}
});
textFields.add(qty);
textFields.add(textField_1);
textField_3 = new JTextField();
textField_3.setEditable(false);
textField_3.setBounds(1038, 46+j, 156, 20);
jf.getContentPane().add(textField_3);
textField_3.setColumns(10);
textFields.add(textField_3);
JButton button = new JButton("+");
button.setBounds(1235, 45+j, 89, 23);
jf.getContentPane().add(button);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("value of J"+j);
createRow(); // after pressing '+' button i am calling same method again. by changing value of j.
}
});
j=j+22;
jf.setVisible(true);
}
I want my all 4 text fields appear simultaneously.
You need to call repaint() on the container after adding a component to it. You also should call revalidate() too, before calling repaint, since this tells the layout managers to layout the new component, but you're using null layouts, something that you really want to avoid doing.
So my suggestion is to either 1) use nested JPanels with appropriate layout managers, and call revalidate and repaint on your containers after adding or removing components, or 2) yeah, use a Cardlayout to swap views as Andrew Thompson astutely recommends. You can have your second JPanel have a JTextField that uses the same Document as the previous JPanel, so it looks like both are using the same JTextField (as the top JTextField).
On looking further at your images, I have to wonder if a JTable might be an even better solution overall. And yeah, after you start using the layout managers, do also call pack() on your top level window after adding all components and before setting it visible.
For an example of a JTable implementation of this, something along the lines of...
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
#SuppressWarnings("serial")
public class CreateRowGui extends JPanel {
private static final Item[] ITEMS = {
new Item("Light Bulb", 2.00),
new Item("Toilet Paper", 3.00),
new Item("Toothpaste", 1.50),
new Item("Aspirin", 3.75) };
private ItemTableModel tableModel = new ItemTableModel();
private JTable table = new JTable(tableModel);
private AddRowAction addRowAction = new AddRowAction("Add Row", KeyEvent.VK_A);
public CreateRowGui() {
TableCellRenderer moneyRenderer = new DefaultTableCellRenderer() {
private NumberFormat currFormat = NumberFormat.getCurrencyInstance();
#Override
protected void setValue(Object value) {
if (value != null) {
value = currFormat.format(value);
}
super.setValue(value);
}
};
table.getColumnModel().getColumn(2).setCellRenderer(moneyRenderer);
table.getColumnModel().getColumn(3).setCellRenderer(moneyRenderer);
JPanel btnPanel = new JPanel();
btnPanel.add(new JButton(addRowAction));
btnPanel.add(new JButton("Remove Row")); // TODO: need Action for this
setLayout(new BorderLayout());
add(new JScrollPane(table));
add(btnPanel, BorderLayout.PAGE_END);
}
class AddRowAction extends AbstractAction {
private NewRowPanel newRowPanel = new NewRowPanel(ITEMS);
public AddRowAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
newRowPanel.reset();
int reply = JOptionPane.showConfirmDialog(table,
newRowPanel.getMainPanel(),
"Select Item and Quantity",
JOptionPane.OK_CANCEL_OPTION,
JOptionPane.PLAIN_MESSAGE);
if (reply == JOptionPane.OK_OPTION) {
Item item = newRowPanel.getSelectedItem();
int quantity = newRowPanel.getQuantity();
tableModel.addRow(item, quantity);
}
}
}
private static void createAndShowGui() {
JFrame frame = new JFrame("CreateRowGui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new CreateRowGui());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class NewRowPanel {
private JPanel mainPanel = new JPanel();
private JComboBox<Item> itemsCombo;
private JSpinner quantitySpinner = new JSpinner(new SpinnerNumberModel(0, 0, 20, 1));
#SuppressWarnings("serial")
public NewRowPanel(Item[] items) {
itemsCombo = new JComboBox<>(items);
itemsCombo.setRenderer(new DefaultListCellRenderer(){
#Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
if (value != null) {
value = ((Item) value).getName();
} else {
value = "";
}
return super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
}
});
mainPanel.add(new JLabel("Item:"));
mainPanel.add(itemsCombo);
mainPanel.add(Box.createHorizontalStrut(15));
mainPanel.add(new JLabel("Quantity"));
mainPanel.add(quantitySpinner);
}
public void reset() {
itemsCombo.setSelectedIndex(-1);
quantitySpinner.setValue(0);
}
public JPanel getMainPanel() {
return mainPanel;
}
public Item getSelectedItem() {
return (Item) itemsCombo.getSelectedItem();
}
public int getQuantity() {
return (int) quantitySpinner.getValue();
}
}
class ItemTableModel extends AbstractTableModel {
private static final String[] COL_NAMES = { "Item Name", "Quantity", "Unit Price", "Total" };
private static final long serialVersionUID = 1L;
private List<ItemWithCount> itemsWithCount = new ArrayList<>();
#Override
public int getColumnCount() {
return 4;
}
#Override
public int getRowCount() {
return itemsWithCount.size();
}
#Override
public Class<?> getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return super.getColumnClass(columnIndex);
case 1:
return Integer.class;
case 2:
case 3:
return Double.class;
}
return super.getColumnClass(columnIndex);
}
#Override
public String getColumnName(int column) {
return COL_NAMES[column];
}
#Override
public Object getValueAt(int row, int column) {
ItemWithCount itemWithCount = itemsWithCount.get(row);
switch (column) {
case 0:
return itemWithCount.getItem().getName();
case 1:
return itemWithCount.getCount();
case 2:
return itemWithCount.getItem().getUnitPrice();
case 3:
return itemWithCount.getCount() * itemWithCount.getItem().getUnitPrice();
}
return null;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
ItemWithCount itemWithCount = itemsWithCount.get(rowIndex);
switch (columnIndex) {
case 1:
itemWithCount.setCount((int) aValue);
fireTableRowsUpdated(rowIndex, rowIndex);
break;
default:
break;
}
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 0 || columnIndex == 1;
}
public void addRow(Item item, int quantity) {
ItemWithCount itemWithCount = new ItemWithCount(item, quantity);
itemsWithCount.add(itemWithCount);
int row = itemsWithCount.size() - 1;
fireTableRowsInserted(row, row);
}
private class ItemWithCount {
private Item item;
private int count;
public ItemWithCount(Item item, int count) {
this.item = item;
this.count = count;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public Item getItem() {
return item;
}
}
}
class Item {
private String name;
private double unitPrice;
public Item(String name, double unitPrice) {
this.name = name;
this.unitPrice = unitPrice;
}
public String getName() {
return name;
}
public double getUnitPrice() {
return unitPrice;
}
public void setUnitPrice(double unitPrice) {
this.unitPrice = unitPrice;
}
#Override
public String toString() {
return "Item [name=" + name + ", unitPrice=" + unitPrice + "]";
}
}
I need a Jtable having Add Button on the header.When add is clicked..then it must add a row containing 4 columns of 3 textfields and delete button. When delete button is clicked, then the corresponding row should deleted.. Thanks in advance..
public class UserTableInfo {
private JFrame frame;
private JTable CompTable = null;
private PanelTableModel CompModel = null;
private JButton delButton=null;
private JButton button=null;
public static void main(String args[]) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception fail) {
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new UserTableInfo().makeUI();
}
}); }
public void makeUI() {
CompTable = CreateCompTable();
JScrollPane CompTableScrollpane = new JScrollPane(CompTable,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JPanel bottomPanel = CreateBottomPanel();
frame = new JFrame("Comp Table Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(CompTableScrollpane, BorderLayout.CENTER);
frame.add(bottomPanel, BorderLayout.SOUTH);
frame.setPreferredSize(new Dimension(800, 400));
frame.setLocation(150, 150);
frame.pack();
frame.setVisible(true);
}public JTable CreateCompTable() {
CompModel = new PanelTableModel();
button=new JButton("Add Row");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
CompModel.addRow();
}
});
JTable table = new JTable(CompModel);
table.setRowHeight(new CompCellPanel().getPreferredSize().height);
JTableHeader header = table.getTableHeader();
header.setLayout(new FlowLayout(FlowLayout.TRAILING, 5, 0));
header.add(button);
PanelCellEditorRenderer PanelCellEditorRenderer = new
PanelCellEditorRenderer();
table.setDefaultRenderer(Object.class, PanelCellEditorRenderer);
table.setDefaultEditor(Object.class, PanelCellEditorRenderer);
return table;
} public JPanel CreateBottomPanel() {
delButton=new JButton("Exit");
delButton.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae) {
Object source = ae.getSource();
if (source == delButton) {
System.exit(1);
}
}
}); JPanel panel = new JPanel(new GridBagLayout());
panel.add(delButton);
return panel;
}
}
class PanelCellEditorRenderer extends AbstractCellEditor implements
TableCellRenderer, TableCellEditor {
private static final long serialVersionUID = 1L;
private CompCellPanel renderer = new CompCellPanel();
private CompCellPanel editor = new CompCellPanel();
#Override
public Component getTableCellRendererComponent(JTable table, Object
value, boolean isSelected, boolean hasFocus, int row, int column) {
renderer.setComp((Comp) value);
return renderer;
}
#Override
public Component getTableCellEditorComponent(JTable table, Object
value, boolean isSelected, int row, int column) {
editor.setComp((Comp) value);
return editor;
}
#Override
public Object getCellEditorValue() {
return null;
}
#Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
#Override
public boolean shouldSelectCell(EventObject anEvent) {
return false;
}
}
class PanelTableModel extends DefaultTableModel {
private static final long serialVersionUID = 1L;
#Override
public int getColumnCount() {
return 1;
}
public void addRow() {
super.addRow(new Object[]{new Comp("")});
}
}
class Comp {
public String upper;
public Comp(String upper) {
this.upper = upper;
}
}
class CompCellPanel extends JPanel {
private static final long serialVersionUID = 1L;
private JLabel label = new JLabel();
private JTextField upperField = new JTextField();
private JButton removeButton = new JButton("remove");
CompCellPanel() {
setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
removeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JTable table = (JTable)
SwingUtilities.getAncestorOfClass(JTable.class, (Component) e.getSource());
int row = table.getEditingRow();
table.getCellEditor().stopCellEditing();
((DefaultTableModel) table.getModel()).removeRow(row);
} });
upperField.setMaximumSize(new Dimension(Integer.MAX_VALUE, upperField.getPreferredSize().height) );
add(upperField);
label.setMaximumSize(getMaximumSize());
add(label);
add(Box.createHorizontalStrut(10));
add(removeButton);
}
public void setComp(Comp Comp) {
upperField.setText(Comp.upper);
} }
This is much easier if you extend a AbstractTableModel and use that to display your data. You can make an ArrayList of your data and add/remove from that. The TableModel will update the Table automatically when the ArrayList is changed. The ArrayList contains a class which has all the data that you would have in a row. See the Java Tutorials example from Oracle: http://docs.oracle.com/javase/tutorial/displayCode.html?code=http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableDemoProject/src/components/TableDemo.java
For custom cells, you can detect from the TableModel which column the cell is in and update its content accordingly.
I am creating one form which contain table and some buttons.
A picture is worth a thousand words:
How can I get the checkbox and comboboxes into the table?
I am using NetBeans. I tried using drag and drop but didn't work.
Here is my form code.
public class HttpOutput extends javax.swing.JPanel {
HttpElements current_Http_EleObject;
/**
* Creates new form HttpOutput
*/
public HttpOutput(HttpElements httpelements) {
initComponents();
current_Http_EleObject=httpelements;
TableColumn includeColumn = jTable1.getColumnModel().getColumn(0);
includeColumn.setCellEditor(new DefaultCellEditor(new JCheckBox()));
}
Here is combo cell insets replicate demo:
import java.awt.*;
import java.awt.event.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class ComboCellInsetsDemo {
public JComponent makeUI() {
String[] columnNames = {"Name", "Check", "Condition"};
Object[][] data = {
{"bbb", false, "="}, {"aaa", true, "<"}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames) {
#Override public Class<?> getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
JTable table = new JTable(model);
table.setRowHeight(36);
table.setAutoCreateRowSorter(true);
TableColumn column = table.getColumnModel().getColumn(2);
column.setCellRenderer(new ComboBoxCellRenderer());
column.setCellEditor(new ComboBoxCellEditor());
return new JScrollPane(table);
}
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 ComboCellInsetsDemo().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class ComboBoxPanel extends JPanel {
private String[] m = new String[] {">", "<", "=", "<="};
protected JComboBox<String> comboBox = new JComboBox<String>(m) {
#Override public Dimension getPreferredSize() {
Dimension d = super.getPreferredSize();
return new Dimension(40, d.height);
}
};
public ComboBoxPanel() {
super();
setOpaque(true);
comboBox.setEditable(true);
add(comboBox);
}
}
class ComboBoxCellRenderer extends ComboBoxPanel
implements TableCellRenderer {
public ComboBoxCellRenderer() {
super();
setName("Table.cellRenderer");
}
#Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
setBackground(isSelected?table.getSelectionBackground()
:table.getBackground());
if(value!=null) {
comboBox.setSelectedItem(value);
}
return this;
}
}
class ComboBoxCellEditor extends ComboBoxPanel
implements TableCellEditor {
public ComboBoxCellEditor() {
super();
comboBox.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent e) {
fireEditingStopped();
}
});
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());
comboBox.setSelectedItem(value);
return this;
}
//Copid from DefaultCellEditor.EditorDelegate
#Override public Object getCellEditorValue() {
return comboBox.getSelectedItem();
}
#Override public boolean shouldSelectCell(EventObject anEvent) {
if(anEvent instanceof MouseEvent) {
MouseEvent e = (MouseEvent)anEvent;
return e.getID() != MouseEvent.MOUSE_DRAGGED;
}
return true;
}
#Override public boolean stopCellEditing() {
if(comboBox.isEditable()) {
comboBox.actionPerformed(new ActionEvent(this, 0, ""));
}
fireEditingStopped();
return true;
}
//Copid from AbstractCellEditor
//protected EventListenerList listenerList = new EventListenerList();
transient protected ChangeEvent changeEvent = null;
#Override public boolean isCellEditable(EventObject e) {
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);
}
}
}
}
includeColumn.setCellEditor(new DefaultCellEditor(new JCheckBox()));
there no reason to use or write Renderer and Editor for JCheckBox in the JTable, put there true / false, because JTable has built_in support for JCheckbox as Renderer and Editor too
override proper column, returns Boolean.Class
for JComboBox to read Using a Combo Box as an Editor
every data are stored in XxxTableModel, and by using DefaultTableModel are events automatically displayed in the JTables view
all updates to the XxxTableModel must be done on Event Dispatch Thread
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);
}
});
}
}