What is an efficient method to have a window change into a different window? When the user presses the next button, I would want it to perform another method that would create this second window. What is the appropriate listener class for this scenario?
An example scenario for your question:
You may have a JFrame which is the starting point of your application, i.e. having single instance, main method, general initialization of components etc. You say you want to change windows. Let these windows be different JPanel objects that each of them are assigned to operate on different tasks. You can add these panels to your main frame. And changing these panels upon certain conditions will make your application capable of navigating between these panels/windows as well. So how to make this happen? Take a look at CardLayout and use it to navigate between your predefined panels on their container frame.
What is the appropriate listener class for this scenario?
Take a look at this post, I have demonstrated CardLayout usage via ActionListener.
What is the appropriate listener class for this scenario?
An ActionListener. See the links already provided in comments, for how to use one.
Related
I am developing a Java Swing-based application with different perspectives. For the "main menu" perspective I do not want the window (JFrame) to be decorated, while in other perspective I do want the window to be decorated. In other words, I need want to change the decoration attribute dynamically.
I have tried to use setUndecorated(false) and setUndecorated(true), but I seems I can only set this once, before actually showing the window.
Is there a way to achieve this?
From the javadoc:
Disables or enables decorations for this frame. This method can only be called while the frame is not displayable.
Therefore, once the JFrame is packed and/or displayed, you can no longer change that value. If you want to change the undecorated state of a JFrame you will need to dispose() it first, then change the state and eventually make it visible again.
After all, I had to take a different approach.
The former solution did work, as I stated in my last comment.
However, it was showing the default LAF window decoration, while I was using a different LAF.
So the result was graphically inconsistent with the rest of the LAF. Finally, I came with the right solution, I used setUndecorate(true) for my frame. Then, when I had to change my perspective to one using decorations I simply had to use the following code
contentPane.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
And when I had to revert to the non decorate perspective, I use
contentPane.getRootPane().setWindowDecorationStyle(JRootPane.NONE);
This approach didn't need to dispose the window and show it again (which actually produced a brief but still visible hide/show of the window)
Say I have various JFrames open in the same application. Is there a way to perform some action (like update a JTable) when the user changes the focus on one frame to another (like clicking the bar on the top)?
If not is there a way to perform an action on one JFrame when she closes another JFrame?
Please read: The Use of Multiple JFrames, Good/Bad Practice? to see why your program design could very well be improved
As for your main question,
Is there a way to perform some action (like update a JTable) when the user changes the focus on one frame to another (like clicking the bar on the top)?
It's really a specific example of a more general question:
How do I change the state of one object through an event that occurs in another object
and there are several possible solutions
Easiest would be to have the code that handles the event have a reference to the first object, here one of your JFrames, and simply call a method on it when the event is triggered.
Better is to structure your program with an MVC (Model-View-Controller) type structure, and in the event code (the control code), change the state of the model. View listeners to the model, including the JFrame you wish to change, would then be notified and would change their appearance based on the model.
Some general recommendations:
Having a bunch of windows displayed and swapped is very annoying to the user. Have a look at my link above to look for other possible options.
You'll probably want to avoid having class's extend JFrame, as that forces you to create JFrames with that code. Much better is coding to the JPanel, not the JFrame, and then placing the JPanels created wherever they are needed, be it within a JFrame, or in another JPanel, or swapped via a CardLayout, or in a JTabbedPane, a JDialog, a JOptionPane...
I am developing a Java Swing-based application with different perspectives. For the "main menu" perspective I do not want the window (JFrame) to be decorated, while in other perspective I do want the window to be decorated. In other words, I need want to change the decoration attribute dynamically.
I have tried to use setUndecorated(false) and setUndecorated(true), but I seems I can only set this once, before actually showing the window.
Is there a way to achieve this?
From the javadoc:
Disables or enables decorations for this frame. This method can only be called while the frame is not displayable.
Therefore, once the JFrame is packed and/or displayed, you can no longer change that value. If you want to change the undecorated state of a JFrame you will need to dispose() it first, then change the state and eventually make it visible again.
After all, I had to take a different approach.
The former solution did work, as I stated in my last comment.
However, it was showing the default LAF window decoration, while I was using a different LAF.
So the result was graphically inconsistent with the rest of the LAF. Finally, I came with the right solution, I used setUndecorate(true) for my frame. Then, when I had to change my perspective to one using decorations I simply had to use the following code
contentPane.getRootPane().setWindowDecorationStyle(JRootPane.FRAME);
And when I had to revert to the non decorate perspective, I use
contentPane.getRootPane().setWindowDecorationStyle(JRootPane.NONE);
This approach didn't need to dispose the window and show it again (which actually produced a brief but still visible hide/show of the window)
I wonder whether there is a possiblity to change the visibility of more than one item (textbox, button, chart ...) in a JFrame in one simple(?) command.
Thanks for answers and ideas!
(Hiding the whole JFrame is no option ;))
You could use a CardLayout, as shown here.
Obviously, one of the two panels shown in the demo would have no components.
Place all into a panel and hide/show the panel. That should propagate to all child components as well
Place components into Collection, then you can use simple iteration to set/clear any flags. You need to create a Collection and add objects to it, but this allows to separate visibility control from the component layout.
My first problem is: "how do I limit the amount of Swing Actions (using the AbstractAction as a base for other actions) when the same actions are used in conjunction with different UI components that are referenced with different Swing JPanel objects that (seem to have) no direct reference to eachother"?
My second problem is: "how to keep referenced between Actions and UI components when the actionPerformerd() method of the action uses TWO or more different UI component references"? I need ui context within the actionPerformed() method at different places that have no direct relation (well, at least that is what I think).
Let me explain my design concerns I am dealing with...
I have one JFrame which holds all UI logic. This JFrame holds three different references to JPanel logic: a ControlPanel, a MainPanel and a StatusPanel (all extend JPanel).
The ControlPanel sets up the JMenu and items, the JToolBar items and this JPanel is added to the contentpane with all the approriate Actions installed.
The MainPanel is where the actual communication with the user takes place. This JPanel holds a CardLayout with a bunch of JPanels inside it.
The StatusPanel is actually a statusbar dealing with all kinds of text messages coming from differnt JPanels, but processed by a StatusBarManager object. No fancy stuff here, just boring gui stuff.
Now the problem part: I first programmed a bunch of extended AbstractActions for each action I could think of (not so good idea). Next I programmed an ActionFactory that hands out an Action obj for a particulair task, like: ActionFactory.getAction("file.new");
This seems like a better approach because I now can instantiate a FileAction object for all "file" operations with one difference: the implementation of the actionPerformed() method. This "seems" a good idea because when I call in a different JPanel the same ActionFactory.getAction("file.new"); I get the same Action object returned that already was instantiated before (saves a lot of duplicate objects).
Well this might seem a good idea, I still struggle with the context of the JPanels. When I select a "card" to display within the MainPanel using the JMenu and JMenuItems, I am in the ControlPanel ui context only and in the actionPerformed() method I do not have the MainPanel context to set the "card" using the CardLayout of that JPanel.
The same goes for when I am in the MainPanel (pressing a button) and have no context of a StatusPanel.
I have looked at these previous suggestions on stackoveflow, but somehow I can't make the connection. I am missing the clue...
Sort of same Q&A over Actions at SO:
here, here, here, here, here, here, here, here, and here .
Some suggested to use a framework for this like the appframework or eclipse rcp or the spring rcp, or others. BUT I prefer to not use any frameworks at all for several reasons other than what is available in the default JVM 6.
I hope someone can shine his/her light over this matter that helps me find a good solution for my problem. Thanks for your help in advance!
I think the main flaw in the design you describe is that the actions work directly against the UI, instead of against a model/controller.
If your action just updates a model, and each view part keeps itself in sync with the relevant part of the model, you avoid those dependencies between one action and several other view components.
This also allows to share the common logic. You move that logic from the action to the model/controller, and the action becomes basically a one-liner (calling that logic).