I have a public JFrame with a CardLayout, this JFrame includes some JPanels for different stages of analysis, I want to return to the main panel and erase all data stored in the objects to start a new analysis using a JMenuItem, but I don't know which function could do that. Any suggestion?
I have tried with this code, a jMenuItem1ActionPerformed which just backs to that jpanel but doesn't reset the gui. "Seleccion" is the main jpanel, the main menu of the application
panelPrincipal.removeAll();
panelPrincipal.revalidate();
panelPrincipal.repaint();
panelPrincipal.add(seleccion);
panelPrincipal.revalidate();
panelPrincipal.repaint();
There is no "one-size-fits-all" solution, and there is no core Java "function" that you can call for this since it all depends on the structure of your program. In other words, you will have to create your own reset mechanism. Hopefully, your program structure is built around an Model-View-Control (MVC) type of pattern, and if so, then your JMenuItem's listener would notify the Control of the user's wish to reset, the Control would call reset() on the Model (a method which you would have to create of course) which would reset the Model to the initial state. The View which should have listeners attached to the Model will then change its display accordingly.
From your codes you probably tried every means you can think of to reset everything to initial state.
Personally, I do not think it is a good idea to remove all Components and add it back simply just because you want to reset it. You have to write your own codes to specifically tell Java what things need to change (reset).
For example if you have 3 text fields, you can do it in your action listener:
public void actionPerformed(ActionEvent e){
txtField1.setText("");
txtField2.setText("");
txtField3.setText("");
}
Doing this works, but it looks pretty much hard-coded and it is hard to maintain. Image if you have 999 textfields to deal with. You can always improve your program structure for example like:
input --> update database --> text fields read from database
Input updates database. The fields just read from the database. If you want to reset everything, just clear of the data in the database.
public void actionPerformed(ActionEvent e){
//Delete records from database
//Instead of updating all 999 fields.
}
This is just an example. It is up to you to decide how your program shall be structured.
repaint() basically just inform the paintManager to call the paintComponent() method, you probably won't see any difference in your UI appearance for calling that unless you have been doing things like overriding paintComponent() and making changes to the look and feel of the JComponents or using Graphics for drawing.
Related
I have created a swing application in Netbeans environment. This application consists of four frames. Now my requirement is, after filling A frame when user clicks "Next" button then A's data should be buffered somewhere and then go to second form and so on. Finally when user lands in the last form, at this point i want the total data of all forms should be stored in database.
I am not sure how to achieve this. Can anyone suggest some useful resource or idea?
Consider having one non-GUI model class, that can be passed into the view (GUI) classes, either via a constructor parameter, or a setter parameter, i.e., public void setModel(Model model). Then all views can have the same Model instance passed into them.
When the first window has its data "submitted", it submits it into the one shared model. If you're using a Model-View-Control structure, then this is usually done by the Control, but if your program is simple, a Model-View is probably all you need. The other windows can be notified by the Model of the changed data, and then change their displays accordingly.
But as an aside, also please ask yourself, how many professional applications do you use that jump from window to window? Not many because it is a very distracting and often unpleasant experience for the user. Most use a single main application window that swaps gui views within this window and with an occasional dialog window popping up when information is needed in a modal fashion. Please have a look at The Use of Multiple JFrames, Good/Bad Practice?
I've set up a Server which runs and accepts connections from my Remote Client, and now I'm working on my GUI.
Before anything else, my goal here is to create a nice looking client that will have a login screen (login/pw), and then a nice layout with my options/perhaps a chat box after the user has logged in.
I've searched a lot online and used this site to set up my server and get things working, but I've got a bit of a problem with the GUI/theory and hope someone here can guide me a bit.
At the moment, I've set up a class called ClientGUI which is called from my main class, and this produces a 420x240 size screen. After placing my login/password JTextField boxes here, is it "proper" to set up the other GUI's the way I've outlined below? I'm not sure if I should be putting them under one class or how I would advance from one GUI to the next. I'm thinking I should repaint and resize the screen as necessary, but I am not sure how to set it all up. A brief outline would be helpful (you don't need to give me exact code).
public class ClientGUI extends JFrame {
public ClientGUI() {
setSize(420,240);
setVisible(true);
setTitle("Title");
setResizable(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
}
public loginGUI() {
//code for my login/pw boxes, images, listener for entering information
}
public afterlogginginGUI() {
}
paint() {
//not too sure about how this should be setup either. Should I do all my textfield
//and image work in paint()?
}
}
I have never made anything like this, so I have the feeling I'm not setting this up in an ideal way.
An alternative is to have a different java class extending JFrame for each 'screen' I want, but if I do it this way, would I do it like this?
In my main RemoteClient class:
main {
ClientGUI();
//display whatever
LoginGUI();
//listen for login info
if (loginIsValid) {
afterlogginginGUI();
}
}
I think you're thinking in to much of a linear fashion, where the code flows from A then to B then to C ... where in fact, Swing (and GUI's in general) are event driven...
C happens, so you do B, which triggers F so you do E ...
Start by creating a JPanel, onto this add your JTextField and JPasswordField, this will act as you basic login view. You could then add this to a JFrame or JDialog depending on your needs. You will need some way for the user to either "cancel" or "validate" their credentials.
Typically, I do this a separate view, as I never know where my poor "user details" pane might end up, but you could do this a single view (including the buttons within the "user details" pane), that will come down to your requirements.
You can use a CardLayout to switch from the "login" view to the "application" view. This has the benefit of maintaining only a single frame and prevents windows from been splashed all about the place...
I would, personally, separate the core functionality of the views to separate classes, this means you can simply create an instance when you need it and add it to whatever container you want.
I would recommend against extending from JFrame directly. This locks you into a single container (making it hard to re-use components or extend the program later) and you're not adding any new functionality to the class anyway...
Start by having a look at Creating a GUI With JFC/Swing.
You'll probably also be interested in How to Use CardLayout, How to Make Dialogs, How to Use Buttons, Check Boxes, and Radio Buttons and How to Write an Action Listeners
You'll also need to have a look at Laying Out Components Within a Container
Because you're likely waiting for a response from the server at some point, you will need to have a look at Concurrency in Swing and Worker Threads and SwingWorker wouldn't hurt
I want to fill values of multiple jTextBox from a jFrame into another, using accessor methods like
String getNameVal()
{
return jTextBox1.getText();
}
How to call these methods from another jFrame?
Suggestions:
It sounds like your GUI code is geared towards making JFrames, and if so, you will want to avoid this. You are painting yourself in a corner by having your class extend JFrame, forcing you to create and display JFrames, when often more flexibility is called for. In fact, I would venture that most of the Swing GUI code that I've created and that I've seen does not extend JFrame, and in fact it is rare that you'll ever want to do this.
More commonly your GUI classes will be geared towards creating JPanels, which can then be placed into JFrames or JDialogs, or JTabbedPanes, or swapped via CardLayouts, wherever needed. This will greatly increase the flexibility of your GUI coding.
This question has direct bearing on your problem. I will guess that your main problem isn't how to give classes getter methods, and how to have other classes call the getter methods. More often then not, when faced with the issue of extracting information from one GUI view to another, the issue is one of when to extract the information. If you displayed your second window as a non-modal JFrame, and then had the calling class immediately extract the data from that second JFrame, you'd get nonsense data, because you'd be extracting data before the user would have time to interact with the 2nd window and enter data.
One possible solution to this when using non-modal windows to get information from the user is to use a WindowListener so you can be notified when the user has completed his dealing with the second window, and so now data can be safely extracted.
Often better is for the 2nd window not be non-modal, as JFrames are, but instead to be a modal window such as a modal JDialog. When the calling code displays a modal dialog, all code flow in the calling code stops until the dialog is no longer visible. In this situation, no WindowListener is needed since you will know exactly when the dialog has been dealt with -- on the code line immediately after you set it visible -- and so can extract your data from it with ease.
A nice variant on this has already been mentioned in by Andrew Thompson in comments -- use a JOptionPane. Don't poo-poo this option since JOptionPanes are powerful tools, likely much more powerful than you realize as they can hold fully formed complex JPanel views, and behave just as described above, as modal dialogs.
If you need more specific help, then please don't hesitate to comment to this answer. Also if so, then consider creating and posting a Minimal, Complete, and Verifiable Example Program where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem.
Edit
For my mcve code examples of the above suggestions, please my answers to the following StackOverflow Questions:
Using a modal JDialog to extract information
Using a JOptonPane to extract information
I assume the textfields are present in frame1 and you want to access them in frame2. The following can be a way to achieve this:
First create getters for all JTextFields that you have in your frame1. Alternatively you can have them in a panel and call getComponents() method.
Create a private variable of JFrame type in your frame2.
Modify the constructor of frame2 to receive the frame1 object and assign it to the private variable of JFrame type.
Now you can create a close() method in frame2 which disposes the frame2 and sets frame1 to visible.
But in my opinion you should create a class which handles the data in these textfields. Initialize the class object in any button click of frame1 and check for any inconsistency in the input. I can guess there is something wrong with your design.
How do buttons in software written in Java work?
For example the above screenshot: when the user clicks different buttons, different algorithms are run on user-inputted data (it's a data analysis application) and the output is displayed. Just getting started writing Java GUI's though, it all seems like magic to me -- is there one ActionListener for every pane? Does it listen for different ActionCommands of the different buttons and execute the algorithm right within the actionPerformed() method (it seems a little nonintuitive to me to execute an algorithm in a method independent of data...i.e. the button doesn't know what data it's dealing with?). So far, all the action listener tutorials I've read online have merely printed something when the button is pressed...
What's the general structure for connecting button, actionlisteners, and actual actions performed in the background?
Thanks in advance.
The usual way is to have one action listener per button. The Statistics panel has access (via one of its fields), to the data it needs to read and modify). So, the handling of the first button in this panel could look like:
private void initButtonListeners() {
this.averageDegreeButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
computeAverageDegree();
}
}
// other buttons...
}
And the computeAverageDegree() method could look like
private void computeAverageDegree() {
double result = this.statistics.computeAverageDegree();
this.averageDegreeLabel.setText(formatDoubleToString(result));
}
My personal preference is to do almost nothing in the UI, but move it all to the model/controller side (not sure what the best name is as it is seldom pure MVC).
I think that everything you do in the UI should be doable through the API as well. Benefits are easier testing, redesign of the UI is possible without messing up your logic, easy to perform the heavy work on background threads, ... .
A good read describing this is the Humble Dialog article. Not really Swing specific, but applicable to all sort of UI's.
To answer your questions:
is there one ActionListener for every pane?
No, typically you have an Action (or ActionListener) for each button. I prefer to use Action instances as they are far more reusable then the typical anonymous ActionListener (and easier to test as well)
Does it listen for different ActionCommands of the different buttons and execute the algorithm right within the actionPerformed() method
Certainly not. Doing heavy calculations in that method will block the Swing UI thread (the Event Dispatch Thread), which results in a non-responsive UI while the calculations are ongoing. Showing progress becomes also impossible. Calculations are typically done on a worker thread, launched when your Action is triggered (for example using a SwingWorker). This is explained in the Concurrency in Swing tutorial.
it seems a little nonintuitive to me to execute an algorithm in a method independent of data...i.e. the button doesn't know what data it's dealing with?
The button should not know about the data. The data is typically stored in the model. The UI is only displaying it, but does not contain it (unless it is input just provided by the user). The button should just know what to call on the model. The model does whatever it has to do and fires an event. The UI picks up that event and updates itself.
At least, that is how Swing is designed (for example JTable and its TableModel). I so no good reason to not follow that model when making your own Swing UI's
I have built a GUI displaying a matrix. It looks much like in excel where you have labels on the first row and first column. The cells contains either 1 or 0.
There's a JComboBox below the matrix. I can select an item from the JComboBox and click a button "add". This adds an extra row to the matrix with the JComboBox item as its name. My question is how i should handle expanding this.
Is it a good idea to have a method that redraws the whole window? Or should i try and just redraw the part that's been changed?
I thought of having a method like updateWindow() that could be used both for initiating the window and updating it if i make changes.
Is it a good idea to have a method that redraws the whole window? Or should i try and just redraw the part that's been changed?
It depends on what's in your window.
If you're drawing on a JPanel, by overriding the paintComponent method, redraw the entire JPanel. It's not worth the effort to try and redraw a part of a JPanel.
If you have a window made up of many JPanels, you can redraw just the JPanel with the changes.
I thought of having a method like updateWindow() that could be used both for initiating the window and updating it if i make changes.
It's generally a good idea to create methods to perform specific GUI tasks. I'd have separate initializeWindow and updateWindow methods for my own sanity. I usually separate the initialization of my GUI from the update of my GUI.
Read this excellent article, Sudoku Solver Swing GUI, to get an idea of how to put together a Swing GUI.
When you add components to a container, you will be invalidating that container's layout. This will automatically trigger a repaint, so the question becomes moot.
The real question becomes why?
Instead of messing about with labels and fields, you should just simply use a JTable. Check out How to use Tables.
This is optimized for performance, so if you're really concerned, this should provide a better solution, so long as you are firing the correct events to the required changes.
Unless you're finding yourself performance bound, I see no real reason not to redraw the entire window; sure there will be a performance hit but it should be negligible and your source will be simpler and easier to maintain. However, if you're finding yourself pressed for performance, I would suggest looking into implementing a "dirty rectangles" method of redrawing (i.e. your second approach).