• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

altering a GUI object without triggering the listener

 
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
In my program there are some GUI items (a JTable for example) which have Listener objects to listen for changes to the item's content when the content is changed by the program user. Then when the content is changed, it fires an event and that causes the program to update the content of the GUI by changing the content. However, of course when the program changes something, I don't want the GUI to react to that event. So what I do is I have a boolean called something like byuser and set it to true most of the time, and before the program changes the GUI, it sets byuser to false, and after it changes the GUI, it sets byuser to true again. And in the method called when the event is fired, I put a line which checks whether or not byuser is true, and does something only if byuser is true.
Anyway, that is how I do it. But I have a feeling that that is not the standard way to do it. What is the standard way of having a GUI object react to the user, but not to the program?
 
Kevin Tysen
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To be more specific about my question, I have a JTextField that has autocomplete function that I am trying to write. When I typed something in the JTextField, the program tried to change the text too and I got this message:
java.lang.IllegalStateException: Attempt to mutate in notification
What's that?
 
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

Kevin Tysen wrote:When I typed something in the JTextField, the program tried to change the text too


Perhaps you should just show the suggestions and not immediately change the input.

Anyhow, the best would be to share your code (a snip) with us ...


Regards,
Rok
 
Marshal
Posts: 79153
377
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Moving to another forum where we usually discuss GUIs
 
Kevin Tysen
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


When the user clicks on an item in cList, that item is passed as a String to setInputText(String newText). userTextChange is set to false. Then .setText(String text) is called, which causes 2 events. The first event is removeUpdate(DocumentEvent e), and nothing happens, and the second event is insertUpdate(DocumentEvent e). When that is called, nothing happens because userTextChange is false. After that, userTextChange is set to true again.
When the user types something in input (the JTextField), insertUpdate(DocumentEvent e) is called, and because userTextChange is true, the findIndex() method is called, which chooses the index of a String from cList. Then cList scrolls to show the String. Then cList.setSelectedIndex(int index) is called. Here is where the problem is.
I expect the program-initiated selection of cList to trigger the valueChanged(ListSelectionEvent lse) event, which calls setInputText(String newText). Then userTextChange is changed to false, then the text is changed, but now that userTextChange is false, when removeUpdate and insertUpdate events occur, nothing happens.
That is what I expect, but I get an Exception which I described above arising in the setInputText(String newText) method.
Maybe what I need is a better way to change the text in input without causing the insertUpdate event.
 
Ranch Hand
Posts: 4632
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
you type something into the textfield, and during insertUpdate() you change the selected index of the list.
this change to the list triggers the listSelectionListener, which tries to set the text of the textfield,
so it errors because you're trying to change the text while it is still being modified (insertUpdate).

these few lines should fix it

add this as a class field
cLListener listListener = new cLListener();

change this
//cList.addListSelectionListener(new cLListener());
cList.addListSelectionListener(listListener);

add the two indicated lines in autoCompleteListener
cList.removeListSelectionListener(listListener);//<-----------------------
cList.ensureIndexIsVisible(mLSIndex);
cList.setSelectedIndex(mLSIndex);
cList.addListSelectionListener(listListener);//<-----------------------
 
Kevin Tysen
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Removing the ListSelectionListener will keep my program from getting an Exception. However, I WANT the ListSelectionListener to change the text in the JTextField. The problem is (according to the printStackTrace) that when the Listener tries to change the text in the JTextField, it calls writeLock() method in the AbstractDocument object in the JTextField, which causes IllegalStateException because the writeLock is not available (probably because the cursor is still in the JTextField and it is in the middle of being edited by the user).

The API of AbstractDocument has this explanation for the IllegalStateException thrown by the writeLock method:

"thrown on illegal lock attempt. If the document is implemented properly, this can only happen if a document listener attempts to mutate the document. This situation violates the bean event model where order of delivery is not guaranteed and all listeners should be notified before further mutations are allowed"

In my program, a document listener IS attempting to mutate the document (but indirectly).
So I think that my next step is to find a way to release the key in the AbstractDocument object so that the program can edit its text.
I know that when I click on an item in the JList, there is no problem. So I think that if the focus is off the JTextField, the key will be released. So I added the line
cList.requestFocus();
just before the setSelectedIndex(mLSIndex) line. I figured that if cList gets focused on, the user editing of the JTextField will come to an end and the key will be released. But that didn't work. I still got the same IllegalStateException.
 
Michael Dunn
Ranch Hand
Posts: 4632
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
> I WANT the ListSelectionListener to change the text in the JTextField.

just wrap setInptText(..) in a SwingUtilities.invokeLater

just curious, say you have a couple of places in your list
New York
New Zealand

you want New Zealand, type N, so New York should appear in the textfield
how do you get New Zealand to appear
 
Kevin Tysen
Ranch Hand
Posts: 255
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Like this?



About the question of New York and New Zealand,
when you type in 'N' the program chooses one of the Strings that start with 'N'. That choice is based on several factors, one factor being how often each String was chosen in the past; the String chosen most in the past becomes the String that goes in the JTextField.
But suppose New York is the program-preferred String and you want to input New Zealand? The String chosen to go in the JTextField is based on the characters in the JTextField from the beginning to the position of the cursor. So when you type 'N', New York appears. Then when you type 'e', the cursor is after 'Ne' and New York is the String chosen. The same thing happens when you type in 'w' and space bar. But then when you type in 'Z', the only String beginning with 'New Z' is New Zealand, so that becomes the chosen String.
Another thing to do is, once New York is displayed, move the cursor to the right and then type 'Z' after 'New '.
If you want to enter 'New Zeal', type in 'New Z' and then move the cursor and use the delete key to delete 'and'.

Oh, yes, the cursor. I suspect that, when I figure out how to run this without Exceptions, I may have to think of a way to get the cursor in the position that it should be. Right now, input.requestFocus() makes the cursor go to the end of the String in input.

Well, thanks for the help.
 
The moth suit and wings road is much more exciting than taxes. Or this tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic