I have a JFrame and when the user presses a button is displayed an input jdialog. I need the jdialog to be in non-modal mode and once the user presses ok,
I want to do some action based on the input. Right now I pass my view as reference in the jdialog, so that when the user presses ok, the jdialog calls a method
of the view. Is there a more standardized way to handle this or this is the only way?
I need the jdialog to be in NON-modal mode
Thanks
You can pass a java.lang.Runnable to be called from the JDialog when the user presses the ok button. In this way you can put the code you want to run inside the Runnable itself.
Your current approach using a callback is straightforward, but the observer pattern is commonly used to decrease the resulting tight coupling. Two implementations are typical in Swing:
Arrange for your view to implement the Observer interface and have your input window delegate to a contained instance of Observable. The notifyObservers() method may be used to pass an object reference to the Observer. A very simple example may be found here.
Have your input window maintain an EventListenerList using a custom event in which the view registers interest. Data of interest to the listener can be passed in the event itself. It may be convenient to reuse an existing javax.swing.event or model the custom event on such a type. Every JComponent contains an EventListenerList.
Related
I always use one ActionListenr for a button, but I find that one component can be assigned multiple action listeners. How we can do that and what is use of it
Thanks in advance
c.addActionListener(actionlistener1);
c.addActionListener(actionlistener2);
It is useful if you need to do several actions that are not necessarily correlated. For example, changing the background color of a button vs appending the action in a Logger vs informing the controller that the button have been pressed, etc...
This allows to be modular: each actionListener can handle a very specific task for a group of components. For example, you can write a default actionListener for all your buttons, and a specific one for a group of buttons that have the same behaviour.
Finally, some objects already have listeners when you instantiate them (JButton have a default FocusListener, JScrollPane a default MouseWheelListener, etc). This allow you to add other behaviours to your components, without overriding previous ones.
How we can do that
That's the easy part, create multiple instance of ActionListeners and use addActionListener. One would assume that they are all different...
and what is use of it
That's a harder question. One could assume that you would use multiple listeners when you want to apply newer logic to the process but not extend from the existing functionality...
Let's say you have a login form. You have a "Login" button. You write an ActionListener to gather the required details and validate them.
Later on, you decide that the button should be disabled during that process. Normally, you would add that functionality to the original code, but for what ever reason (it's not your code etc), you can't.
You could create another ActionListener whose sole purpose was to disable the button when it was pressed.
As an example...
I am starting to write some code in Java Swing and I am getting a little bit mixed up in the hierarchy of listeners that swing offers. Namely I wanted to know when to use, for instance, an ActionListener over ListSelectionListener and how to differentiate when a particular listener gets called from the UI i.e. after what user interaction.
Thanks very much for your responses.
About ActionListener
An action event occurs, whenever an action is performed by the user.
Examples: When the user clicks a button, chooses a menu item, presses
Enter in a text field. The result is that an actionPerformed message
is sent to all action listeners that are registered on the relevant
component. reference
About ListSelectionListener
List selection events occur when the selection in a list or table is
either changing or has just changed. List selection events are fired
from an object that implements the ListSelectionModel interface. To
get a table's list selection model object, you can use either
getSelectionModel method or getColumnModel().getSelectionModel(). reference
Q. how to differentiate when a particular listener gets called from the UI i.e. after what user interaction.
The above details and the references contains much information to get start with.
ActionListener is used e.g. for JButton, it tells just that the GUI-element has done something (a button can not do anything except be clicked).
ListSelectionListener contains more information (which element has been choosen).
For more information on when to use which Listener check the javadoc of the element you want to use.
I'm building my first Swing app and am trying to figure out how my JDialogs - exclusively invoked when the user selects a JMenuItem - can update the components in the main client area of the JFrame which is the parent "window" of the whole app.
This is the design I've come up with, but don't know if its: (1) just plain bad, (2) not the standard (thus best) way, or (3) if I'm totally off-base here. Any suggestions are enormously appreciated.
Basically, the user selects a JMenuItem, which launches a JDialog. The user interacts with the components on the dialog, and then clicks "Done". If everything validates, the JDialog closes, and I want the parent window (a JFrame) to have its state updated (and eventually rippled out into its components).
My design:
Have an AppStateController that is a member of the JFrame subclass (my application). I would then create an AppStateChangeListener and AppStateChange EventObject subclass so that whenever a dialog validates and closes, it fires an AppStateChange event. Since the parent JFrame is the only registered listener to that event, I could define a handler that gets the event passed to it. I would make sure the AppStateChangeEvent had enough metadata to describe all the possible changes.
In theory, I like this approach: it should be clean and free of "spaghetti"-type calls to multiple controls every time a different event fires. However, I fear it may be overkill.
What do best practices dictate here? I'm not really a GUI person!
Java has several ways to implement the observer pattern; several are discussed here.
The mechanism prescribed by EventListenerList is probably the most general, as it would allow you to define your own event and listener types, and it is familiar to Swing programmers. Instead of making the JFrame a listener, let the highest level JComponent do so. Each instance of JComponent has a suitable protected member, listenerList.
Bound Properties are also an excellent choice, as shown here.
If you go with Observable, you'll need to use a delegate.
Addendum: As concrete examples, jfreechart uses the EventListenerList scheme to manage chart, dataset and series events. In contrast, jcalendar uses bean properties to notify listeners of widget selections.
I have this main JFrame (call it DrinkChooser) that shows another complex confirmation JFrame (call it ConfirmWin).
The ConfirmWin has only two JButtons, confirm and cancel.
I want to do this:
(in DrinkChooser, assume drinksChoosen is a Drink[])
public void handleAction(){
int choice = ConfirmWin.showDrinkConfirmation(drinksChoosen);
if(choice == ConfirmWin.CONFIRM)
//Handle confirmation.
else
//handle cancel, do nothing.
}
I want to achieve an effect that is as close as possible to the "JOptionPane effect", which is that the original DrinkChooser gets suspended, and the ConfirmWin returns the choice of the user.
Thanks.
Have a look at the trail How to Make Dialogs.
A Dialog window is an independent subwindow meant to carry temporary notice apart from the main Swing Application Window. Most Dialogs present an error message or warning to a user, but Dialogs can present images, directory trees, or just about anything compatible with the main Swing Application that manages them.
For convenience, several Swing component classes can directly instantiate and display dialogs. To create simple, standard dialogs, you use the JOptionPane class.
Here is a possibly related question:
Java - How to create a custom dialog box?
Don't forget that the value argument of all JOptionPane.showXXXX methods can be a JComponent. If you pass a component (in your example it might be a JList with a custom renderer), it will be embedded within the dialog and can be used to customize the appearance.
First, let it be known that I'm new to java and it's quirks. I'm a seasoned programmer with various languages, which may be why I'm stuck...
I have an application that, possibly due to poor design, spawns new JFrames through the users' work-flow. My question is, if there is an event in a spawned JFrame, is it able to contact and pass data or an event to it's parent?
I have read that using a JDialog seems to be the way to design, but let's assume that's not an option. Essentially, JFrame1 contains a JTable with a list of data. An action spawns JFrame2 and a user "does something" that impacts the data in the list in JFrame1. Upon closing JFrame2, is there a way to control the JTable based on JFrame2's close event?
It's a pretty basic concept, I just can't seem to find the mechanism that would allow such an action.
Thanks!
You can use "listeners" to listen for various events.
It sounds like you might want to start with How to Write a Window Listener.
I have read that using a JDialog seems to be the way to design, but let's assume that's not an option.
Why? The code is the same and JDialogs where designed for this purpose. What is the specific requirement that says you need to use a JFrame?
An action spawns JFrame2 and a user "does something" that impacts the data in the list in JFrame1. Upon closing JFrame2, is there a way to control the JTable based on JFrame2's close event?
This is a common design. The user selects a row to change or update and a model dialog is created to display all the data so it can be changed. When the dialog is saved the data in the table is updated. If this is your requirement, then you can just pass in the TableModel to the dialog. Then when the dialog is closed you update the TableModel and the table will be repainted automatically.
You would have to capture the window closing event using a window listener. The window listener would also need a reference to the data that needs to be changed.
In addition to using Window.addWindowListener() on either a JFrame or a JDialog, consider using a model-view approach. Have the close event modify the table's data, rather than the table itself. Use AbstractTableModel as the model for the table, and listen for changes to the data.