Update jtextfields in jpanel when other jtextfields changed - java

i have a GUI with some jtextfields (for example jtextfield_a, jtextfield_b, jtextfield_c, jtextfield_d, jtextfield_e). I can't find a way to change the value of jtextfield_d and jtextfield_e when for example jtextfield_a value is changed. Any way to do this?

You could...
Use an ActionListener on the JTextField you want to monitor
See How to Write an Action Listener for more details
Cons
Requires the user to press the "action" key (typically Enter) while the field is focused
You could...
Use a FocusListener on the JTextField you want to monitor
Cons
Requires the user to leave the field, so the focusLost event can be triggered
See How to Write a Focus Listener for more details
You could...
Use a DocumentListener on the JTextField you want to monitor
See How to Write a Document Listener for more details
Pros
Provides real time feedback as the user types
You could...
Have some other control trigger the update, like a JButton, so the user gains greater control over the process. It's not always the best from the users perspective (because we're lazy), but is among the simplest

Related

Design for a component with 2 listeners and 2 "setters" (Swing application)

I'm making a map editor using java swing for my tile based java game. the swing application has two major components, the "upper" component is the game map preview, and the "lower" component is modifyable properties of the map, like its height and width.
Currently the user types in to a jtextfield for the map width, then I use a change listener to set that value to the GameMap object. The GameMap object when changed fires a notification event to GameMapListeners, the primary listener it has is the preview display of the map inside the swing application.
This lets the user change the map width and instnatly see the results in a preview pane.
Now I want to go to the other way. I want the user to be able to click and drag the edges of the map in the preview pane, but then the results need to then be sent to the properties panel so it shows the updated width value.
This is where the problem is, if I update the jtextfield it'll fire a change event, which would update the GameMap and update the preview display, and then that would fire an event that changes the jtextfield again (so on and on until the program crashes due to stack overflow)
Are there any kind of design patterns i could use instead, or is there some common way to solve this issue?
In this type of case, you have at least two choices...
You Could
Remove the listener to the other component when you want to trigger a change, adding it back after you've raised the event...
You Could
Change the state of a flag to indicate that you should ignore any changes that might come in, resetting after you're raised the event...
Which one you choose will depend on how much code you want to add and how readily available the reference to the listeners in question are (ie, if you don't have a reference to the listener you want to remove, it's kind of hard to implement)
If I update the jtextfield it'll fire a change event, which would update the GameMap and update the preview display, and then that would fire an event that changes the jtextfield again (so on and on until the program crashes due to stack overflow).
When you have a situation like this, you can temporarily remove event listeners, fire the change event, and add the event listeners back. Yes, this is as much of a pain as it sounds, but it's a good way to prevent the stack overflow.
You can see a detailed explanation as well as a working example of managing event listeners in my Sudoku Solver Swing GUI article.
You can use action events for a JTextField. Action events don't trigger when you change the component programmatically.

Instanceof, Enum Or Multiple Listeners for JButtons

On my swing GUI I have lines of data and a number of buttons, the user selects a number of items and then then selects a button.
Each button applies a different rule to the data and so different functions need to be called for every button, I'm using an MVC design pattern and my question is such, How should I handle the different needs of every button?
Create a class 'MyButton' which extends JButton then give this some sort of Enum, I can then create 1 action listener and then check which button has been pressed in the ActionListener by inspecting the Enum.
Similar to above but with a different class for each button then using instanceof to determine which has been pressed.
Implement a separate ActionListener for each button
Other?
Which is the best method to use if any? Any advice would be greatly received!
Implement a separate listener for each button.
First because it's the usual solution. Second, between there's no reason to extend JButton just to do something else when it's clicked. That's the role of the ActionListener. Swing components are designed to be used as is, and you should generally not extend them.
It's MVC: you separate the logic (in Actions) and the view (the button).
There is no need to use an enum or to subclass JButton. What you can do to keep things clean when you have dozens of buttons, is a factory class to create Action instances.
If I get your question correctly, you mean to say, you have a data in line items and every line items have a button, which when pressed invokes a rule pertaining to the line item.
If so, then
If you take the 2nd approach, you need to code inside your action listener every time a new line item added in future.
Third approach will also have same implication as above
First approach sounds quite good. You can have a Factory which may have a hashmap keyed with the enum variables and the respective rule. Inside the action listener get the rule from the factory and invoke it.
This way you get a proper separation of concerns and your action listener will act as a controller, having no knowledge of rules and data items.

