Java JList refresh only after minimized or maximized - java

I have a JList connected to a collection.
When collection change, I need the JList to be automatically refreshed. But I can see that my JList will refresh only after I minimized (or maximized) the JFrame.
Why?
I'm new with Java and I'm trying to learn.
I have this collection for the list model:
public class UserCollection extends Vector<User> implements ListModel{
private static final long serialVersionUID = 2668410577023194442L;
#Override
public void addListDataListener(ListDataListener arg0) {
System.out.println("add list! --- " +arg0.toString());
}
#Override
public Object getElementAt(int index) {
return this.get(index).getName();
}
#Override
public int getSize() {
return(this.elementCount);
}
#Override
public void removeListDataListener(ListDataListener arg0) {}
}
In another class, I populate the collection with userList.add(u1); or userList.remove(u1);
In the JFrame class I have:
JList list = new JList();
list.setModel(xmppManager.userList);
I can see on console the collection changing, and if I minimize the JFrame and/or maximize, the JList is refreshed properly...

If you can, I suggest you use a DefaultListModel as your JList's model. This model will automate the change of the view (the JList) as the model changes and will make your life much easier. If you absolutely must use a collection of your own making, then see if you can have the class that holds it extend an AbstractListModel. If you do this, be sure to call the appropriate fireXXXX() method whenever you change data in the model.

Once your collection has changed, call a refresh on your JList:
SwingUtilities.invokeLater(new Runnable() {
public void run() {
jlist.revalidate(); // triggers a repaint of all the items in the JList.
jlistContainer.repaint(); // Not sure if this one is needed
}
});
How your JList model is updated?
[EDIT] Now that we have your code, you should look at AbstractListModel and implements your model in the same way, or better, extends AbstractListModel.
Actually, you add data to your collection but the model is not notified of this change!

When you added or removed items using the add and remove methods, you were calling methods in Vector. This updated your model but the actual JList had no way to know that the model was updated and that it needed to refresh itself.
(I think others have adequately explained how to fix the problem)

Finally I have resolved this thanks to your help!
This is what I did:
1) In the class doing the work I have
public DefaultListModel userList;
and I populate it with userList.addElement(user) and userList.removeElement(user)
2) in the JFrame class, I have:
JList list = new JList();
list.setCellRenderer(new UsersRenderer());
list.setModel(xmppManager.userList);
3) and this is my UsersRenderer:
import java.awt.Color;
import java.awt.Component;
import javax.swing.*;
public class UsersRenderer extends javax.swing.JPanel implements ListCellRenderer {
/**
*
*/
private static final long serialVersionUID = -9210143012283239644L;
public UsersRenderer() {
initComponents();
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
User person = (User) value;
labelUser.setText(person.getName() + " " + person.getAddress());
if (isSelected) {
setBackground(Color.red);
setForeground(Color.white);
} else {
setBackground(Color.white);
setForeground(Color.black);
}
return this;
}
private void initComponents() {
labelUser = new javax.swing.JLabel();
labelUser.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
labelUser.setText("testo");
add(labelUser);
}
private javax.swing.JLabel labelUser;
}

Related

JAVA GUI - How to make a custom JList entry that has two components, and identify which component was clicked

I am trying to create a JList of JCheckBoxes. To do this, i created a JListRenderer which will render each individual entry as a checkbox.
private class JListRenderer extends JCheckBox implements ListCellRenderer<ACustomClass> {
#Override
public Component getListCellRendererComponent(JList<? extends ACustomClass> list, ACustomClass value, int index, boolean isSelected, boolean cellHasFocus) {
//code
return this;
}
}
I also created a custom ListSelectionListener that will handle the selection of these checkboxes and will select and unselect the checkbox.
public class CheckBoxListSelectionListener implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent e) {
//list selection code where i handle how to check or uncheck the JCheckBox
}
}
This is all working really well, hence i have not written body of the code in the above example.
I want the selection of the checkbox part of the entry, separate from the text.
Such that i can select/highlight the text without checking the checkbox. By doing this, I am hoping to choose a single entry and display its values at a different place, while the state of the checkbox stays unchanged.
I tried to create a RowPanel, and replaced JCheckbox with it, such that JList is rendered with RowPanel entries, making the JListRenderer something like this
private class JListRenderer extends RowPanel implements ListCellRenderer<RowPanel> {
#Override
public Component getListCellRendererComponent(JList<? extends RowPanel> list, RowPanel value, int index, boolean isSelected, boolean cellHasFocus) {
//code
return this;
}
}
public class RowPanel extends javax.swing.JPanel {
private DataClass data;
private JCheckBox checkbox;
private JLabel label;
/**
* Creates new form RowPanel
*/
public RowPanel() {
initComponents();
}
public RowPanel(DataClass value) {
this.data = value;
initComponents();
}
}
The problem with this approach is, that the ListSelectionListener only identify RowPanel as the source of 'selection' event. How can I identify "whether the checkbox was selected or the label"?

