Jcombobox - subscribe to selectedItemChanged event - java

I am trying to perform an action whenever a selected item on the combobox changes. one particular scenario, when action listener is not notified, is when you reset the model on the combobox. I can subscribe with another PropertyChangedListener and listen when the model changes, and then extract selected item, but I simply do not understand why the selected item changed event is not raise dwhen model changes. visually your selection does change, even if you query the cobox for a selected item, it does change from null to some object... ANy clear olution to this, rather than using two separate listeners?

If the action and item listeners don't fire events when model is reset, you can fire those event by yourself by subclassing JComboBox:
public class MyComboBox extends JComboBox
{
#Override
public void setModel(ComboBoxModel aModel) {
super.setModel(aModel);
fireActionEvent();
}
}
But IMHO it is a bug - you should report that to the official bugzilla.

Related

Swing Dynamical JCombobox detect selection change by user

I would like to know if there is a way to detect if changes in the selection of a item in a swing JCombobox is done by a user (actively) or is causes by repopulating the Jcombobox.
I have to dynamically repopulate the items of the combobox based on other selection, this also invokes the actionPerformed event
so actionPerformed is invoked by:
selection changed by user
repopulating the jcombobox items.
how to tell the difference?
Thanks of helping !
No, not really.
A possible solution is to disable event notification while the combo box is updated. This can be done in (at least) one of two ways...
Firstly, you could physically remove the listener from the combo box, if you have a reference to it.
Secondly, you set a boolean flag, which when true, the listener would ignore the event.
For example...

Add item to GUI jCombo box

I have a Java program with a model and a GUI. On my Frame (that implements Observer) I have put a jcombobox with a list of registration from my model (that extends Observable).
When I click on a button add registration the list in my model changed. And than I do
setChanged();
notifyObservers();
In my update method I want to make change the values of the jcombobox. I tried with a repaint() or something like that, but my combobox doesn't change. I am sure I go to my update method, but I don't know how I have to change the jcombobox.
Can someone help
Your update() implementation should obtain a reference to the combo's model and either set the selected item or add a new item, as warranted. A PropertyChangeEvent, illustrated here, may be an alternative, as it can include both old and new values.

Java: JList ListSelectionListener only on MouseClick

I'm fairly new to Java, and have exhausted my Google'ing for this problem with selection on a JList component. I have a list of strings that dynamically change when the user clicks various JButtons. My JList selection mode is set to SINGLE_SELECTION, and the ListSelectionModel is registered to a custom ListSelectionChangeHandler that implements ListSelectionListener.
My problem is that every time the JList model's contents get modified (by clicking a JButton), the ListSelectionChangeHandler gets called and a NullPointerException occurs - e.g. The user has an item selected in the list, clicks a button, the list contents change, and the listener gets called. I want the ListSelectionListener to only perform some action when a MouseClick fires the event. How can I prevent my listener from firing when the model data gets modified?
Relevant Code:
this.suggestionsList = new JList();
this.suggestionsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
ListSelectionModel model = this.suggestionsList.getSelectionModel();
model.addListSelectionListener(new ListSelectionChangeHandler());
class ListSelectionChangeHandler implements ListSelectionListener {
#Override
public void valueChanged(ListSelectionEvent arg0) {
Object selectedValue = suggestionsList.getSelectedValue();
// Perform action on selectedValue
// Enable/Disable components as needed
}
}
Thanks for the help!
The easiest way, of which I can think, is to make a switcher - boolean variable, that will be checked every time in your listener before it starts to really do something. Then you can start all of you modifications with switching this variable off. In case of multithreading, you may need some synchronization here.

How would I code when a item has been selected in a JList?

I have a JList with 5 options in it and when one of the items becomes selected or clicked i want the text area next to it to show a paragraph of text relative to the item clicked. It should do this for each item in the list but I cant seem to find how to do it in the API
How would my program know if an item in the JList was selected so I can work with the data?
Use addListSelectionListener. You can create a subclass (anonymous or not) of ListSelectionListener that does the work you want.
myList.addListSelectionListener(new ListSelectionListener()
{
public void valueChanged(ListSelectionEvent ev)
{
// handle ev
}
});
You should register a Listener for events on your JList. When the Swing UI fires one off, this Listener class will get the message and react accordingly.

Java JTree valueChanged Event before MouseEvent

