For example, I have a JList named across_list that containing a list of items and now I add a ListSelectionListener to that JList
Considering these lines of code:
class AcrossListHandler implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent e) {
JList lsm = (JList) e.getSource();
int selected_index = lsm.getMaxSelectionIndex();
if (selected_index >= 0){
System.out.println(selected_index);
}
}
}
}
I have a question that: Why the line "System.out.println()" print 2 values of selected_value while i just click 1 time on an index in JList ???
The listSelectionListener registered by the ui-delegate marks the selection change as being in-process on mousePressed and resets that flag in mouseReleased, making it final. If you want to only react only to changes that are finalized, you can query the valueIsAdjusting property and do nothing if true:
class AcrossListHandler implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent e) {
if (e.getValueIsAdjusting()) return;
// do stuff
}
}
Related
So this is the first time I tried using CellEditors for my JTable to embed JComboBox and JSpinner. Everything works fine as expected wherein I can see the values in JComboBox model as well as JSpinner's model values.
However, I noticed that it always displays the JComboBox's values as soon as I make a single click on JTable's column that has the JComboBox.
It's not very user friendly because I think the user would prefer to double click on a JTable's column to get the dropdown box values and select values from it instead of a single click.
How can I change the JComboBox's behaviour to only display itself on double click?
I thought I'd apply a MouseListener to the JComboBox but I don't know what to do next.
Here's what I've written so far.
public class ScheduleDayCellEditor extends DefaultCellEditor{
private JComboBox jcmbDays;
private JTable jtblSchedule;
private DefaultComboBoxModel model;
public ScheduleDayCellEditor(){
super(new JComboBox());
model = new DefaultComboBoxModel(new String[]{"Mon","Tue","Wed","Thu","Fri"});
jcmbDays = new JComboBox(model);
jcmbDays.setEditable(false);
jcmbDays.setSelectedIndex(-1);
jcmbDays.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
if(e.getClickCount() == 2){
//? ? ? ?
}
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
});
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
return jcmbDays;
}
#Override
public Object getCellEditorValue() {
return jcmbDays.getSelectedItem(); //To change body of generated methods, choose Tools | Templates.
}
Here's a screenshot for additional description.
I'd appreciate any help.
Thank you.
If you don't need to extend DefaultCellEditor for some other reason, you can simply invoke its setClickCountToStart() method with a count of 2.
DefaultCellEditor editor = new DefaultCellEditor(jcmbDays);
editor.setClickCountToStart(2);
jcmbColumn.setCellEditor(editor);
Simply override isCellEditable by applying further criterion:
#Override
public boolean isCellEditable(EventObject aAnEvent) {
boolean cellEditable = super.isCellEditable(aAnEvent);
if (cellEditable && aAnEvent instanceof MouseEvent) {
cellEditable = ((MouseEvent) aAnEvent).getClickCount() == 2;
}
return cellEditable;
}
I have a big panel with 6 JScrollPane inside, each JScrollPane contain a JList.
I am trying to add a MouseListener event to every single JList on the panel, how can i get access to it? to better understand, this is my code:
private void agregarDobleClick() {
for (Component c : jPanel1.getComponents()) {
c.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent evt) {
JList list = (JList) evt.getSource();
if (evt.getClickCount() == 2) {
Rectangle r = list.getCellBounds(0, list.getLastVisibleIndex());
if (r != null && r.contains(evt.getPoint())) {
modCitaPOPUP modcita = new modCitaPOPUP((Cita) list.getSelectedValue());
modcita.setVisible(true);
}
}
}
});
}
}
when i run this, it add the mouseListener to the JScrollPane, and when i double-click on a JList item, nothing happen because the mouseListener event isnt there.
thanks.
It "looks" like, from your description, you're adding the MouseListener to the JScrollPane and not the JList.
The simple solution would be to make a speciality MouseListener...
public class ListMouseListener extends MouseAdapter {
private JList list;
public ListMouseListener (JList list) {
this.list = list;
}
#Override
public void mouseClicked(MouseEvent evt) {
// Know you're self out with the list instance variable...
}
}
And apply it to each JList when you create it...
JList list = new JList();
list.addMouseListener(new ListMouseListener(list));
Now, if you're worried that they might be inefficient or consuming to much memory (which based on your example, you're not), you could instead, create a generic MouseListener which used the event source to determine who triggered it...
public class ListMouseListener extends MouseAdapter {
#Override
public void mouseClicked(MouseEvent evt) {
Object source = evt.getSource();
if (source instanceof JList) {
JList list = (JList)source;
}
}
}
Then create a single instance and apply it all your instances of JList...
ListMouseListener singleInstance = new ListMouseListener();
//...
JList list = new JList();
list.addMouseListener(singleInstance);
I'm having a little headache with a situation. Maybe some of you have been through this before and can show me another way or even my error here.
I need to add a JTree inside a JComboBox and the code below works like a charm.
public class HierarchyComboBox extends JComboBox {
HierarchyTree ht = new HierarchyTree();
HierarchyComboBox box;
JPopupMenu popup;
MouseAdapter adapter = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
if (arg0.getClickCount() == 1) {
removeAllItems();
addItem(ht.getSelectedLevel());
// ((JPopupMenu) comp).setVisible(false);
}
}
};
PopupMenuListener listener = new PopupMenuListener() {
#Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
if (box == null) {
box = (HierarchyComboBox) e.getSource();
if (popup == null) {
final Object comp = box.getUI().getAccessibleChild(box, 0);
if (!(comp instanceof JPopupMenu))
return;
popup = (JPopupMenu) comp;
}
popup.removeAll();
ht.getTreePane().setBorder(null);
ht.getTreePane().setPreferredSize(new Dimension(box.getWidth(), 200));
MyTree tree = (MyTree)ht.getTreePane().getViewport().getComponent(0);
tree.addMouseListener(adapter);
popup.add(ht.getTreePane());
}
}
#Override
public void popupMenuCanceled(PopupMenuEvent arg0) { }
#Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent arg0) { }
};
public HierarchyComboBox() {
setEditable(true);
addPopupMenuListener(listener);
}
}
but I added this component to 2 different dialogs.
The first one I can click and the selection is added to the JComboBox
and the second, doing EXACTLY the same instantiation, and the same tests
The component has a different behaviour:
- The JPopupMenu disappears
- It doesn't add the selection to the combo
Any ideas here?
Thanks in advance..
As shown in Providing a Custom Renderer, "A combo box uses a renderer to display each item in its menu." You could render the tree in a custom ListCellRenderer. Alternatively,
Render the tree in an adjacent component in response to an ActionListener.
Use a hierarchical model, shown here.
I noticed that the JPopupMenu was loosing it's focus.
The solution was to add the component as the last component of the Panel.
I have this bug, after populating the JList, I try to retrieve the value of the selected item. But when I am doing it, it is called twice.
Here is my code :
public CaveAdventureUI(CaveGame game) {
initComponents();
playerCarryItemModel = new DefaultListModel();
caveCarryItemModel = new DefaultListModel();
this.caveGame = game;
this.world = game.getCaveWorld();
listSelectionModel = this.jListCaveCarryItems.getSelectionModel();
listSelectionModel.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
this.listSelectionModel.addListSelectionListener( new SharedListSelectionHandler());
//for debug purpose,see the world grid in console
game.drawCaves();
//new JComboBox(Mood.values());
createGridQuarePanels();
//world.startGame(GameLevel.Beginner);
update();
}
private class SharedListSelectionHandler implements ListSelectionListener {
public void valueChanged(ListSelectionEvent listSelectionEvent) {
ListSelectionModel lsm = (ListSelectionModel)listSelectionEvent.getSource();
if (!lsm.isSelectionEmpty()) {
Occupant opt = mapOccupants.get(Integer.toString(jListCaveCarryItems.getSelectedIndex()));
System.out.println("selected index :" +jListCaveCarryItems.getSelectedIndex() +"[["+opt.getName()+"]]");
}
}
}
In the above code, when I am making selection on jList : jListCaveCarryItems, it triggers the SharedListSelectionHandler class. However, when I am clicking on the JList, it print out the selected value twice.
Can anyone help me to figure it out?
Thanks & Regards,
2 ListSelectionEvents are dispatched when the JList is selected—one during and another after the selection event. From How to Write a List Selection Listener
The isAdjusting flag is true if the user is still manipulating the selection, and false if the user has finished changing the selection.
Therefore, ensure that the ListSelectionEvent value is not adjusting.
public void valueChanged( ListSelectionEvent listSelectionEvent) {
if ( !listSelectionEvent.getValueIsAdjusting() && !lsm.isSelectionEmpty()) {
Occupant opt = ...
...
}
}
Currently, I have a Jlist with a custom CellRenderer as follows. I attached a custom MouseListener in order to capture hover events and, later on, double click events; but the events weren't being fired when I added them this way. After 20 minutes, I found out it was because the JList was blocking the events from reaching the individual list items. Is there any way I can force the JList to forward the mouse events to its children elements, or is there a better way of doing this.
My CellRenderer:
public class FriendRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 1L;
public Component getListCellRendererComponent(JList list,
Object value,
int index,
boolean isSelected,
boolean hasFocus) {
Friend friend = (Friend)value;
JLabel label = new JLabel(friend.getName());
JPanel mainOuterPanel = new JPanel();
mainOuterPanel.setLayout(new BorderLayout());
/* Adding components to mainOuterPanel... */
/* Here is where I add the custom MouseListener */
mainOuterPanel.addMouseListener(new ListItemMouseListener());
return(mainOuterPanel);
}
}
My MouseListener:
public class ListItemMouseListener implements MouseListener{
#Override
public void mouseClicked(MouseEvent e) {}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {
Component source = e.getComponent();
source.setBackground(new Color(102, 99, 86));
System.out.println("Mouse entered on " + source.toString());
}
#Override
public void mouseExited(MouseEvent e) {
Component source = e.getComponent();
source.setBackground(null);
System.out.println("Mouse Exited on " + source.toString());
}
}
Where I build my JList in my JFrame:
private JList getFriendsList(){
friendsList = new JList(getFriendsListModel()); //TODO Actually fill with data
friendsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
friendsList.setLayoutOrientation( JList.VERTICAL );
friendsList.addListSelectionListener(new FriendsListSelectionListener());
friendsList.setCellRenderer(new FriendRenderer());
return friendsList;
}
Thanks in advance!
Add the listener to the list and use the list methods to convert the point to a row.
The reason it is not working when added to the renderer, is that the render is really only used for ..rendering. It is like a 'template' used to paint the list item (& every other visible list item) before the item(s) appear on-screen.
..access the cells .. in order to change the background..
Configure the ListCellRenderer to handle that.