How do I return an object to a previous frame that is still open?

I have a main frame which has an array list containing a list of items for an order. I then have a button which creates a new window that has a form allowing the user to pick multiple options for an item, this information is then put into an object.
I want to return this object back to the original frame so that I can add it to the order array list. However I'm not sure how to go about this as my frames have their code auto generated as I'm using netbeans.
You should use a listener (interface) system. Create an interface and implement it in your main frame, when you create your second frame you pass the first one as parameter. By this way you will be able to call a method, let's say, onItemSelected in the second frame whenever you want in an elegant way.
Using interfaces is more convenient, you can have multiple listener.
There is an example:
class MyFrame extends JFrame implements ItemSelectedListener {
void onButtonClick() {
new SecondFrame(this);
}
#Override
public void onItemSelected(List<String> items) {
// do your stuff with the selected items here
}
}
interface ItemSelectedListener {
void onItemSelected(List<String> items);
}
class SecondFrame extends JFrame {
private ItemSelectedListener itemSelectedListener;
private JTextField name;
private JButton buttonOk;
SecondFrame(ItemSelectedListener listener) {
itemSelectedListener = listener;
name = new JTextField();
buttonOk = new JButton("OK");
getContentPane().add(name);
getContentPane().add(buttonOk);
buttonOk.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
List<String> myFormItems = new ArrayList<>();
// fulfill your list with all informations that you need
myFormItems.add(name.getText());
// notify your main frame that the user finished to complete the form
itemSelectedListener.onItemSelected(myFormItems);
}
});
}
}

Java Swing - Get object that the mouse hovers over

I have a JList and want to change the tooltips, depending on the entry the mouse hovers over. I tried searching my problem on google, but had no success.
Basically i need to get the object i am currently hovering over.
Every help is appreciated
In order to do that, you have to extend JList and expose the tooltip text method. Here is an example program I found sometime ago using Google:
import java.awt.EventQueue;
import java.awt.event.*;
import javax.swing.*;
// Custom class to extend our JList and expose tooltip functionality.
class MyList extends JList {
public MyList() {
super();
// Attach a mouse motion adapter to let us know the mouse is over an item and to show the tip.
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
MyList theList = (MyList) e.getSource();
ListModel model = theList.getModel();
int index = theList.locationToIndex(e.getPoint());
if (index > -1) {
theList.setToolTipText(null);
String text = (String) model.getElementAt(index);
theList.setToolTipText(text);
}
}
});
}
// Expose the getToolTipText event of our JList
public String getToolTipText(MouseEvent e) {
return super.getToolTipText();
}
}
public class TestJList extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TestJList myTest = new TestJList();
myTest.setTitle("Example JList");
myTest.setSize(300, 300);
myTest.setDefaultCloseOperation(EXIT_ON_CLOSE);
MyList list = new MyList();
// Create our model and add some items.
DefaultListModel model = new DefaultListModel();
model.addElement("one");
model.addElement("two");
model.addElement("three");
model.addElement("four");
// Set the model for our list
list.setModel(model);
ToolTipManager.sharedInstance().registerComponent(list);
// Add our custom list and show the form.
MyTest.add(list);
MyTest.setVisible(true);
}
});
}
}
Hope this helps.
1) Assign a MouseListener to all elements in question.
2) Implement the mouseEntered method
3) Inside that method, use event.getSource() to get the element that was hovered.

PropertyChangeSupport for SpinnerNumberModel

