I have a class that creates a JFrame. When the JFrame is created it has a start button. When the start button is clicked, it runs two threads until the stop button is clicked. The two threads are in another class file. From the class that contains the threads, how can I access the JFrame instance in order to change value that are displayed?
In order to acheive this you have to pass the reference of JFrame using this keyword.
To have access to a private instance within another class, I think you should use agetter.
Example:
//JFrame declaration
private JFrame frame;
//Getter
public JFrame getFrame() {
return frame;
}
As noted by one answer, you can pass in a reference of the GUI or view into any class that needs it, for instance by passing the GUI class into the other class's constructor parameter, and using the parameter to set a field, but having said that, there are caveats:
Always be sure to make Swing state changes on the Swing event thread (the EDT). Since you're using background threading, this means that you will either
use a SwingWorker as your background thread, and notify the GUI of changes via the publish/process method pair, or
your SwingWorker can notify observers of change via PropertyChangeListeners and "bound" properties, or
if using a standard Thread/Runnable, you will need to be sure to queue Swing calls onto the EDT using SwingUtilities.invokeLater(someRunnable)
Even better is to use a Model-View-Control type structure, but even if you do this, the model should be changed on the EDT for the same reasons above.
As a side recommendation in general I try to avoid making classes that extend JFrame as that unnecessarily restricts my code to creating just JFrames.
Note that this help is very general, but if you need more specific help, then you will want to post more specific information regarding your problem and your pertinent code.
Related
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.
sorry guys, but I got confused after many hours sitting ang writting the code.
Situation:
I have two JFrames. These are different Java classes - one of them is the FirstGUI, from which we can call the other JFrame called SecondGUI. OK - that's clear.
I also have one class called Processor in which i have specific methods like "connectToPort" or "disconnectFromPort".
Also, in the FirstGUI (which has the main method) I'm creating SecondGUI object (and set setVisible to false) and Processor object with FirstGUI and SecondGUI as parameters.
Problem:
From the FirstGUI in I want to call out SecondGUI (by setVisible to true) - OK, done. But what about calling out the created at the beginning Processor object from the SecondGUI JFrame? It's important to call the SAME object, because Processor methods can for example set text in the FirstGUI JFrame.JTextPane component, and add items to JComboBox of the SecondGUI.
I don't know how to solve this, I'm always getting NullPointerException.
EDIT:
I want to add that I can't pass the Processor object as an argument while creating SecondGUI, because Second GUI is created earlier and it is an argument while creating Processor... That's the problem.
When constructing the second GUI (child), the initiating class (FirstGUI) can pass self in constructor, and also retain the reference to the constructed object. Now both GUIs have the reference to each other:
class F1 extends JFrame {
F2 child;
void createF2() {
child = new F2(this);
child.setVisible(true);
}
}
class F2 extends JFrame {
final F1 parent;
F2(F1 parent) { this.parent = parent; };
}
If you've searched out your problem or for similar problems on this site, you'll know that the most common recommendation is not to use multiple JFrames, that it is suggestive of a bad design. Better to either swap views with a CardLayout or use JDialogs of the appropriate modality.
As for your question, having one class pass information dynamically to another class, there are two main options depending on program structure.
If one class is in a modal JDialog, then the first class can pull information from the second modal class by calling appropriate getter methods after the second window is no longer visible.
If one class is displayed non-modally, then you'll want to use some type of listener such as a PropertyChangeListener to have the listening class be notified by the observed class when state changes occur.
Edit
Regarding:
From the FirstGUI in I want to call out SecondGUI (by setVisible to true) - OK, done. But what about calling out the created at the beginning Processor object from the SecondGUI JFrame? It's important to call the SAME object, because Processor methods can for example set text in the FirstGUI JFrame.JTextPane component, and add items to JComboBox of the SecondGUI.
Audrius gives you an answer for that. 1+ up-vote given to his answer.
I don't know how to solve this, I'm always getting NullPointerException.
If you get a NPE, should carefully inspect the line that throws the NPE to see which variable is null and then trace back in your code to see why. If your still stuck on a NPE and need our help, then you'll want to show pertinent code and give us more detail on the problem including noting which variable is null and why you think that it shouldn't be null.
EDIT: I want to add that I can't pass the Processor object as an argument while creating SecondGUI, because Second GUI is created earlier and it is an argument while creating Processor... That's the problem.
This is a non-issue. Since the dependent window is displayed dynamically, you can always pass a reference just prior to displaying it using a setter method.
This method is supposed to merge two the definitions of two entries for a single in a glossary. It creates an instance of the GlossaryEntryMergeUI class (extension of JFrame), which walks the user through the merging process. The user clicks a button to submit and the window closes. The merge method extracts the merged definitions and returns the combined glossary entry.
What is the best way to make the merge method wait for response from the MergeUI? I tried using InvokeAndWait, but I couldn't figure out how to make it work.
public GlossaryEntry merge(GlossaryEntry otherEntry){
//First, merge the definitions
GlossaryEntryMergeUI thisMerge = new GlossaryEntryMergeUI(this,otherEntry,mergeSignal);
thisMerge.setVisible(true);
thisMerge.setAlwaysOnTop(true);
GlossaryEntry combined = new GlossaryEntry(word);
combined.addDefinitions(thisMerge.getDefinitions());
return combined;
}
consider to look for CardLayout instead of switch between two or more Windows
if is there Serializable or Observate, then better is wrap the code into invokeAndWait(), for simple switch between two Windows is there invokeLater()
I'd suggest not using two JFrames in same time, one JFrame and another Window would be JDialod or JWindow, because (for example if is there BackGroung Task) sometimes is so hard swith Focus from one JFrame to another, not to move JFrame toFront() ...
This has nothing to do with use of invokeAndWait or invokeLater and all to do with listening on one thread for a response in another. If you're not using a modal dialog for this, such as a JOptionPane (which is quite easy to use and can hold a very comnplex GUI if needed), consider using a listener or otherwise known as the observer design pattern to notify the non-GUI component when the GUI has been acted upon.
Also, is GlossaryEntryMergeUI the only GUI the user comes in contact with? Or is it called into being from another GUI, perhaps a "parent" GUI? If the latter, then a modal dialog, not a JFrame is the way to go. Edit: or a CardLayout as per mKorbel's excellent answer.
If I have a massive Swing component in my application which takes a long time to initialize, and want to display this component in different places in my GUI at the same time, how would I preferably do this?
The GUI user must be able to interact with the different copies of the component
(they could, for example, work as mirrors).
Let's assume that one might want to display copies of this component dynamically, depending on the input of the GUI user (that is, we do not want pre-loading of many copies of the same component).
You need to change your components to access data in a model-view like fashion. Each component would need to point to the same model that would server up the data and do the intensive task once rather than multiple times.
Also, initialization is slowing the GUI, then it sounds like you need a splash screen or a progress bar and the task moved off the EDT.
Is there any way that you could pull the heavy-duty initialization code out, maybe into a '...Factory' class?
I would create a one instance of the component (let's say HeavyComponent) and a custom class extending e.g. JPanel and referencing the component. Let's name it MyContainer. On paintComponent() of the MyContainer I would draw original component into a BufferedImage or use heavyComponentReference.paint(g).
Then on click by the MyContainer I would swap the component replacing the panel with real instance of HeavyComponent and placing in the old location of the HeavyComponent new instance of MyContainer.
display this component in different
places in my GUI at the same time ...
without having to create a new copy of
the same component ... user must be able to interact with the different copies
No way.
How do I call the same instance of a JFrame say A from 5 different JFrames if I need the display of A to be updated every time I call it??
One way is to provide a reference to the frame to each of the 'child processes' and a public method that will update the UI.
Or since it is better not to extend JFrame, a utility class that has a reference to the JFrame and provides the public method.
BTW: Most apps. would have only a single JFrame. The way to handle the situation you describe might be better implemented using JDialogs or JOptionPanes for the 'secondary' windows. Or to collect all the GUI elements together into the main frame: JDesktopPane/JInternalFrames, CardLayout, JTabbedPane..