Enable a Jbutton after all Jtable fields are filled

I have a Jtable with editable fields and a Jbutton. I want my button to be disabled until all table fields are filled. After all fields are filled I want the button to be enabled. How can I achieve this?
Thanks for the help.
two options:
implement a TableModelListener which checks if the condition is met, and if so enabled/disables the button
implement a custom TableModel which does the check itself and fires a PropertyChange if not/filled. Listen to that property and enable/disable as appropriate
The latter is the better option, because it's really up to the model to decide about its own state.

How to transfer focus a custom component when traversal keys are disabled?

I have created a custom JComboBox with a custom popup that implements the KeyListener. I wanted an item to be selected from the popup of the cmbBox on the press of either Tab or Enter hence I set the setFocusTraversalKeysEnabled(false) for both the combobox and the popup.
The problem with this approach is that now I have to add another KeyListener to the combobox when I use it in containers so as to shift the focus.
Can I fire a transfer focus event(hypothetically) or something like that within my custom JComponent which will transfer the focus in its parent component so that I dont have to add key listeners everywhere I use it. I have used transferFocus() but it is not transferring the focus.
I have not dirtied my hands on Key Bindings yet but is there a key binding to transfer the focus?
Thanks
I am trying to recreate a sscce but its proving difficult. Please bear.
Basic Listeners lifecycle is about to add required listener if is really needed, and remove Listener if is useless
I'd would be suggesting use KeyBindings, because this Listener is designated for Swing JComponents and sure you can (sure same as for KeyListener) add this listener to the concrete JComponent or its derivate(s)
you can add Listener to the derived popup on firePopupMenuWillBecomeVisible
you can add ItemListener to the derived JList
maybe not correct way but protect all defects implemented to the KeyListener, that only Focus owner can take events from keyboard, sure workaround for KeyBindings os more that settable and confortable
notice please read this answer

How to avoid infinite update loops in Swing?

I have a JPanel with a set of items (for example combo boxes and text fields). Some action listeners are implemented on those items to register user updates.
If the user selects a value in a JComboBox (for example), the action listener captures the event. The corresponding underlying bean method is called and the panel is refreshed. Changing can have an impact on other fields displayed in the pane.
The problem is that when the panel is refreshed, all listeners are triggered, and they call for a refresh themselves. This leads to an infinite loop.
How can I avoid this? I can't get rid of the listeners, because I need to capture user updates, but I don't want these to fire when I am only refreshing the panel content.
One option is to have a central boolean value or some indicator that each listener can check to prevent the chaining of events.
Another option is to not refresh the field if the value does not change. That way each component is updated at most once per refresh.
I can't get rid of the listeners, because I need to capture user updates, but I don't want these to fire when I am only refreshing the pane content
Then remove the listeners, refresh the pane content and then restore the listeners. This way the listeners only fire when a user change is made.
I think that if your problem is in combobox it just points to a bug. Really, if user changes the value of the combobox, that somehow triggers refresh of the pane the value of the combo box should not be changed second time! So if it is onValueChanged() (or something like this) it should not be called at all when pane is being refreshed.
But if for some reason it happens you can verify whether the old and new values are the same and exit the listener.
If this still does not help I'd suggest you some non-standard solution: try to investigate the stack trace into the listener. Can you identify whether the listener was called as a direct reaction to user's action or after the pane refresh? In this case you can create utility method and put it in the beginning of all relevant listeners.
My applications also suffered from this problem, and solution with the flag, that I should check in every listener and enable/disable in code, feels not very good for me. I always forgot to set this flag to true/false in necessary places.
That is why I decide to implement another solution.
I just subclass all default swing components that I am using often, and implemented custom ValueChanged event that I fire after mouse/keyboard/clipboard/etc events. Now I am always know, that if ValueChanged event is fired, it means, that value was issued by user, not by code. Event handling in this way much more cleaner. This solution solves my problem.

Categories

Resources