I want to listen to the changes of the value of the SpinnerNumberModel for a JSpinner.
I create a PropertyChangeSupport and put the model into it.
I need the propertyChangeListener, because it shows me the old and new value of the property.
The snippet doesn't work: the propertyChange method prints nothing, when I click on the JSpinner.
A simple ChangeListener give only the new value, but I need also the old value, how can I get it?
package de.unikassel.jung;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
public class PropertyChangeTest implements PropertyChangeListener {
public static void main(String[] args) {
new PropertyChangeTest();
}
public PropertyChangeTest() {
JFrame frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int value = 1;
int min = 0;
int max = 10;
int step = 1;
SpinnerNumberModel spinnerModel = new SpinnerNumberModel(value, min, max, step);
PropertyChangeSupport pcs = new PropertyChangeSupport(spinnerModel);
pcs.addPropertyChangeListener("value", this);
JSpinner spinner = new JSpinner(spinnerModel);
frame.getContentPane().add(spinner);
frame.setVisible(true);
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
System.out.println(evt);
System.out.println(evt.getSource());
}
}
Instead of listening to the model, listen to the editor's JFormattedTextField, as suggested below.
JSpinner spinner = new JSpinner(new SpinnerNumberModel(1, 0, 10, 1));
JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) spinner.getEditor();
editor.getTextField().addPropertyChangeListener("value", this);
Monday morning ... classical time for not resisting a couple of comments :-)
#timaschew
"need the propertyChangeListener, because it shows me the old and new value of the property." - (nitpicking - but always have this strong urge to separate requirement and solution :), I think it's the other way round: on a change notification you need access to both the old and new value, a propertyChangeEvent/Listener is a notification type which supports it, there might be others
PropertyChangeSupport is not supposed to be used on part of the the observing code, it's supposed to be used on the obervable's side (just as #Hovercraft did in his example): it's sole responsibility is manage and notify the listeners registered to the observable
occasionally, accessibleContext provides a hook for hacks - nevertheless, it's a hack to hook into it (except you really need to support accessibility, which might well be the case :-) As with all hacks, that's a brittle solution which most probably will cause pain sometime in the future. Much more stable to follow the link about how Action and AbstractButton interact
#Hovercraft
enhancing the model with a richer change notification is the way-to-go (as in: my absolute favourite :-)
just a small detail: if you have a slave let him do all the work - PropertyChangeSupport has methods which take the old/new value, no need to feed to create an event on the observable. It will be thrown away anyway when old and new are equal
for newValue in the notification event, don't use the parameter but instead use getValue again (super might have rejected the change)
#trashgod
haha - you already guessed that I don't like solution: it breaks encapsulation in that it relies on an implementation detail, so don't except when in complete control of the JSpinner creation and are absolutely sure its editor is never changed
For a PropertyChangeSupport to work you need to call its firePropertyChange method, but more importantly the support object needs to have access to the setXXX method of the property that it is listening to, and in that method it needs to call PropertyChangeSupport's firePropertyChange method. And so I think for your idea to work, you'll need to extend the model's class, give it a PropertyChangeSupport object, give it the add and remove listener methods, and be sure to listen to changes made in the model's setValue method which is key. In my example that method looks like this:
#Override
public void setValue(Object newValue) {
// store old value and set the new one
Object oldValue = getValue();
super.setValue(newValue);
// construct the event object using these saved values
PropertyChangeEvent evt = new PropertyChangeEvent(this, VALUE, oldValue,
newValue);
// notify all of the listeners
pcs.firePropertyChange(evt);
}
Here's my sample model class that uses PropertyChangeSupport:
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
#SuppressWarnings("serial")
class MySpinnerNumberModel extends SpinnerNumberModel {
public static final String VALUE = "value";
private SwingPropertyChangeSupport pcs = new SwingPropertyChangeSupport(this);
// you will likely need to create multiple constructors to match
// the ones available to the SpinnerNumberModel class
public MySpinnerNumberModel(int value, int min, int max, int step) {
super(value, min, max, step);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
#Override
public void setValue(Object newValue) {
// store old value and set the new one
Object oldValue = getValue();
super.setValue(newValue);
// construct the event object using these saved values
PropertyChangeEvent evt = new PropertyChangeEvent(this, VALUE, oldValue,
newValue);
// notify all of the listeners
pcs.firePropertyChange(evt);
}
}
And finally the test class to test out the above class to see if it is working properly:
import java.beans.*;
import javax.swing.*;
public class TestSpinnerPropChange {
private static void createAndShowUI() {
final MySpinnerNumberModel myModel = new MySpinnerNumberModel(1, 0, 10, 1);
final JSpinner spinner = new JSpinner(myModel);
final JTextField oldValueField = new JTextField(10);
final JTextField newValueField = new JTextField(10);
JPanel panel = new JPanel();
panel.add(spinner);
panel.add(new JLabel("old value:"));
panel.add(oldValueField);
panel.add(new JLabel("new value:"));
panel.add(newValueField);
myModel.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
// checking the property name is overkill here, but is a good habit
// to get into, especially if listening to more than one property.
if (evt.getPropertyName().equals(MySpinnerNumberModel.VALUE)) {
oldValueField.setText(evt.getOldValue().toString());
newValueField.setText(evt.getNewValue().toString());
}
}
});
JFrame frame = new JFrame("TestSpinnerPropChange");
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html#bound
You have to fireThePropertyChange in the setters.

How do I make a list with checkboxes in Java Swing?

What would be the best way to have a list of items with a checkbox each in Java Swing?
I.e. a JList with items that have some text and a checkbox each?
A wonderful answer is this CheckBoxList. It implements Telcontar's answer (though 3 years before :)... I'm using it in Java 1.6 with no problems. I've also added an addCheckbox method like this (surely could be shorter, haven't used Java in a while):
public void addCheckbox(JCheckBox checkBox) {
ListModel currentList = this.getModel();
JCheckBox[] newList = new JCheckBox[currentList.getSize() + 1];
for (int i = 0; i < currentList.getSize(); i++) {
newList[i] = (JCheckBox) currentList.getElementAt(i);
}
newList[newList.length - 1] = checkBox;
setListData(newList);
}
I tried out the demo for the Jidesoft stuff, playing with the CheckBoxList I encountered some problems (behaviors that didn't work). I'll modify this answer if I find problems with the CheckBoxList I linked to.
Create a custom ListCellRenderer and asign it to the JList.
This custom ListCellRenderer must return a JCheckbox in the implementantion of getListCellRendererComponent(...) method.
But this JCheckbox will not be editable, is a simple paint in the screen is up to you to choose when this JCheckbox must be 'ticked' or not,
For example, show it ticked when the row is selected (parameter isSelected), but this way the check status will no be mantained if the selection changes. Its better to show it checked consulting the data below the ListModel, but then is up to you to implement the method who changes the check status of the data, and notify the change to the JList to be repainted.
I Will post sample code later if you need it
ListCellRenderer
Just implement a ListCellRenderer
public class CheckboxListCellRenderer extends JCheckBox implements ListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
setComponentOrientation(list.getComponentOrientation());
setFont(list.getFont());
setBackground(list.getBackground());
setForeground(list.getForeground());
setSelected(isSelected);
setEnabled(list.isEnabled());
setText(value == null ? "" : value.toString());
return this;
}
}
and set the renderer
JList list = new JList();
list.setCellRenderer(new CheckboxListCellRenderer());
this will result in
Details at Custom swing component renderers.
PS: If you want radio elements just replace extends JCheckbox with extends JRadioButton.
I'd probably be looking to use a JTable rather than a JList and since the default rendering of a checkbox is rather ugly, I'd probably be looking to drop in a custom TableModel, CellRenderer and CellEditor to represent a boolean value. Of course, I would imagine this has been done a bajillion times already. Sun has good examples.
Better solution for Java 7 and newer
I stumbled upon this question and realized that some of the answers are pretty old and outdated. Nowadays, JList is generic and thus there are better solutions.
My solution of the generic JCheckBoxList:
import java.awt.Component;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class JCheckBoxList extends JList<JCheckBox> {
protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public JCheckBoxList() {
setCellRenderer(new CellRenderer());
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int index = locationToIndex(e.getPoint());
if (index != -1) {
JCheckBox checkbox = (JCheckBox) getModel().getElementAt(index);
checkbox.setSelected(!checkbox.isSelected());
repaint();
}
}
});
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
public JCheckBoxList(ListModel<JCheckBox> model){
this();
setModel(model);
}
protected class CellRenderer implements ListCellRenderer<JCheckBox> {
public Component getListCellRendererComponent(
JList<? extends JCheckBox> list, JCheckBox value, int index,
boolean isSelected, boolean cellHasFocus) {
JCheckBox checkbox = value;
//Drawing checkbox, change the appearance here
checkbox.setBackground(isSelected ? getSelectionBackground()
: getBackground());
checkbox.setForeground(isSelected ? getSelectionForeground()
: getForeground());
checkbox.setEnabled(isEnabled());
checkbox.setFont(getFont());
checkbox.setFocusPainted(false);
checkbox.setBorderPainted(true);
checkbox.setBorder(isSelected ? UIManager
.getBorder("List.focusCellHighlightBorder") : noFocusBorder);
return checkbox;
}
}
}
For dynamically adding JCheckBox lists you need to create your own ListModel or add the DefaultListModel.
DefaultListModel<JCheckBox> model = new DefaultListModel<JCheckBox>();
JCheckBoxList checkBoxList = new JCheckBoxList(model);
The DefaultListModel are generic and thus you can use methods specified by JAVA 7 API here like this:
model.addElement(new JCheckBox("Checkbox1"));
model.addElement(new JCheckBox("Checkbox2"));
model.addElement(new JCheckBox("Checkbox3"));
I recommend you use a JPanel with a GridLayout of 1 column. Add the checkBoxes to the JPanel, and set the JPanel as the data source of a JScrollPane. And to get the selected CheckBoxes, just call the getComponents() of the JPanel to get the CheckBoxes.
Odds are good w/ Java that someone has already implemented the widget or utility you need. Part of the benefits of a large OSS community. No need to reinvent the wheel unless you really want to do it yourself. In this case it would be a good learning exercise in CellRenderers and Editors.
My project has had great success with JIDE. The component you want, a Check Box List, is in the JIDE Common Layer (which is OSS and hosted on java.net). The commercial stuff is good too, but you don't need it.
http://www.jidesoft.com/products/oss.htm
https://jide-oss.dev.java.net/
I don't like the solutions that put a Checkbox into the model. The model should only contain data not display elements.
I found this http://www.java2s.com/Tutorials/Java/Swing_How_to/JList/Create_JList_of_CheckBox.htm
which I optimized a bit. The ACTIVE flag represents the Checkbox, the SELECTED flag shows what entry the cursor sits on.
my version requires a renderer
import java.awt.Component;
import javax.swing.JCheckBox;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
class CheckListRenderer extends JCheckBox implements ListCellRenderer<Entity> {
#Override
public Component getListCellRendererComponent(JList<? extends Entity> list,
Entity value, int index, boolean isSelected, boolean cellHasFocus) {
setEnabled(list.isEnabled());
setSelected(value.isActive()); // sets the checkbox
setFont(list.getFont());
if (isSelected) { // highlights the currently selected entry
setBackground(list.getSelectionBackground());
setForeground(list.getSelectionForeground());
} else {
setBackground(list.getBackground());
setForeground(list.getForeground());
}
setText(value.toString()+" - A" + value.isActive()+" - F"+cellHasFocus+" - S"+isSelected );
return this;
}
}
and an entity that got the active field:
public class Entity {
private boolean active = true;
public boolean isActive() {
return active;
}
public void setActive(boolean isActive) {
this.active = isActive;
}
}
Now you only have to add this to your JList:
list = new JList<Entity>();
list.setModel(new DefaultListModel<Entity>());
list.setCellRenderer(new CheckListRenderer());
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent event) {
if (event.getX() < 20) {
// Quick and dirty: only change the tick if clicked into the leftmost pixels
#SuppressWarnings("unchecked")
JList<Entity> list = ((JList<Entity>) event.getSource());
int index = list.locationToIndex(event.getPoint());// Get index of item clicked
if (index >= 0) {
Entity item = (Entity) list.getModel().getElementAt(index);
item.setActive(!item.isActive()); // Toggle selected state
list.repaint(list.getCellBounds(index, index));// Repaint cell
}
}
}
});
All of the aggregate components in Swing--that is, components made up other components, such as JTable, JTree, or JComboBox--can be highly customized. For example, a JTable component normally displays a grid of JLabel components, but it can also display JButtons, JTextFields, or even other JTables. Getting these aggregate components to display non-default objects is the easy part, however. Making them respond properly to keyboard and mouse events is a much harder task, due to Swing's separation of components into "renderers" and "editors." This separation was (in my opinion) a poor design choice and only serves to complicate matters when trying to extend Swing components.
To see what I mean, try enhancing Swing's JList component so that it displays checkboxes instead of labels. According to Swing philosophy, this task requires implementing two interfaces: ListCellRenderer (for drawing the checkboxes) and CellEditor (for handling keyboard and mouse events on the checkboxes). Implementing the ListCellRenderer interface is easy enough, but the CellEditor interface can be rather clumsy and hard to understand. In this particular case, I would suggest forgetting CellEditor entirely and to handle input events directly, as shown in the following code.
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
public class CheckBoxList extends JList
{
protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public CheckBoxList()
{
setCellRenderer(new CellRenderer());
addMouseListener(new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
int index = locationToIndex(e.getPoint());
if (index != -1) {
JCheckBox checkbox = (JCheckBox)
getModel().getElementAt(index);
checkbox.setSelected(
!checkbox.isSelected());
repaint();
}
}
}
);
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
protected class CellRenderer implements ListCellRenderer
{
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus)
{
JCheckBox checkbox = (JCheckBox) value;
checkbox.setBackground(isSelected ?
getSelectionBackground() : getBackground());
checkbox.setForeground(isSelected ?
getSelectionForeground() : getForeground());
checkbox.setEnabled(isEnabled());
checkbox.setFont(getFont());
checkbox.setFocusPainted(false);
checkbox.setBorderPainted(true);
checkbox.setBorder(isSelected ?
UIManager.getBorder(
"List.focusCellHighlightBorder") : noFocusBorder);
return checkbox;
}
}
}
Here, I intercept mouse clicks from the listbox and simulate a click on the appropriate checkbox. The result is a "CheckBoxList" component that is both simpler and smaller than an equivalent component using the CellEditor interface. To use the class, simply instantiate it, then pass it an array of JCheckBox objects (or subclasses of JCheckBox objects) by calling setListData. Note that the checkboxes in this component will not respond to keypresses (i.e. the spacebar), but you could always add your own key listener if needed.
Source: DevX.com
Here is just a little addition to the JCheckBoxList by Rawa. This will add the ability to select using space bar. If multiple items are selected, all will be set to inverted value of the first item.
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
int index = getSelectedIndex();
if (index != -1 && e.getKeyCode() == KeyEvent.VK_SPACE) {
boolean newVal = !((JCheckBox) (getModel()
.getElementAt(index))).isSelected();
for (int i : getSelectedIndices()) {
JCheckBox checkbox = (JCheckBox) getModel()
.getElementAt(i);
checkbox.setSelected(newVal);
repaint();
}
}
}
});
this is yet another example of making list with checkboxes
class JCheckList<T> extends JList<T> {
protected static Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
public void setSelected(int index) {
if (index != -1) {
JCheckBox checkbox = (JCheckBox) getModel().getElementAt(index);
checkbox.setSelected(
!checkbox.isSelected());
repaint();
}
}
protected static class CellListener
extends DefaultListModel
implements ListDataListener {
ListModel ls;
public CellListener(ListModel ls) {
ls.addListDataListener(this);
int i = ls.getSize();
for (int v = 0; v < i; v++) {
var r = new JCheckBox();
r.setText(ls.getElementAt(v).toString());
this.addElement(r);
}
this.ls = ls;
}
#Override
public void intervalAdded(ListDataEvent e) {
int begin = e.getIndex0();
int end = e.getIndex1();
for (; begin <= end; begin++) {
var r = new JCheckBox();
r.setText(ls.getElementAt(begin).toString());
this.add(begin, r);
}
}
#Override
public void intervalRemoved(ListDataEvent e) {
int begin = e.getIndex0();
int end = e.getIndex1();
for (; begin <= end; end--) {
this.remove(begin);
}
}
#Override
public void contentsChanged(ListDataEvent e) {
}
}
public JCheckList() {
setCellRenderer(new CellRenderer());
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int index = locationToIndex(e.getPoint());
setSelected(index);
}
}
);
addKeyListener(new KeyListener(){
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE){
int index = JCheckList.this.getSelectedIndex();
setSelected(index);
}
}
#Override
public void keyReleased(KeyEvent e) {
}
});
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
#Override
public void setModel(ListModel<T> d) {
var r = new CellListener(d);
d.addListDataListener(r);
super.setModel(r);
}
protected class CellRenderer implements ListCellRenderer {
public Component getListCellRendererComponent(
JList list, Object value, int index,
boolean isSelected, boolean cellHasFocus) {
JCheckBox checkbox = (JCheckBox) value;
checkbox.setBackground(isSelected
? getSelectionBackground() : getBackground());
checkbox.setForeground(isSelected
? getSelectionForeground() : getForeground());
checkbox.setEnabled(isEnabled());
checkbox.setFont(getFont());
checkbox.setFocusPainted(false);
checkbox.setBorderPainted(true);
checkbox.setBorder(isSelected
? UIManager.getBorder(
"List.focusCellHighlightBorder") : noFocusBorder);
return checkbox;
}
}
}

Categories

Resources