Here's the situation, I have a jFrame with a tabbed pane and within the tabs I have a couple of jTables and a jTree. I want to be able to chain the selections between the tables and the tree based on whether a user uses a ctrl/shift + click versus a regular click. (If you hold ctrl and click in the first table/tree, it adds to the overall selection, if you use a regular click it clears the selections in the other tables/tree). Currently I'm having an issue with Java's jTree component. I have added a TreeSelectionListener and a MouseListener with a class that implements both interfaces, call it MyBigListener;
i.e.
MyBigListener listener = new MyBigListener();
jTree1.addMouseListener( listener );
jTree1.addTreeSelectionListener( listener );
MyBigListener implements TreeSelectionListener, MouseListener {
private boolean chained = false;
public synchronized setChained(boolean ch){
chained = ch;
}
public synchronized boolean isChained(){
return chained
}
public void valueChanged(TreeSelectionEvent e){
if(isChained()){ blah... }
}
public void mousePressed(MouseEvent e){
setChained(e.isControlDown() || e.isShiftDown());
}
}
My plan was to set a boolean flag if the user uses a ctrl/shift + click that I could check during the valueChanged(TreeSelectionEvent e) implemented by the tree selection listener.
I want to be able to process the mouse events before the valueChanged TreeSelectionEvents, but the problem is that I receive the mouse events after the valueChanged treeSelection event. This seems weird to me that I receive the selection change before the mouse pressed event fires, when the selection change is actually initiated by the mouse pressed. (I've already synchronized the boolean flag setting, which ironically helped to highlight the mis-order of events.)
I've already tried alternatives like adding a keyListener, but this doesn't work when the focus is on a separate frame, which goofs me up when a user holds ctrl and then clicks into the jTree causing it to receive both the focus and fire any valueChanged selection events.
Any help would be appreciated, thanks!
--EDIT-- #akf
I have separate jTables and jTrees in a tabbed Pane that serve as a summary/control panel for data in a nodal-graph. I'm using these components in the tabbed Pane to do coordinated selection to a graph displayed in a separate jFrame. Individually each table works just fine for its selection as does the jTree. It's coordinating between the panes that's tricky. This works fine so far with jTable components because I fire the new selections as the result of a MouseEvent where I can tell if the shift/ctrl button was down, formulate my new selection, and pass it to the parent frame which coordinates selections between all panes and sends the final selection to the graph. However, the parent needs to know if it needs to chain a selection between panes, or squash the others. With the jTables it's fine again, because I fire selection changes as the result of a mouse click. The jTree is more of a problem because I'm doing some forced selections. If you click on a branch, it forces all leaves into the selection. I needed to implement a TreeSelectionListener to do that, but only get a valueChanged(TreeSelectionEvent) to realized changes. I added a mouseListener to listen for ctrl+clicks and shift+clicks, but apparently the events don't always happen in the same order.. at least so far I receive the valueChanged event before the mousePressed event, so checking to if a ctrl+click happened posts after the selection has already been modified.
Right now, I'm posting a pending selection change and then have the MouseListener grab that and send it up the chain, but if these events aren't guaranteed to happen in the same order, at some point it's going to fail. Implementing a delayer also rubs me the wrong way.
Thanks for the help so far.
--EDIT2-- #ykaganovich
I think overriding the fireValueChanged method is closer to the right way to go about things. Depending on my definition of what actions should cause a "chained" selection to the other components, I'd need to gather some context on what's going on before the valuedChanged method fires. This basically means calling it myself in all cases where I can define what it means by who triggers it. I.e. If a mouse event causes it and ctrl is down then set what I need to set (interpret) then fire. If it's going to change due to a keyboard event, again, set what I need to set, then fire. I don't think the TreeSelectionModel is the way to go, because I still won't know what the circumstances were when the event fired. I think this means I'll need to rewrite parts of the jTree to do this but I guess I'll see how it goes. Thanks.
Don't do it that way, override JTree.fireValueChanged instead.
Try something like this (untested):
class ChainedSelectionEvent extends TreeSelectionEvent {
ChainedSelectionEvent(TreeSelectionEvent e) {
super(e.newSource, e.paths, e.areNew, e.oldLeadSelectionPath, e.newLeadSelectionPath);
}
}
protected void fireValueChanged(TreeSelectionEvent e) {
if(chained) { // figure out separately
super.fireValueChanged(new ChainedSelectionEvent(e));
} else {
super.fireValueChanged(e);
}
}
Then check instanceof ChainedSelectionEvent in your listener
EDIT
Actually, I think the right way to do this is to implement your own TreeSelectionModel, and override fireValueChanged there instead. Assuming setSelectionPath(s) methods imply a new selection, and add/removeSelectionPath(s) imply chaining, you could distinguish between the two cleanly. I don't like listening to either keyboard or mouse events explicitly, because there's more than one way to change a selection (e.g. if someone is holding down SHIFT and hitting a down-arrow, you won't get a mouse event).
You may get the mouse event before or after the tree selection event. Best not to rely on such orders. The reason is that the tree selection event is caused in response to the mouse event. Is that mouse event listener called before or after your listener? Could be either.
This sort of thing is closely involved with the implementation of the PL&F.
the key here is to understand that a JTree is delivered with a BasicTreeUI.MouseHandler, see javax.swing.plaf.basic.BasicTreeUI.
to answer the central question, "what fires fireValueChanged", the answer is "this mouse handler"... which turns out to be the only mouse listener returned when you go tree.getMouseListeners().
So you have to replace this default mouse listener with your own version ... which is a little tricky. I use Jython, which everyone needs to discover. This code shouldn't be too difficult to translate into Java however:
from javax.swing.plaf.basic import BasicTreeUI
def makeMouseHandlerClass():
class MouseHandlerClass( BasicTreeUI.MouseHandler ):
def mousePressed( self, mouseEvent ):
genLog.info( "mouse handler MOUSE PRESSED!" )
nTFSelf.mousePressedStatus = True
BasicTreeUI.MouseHandler.mousePressed( self, mouseEvent )
nTFSelf.mousePressedStatus = False
return MouseHandlerClass
suppliedMouseHandler = nTFSelf.taskTree.mouseListeners[ 0 ]
nTFSelf.taskTree.removeMouseListener( suppliedMouseHandler )
nTFSelf.taskTree.addMouseListener( makeMouseHandlerClass()( nTFSelf.taskTree.getUI() ))
... basically the equivalent Java here would be to extend BasicTreeUI.MouseHandler as MyMouseHandler, and then in the last line replace with new MyMouseHandler( tree.getUI() )... "nTFSelf" here is merely a reference to the "this" object of the code where all this is being written...

Categories

Resources