Button opens new JFrame multiple times. How do I stop this? - java

I am using to different classes: one holding a main JFrame with a button, and one holding a new JFrame that is called upon at a button press.
if( event.getSource() == noteBtn ) { MiniPad.pad(); return;}
(MiniPad.pad() references the class and pad() method on the new JFrame)
When I removeAll() on the JPanel that hosts the button, and then revalidate() and repaint(), the button opens the JFrame multiple times, which isn't what I want it to do at all.
Is there a way to tell the MiniPad class that you can't have more than one copy of the JFrame open at any one time? I extend the JFrame by the way, in case that's any help.

Edit: Everything below is valid programming knowledge, but you might also want to consider having MiniPad extend the JDialog class instead. I haven't used it before, but its implementation looks a lot like JFrame. You might not actually have to change much in your MiniPad class. The documentation is here: http://docs.oracle.com/javase/7/docs/api/javax/swing/JDialog.html
If you're wondering why, check out Andrew Thompson's post here.
--
From what I understood of your question, MiniPad extends JFrame, and the pad() method creates a new instance of the MiniPad class. The simplest solution would be to turn the MiniPad class (at least through the pad() method) into a singleton. A singleton is a type of class where only one instance (or object) can exist at any given time. By calling a static method (in this case pad()) you check to see if an instance of the object already exists; if it does, simply use that existing object:
public class MiniPad extends JFrame {
//whatever code you have
private static MiniPad padInstance = null; //the singleton instance of your MiniPad
public static MiniPad pad() {
if(padInstance == null)
padInstance = new MiniPad();
//If you want to reset the object every time you call the method for whatever reason, do it here
pad.setVisible(true); // I believe this is all you want to do
}
}
This should do what you want. By calling the pad() method, only one MiniPad will ever show up.
However, if I read your question wrong, let me know and I will revise my answer.
Info on singletons:
http://en.wikipedia.org/wiki/Singleton_pattern

The best solution is to open a modal dialog instead of the frame. See The Use of Multiple JFrames, Good/Bad Practice? for more.

Related

Disposing a JFrame in another Class [duplicate]

This question already has an answer here:
Dispose JFrame from another class
(1 answer)
Closed 7 years ago.
I have a quick question regarding JFrames and disposing them properly. I have a game that has multiple levels, I wish to dispose of the frame in use when another is created with a new level.
The program I am currently working on extends a JFrame which has always confused me as I don't know what that JFrame is called.
Anyway, I have another class that extends a JPanel. In this class I have a method that, when the game state is completed, removes all instances and closes the JFrame. Yet this does not work because I cannot get the frame of the frame, instead I get multiple instances of the same JFrame.
So my set up looks like this:
Class 1 extends JFrame
....
....
....
Class 2 extends JPanel
...
...
method(clears everything + gets new JFrame for new level)
...
Sorry if that is vague, I don't want to post hundreds of lines of code for a short question. I know others have asked this question but I can never seem to get it to work for me.
So once again, my question is simply how do you close a JFrame in another class method.
(Please note everything works perfectly, I just can't close the frame without it breaking completely on me)
dispose() is an insance-level method. If you have object o, which is of JFrame or an inherited class, then o.dispose() should dispose it. If you are not sure that o is initialized when you want to dispose it, then
if (o != null) {
o.dispose();
}
If you simply call dispose() from somewhere, you will get an exception if that object/class does not have a dispose object. So, if you want to dispose o from class A, then you should call o.dispose() in one of the methods, but make sure that you initialize o correctly before that.

Can I call componentShown() method from a class that extends JFrame instead of JPanel ? If yes, how?

I want to show one JLabel and one JComboBox when one particular RadioButton is selected in previous frame, otherwise it should be hidden. Even when I implement ComponentListener in that class his abstract methods(componentShown(), componentHidden()) are never called.
I think that your problem can be handled pretty easily, without even getting into these event handlers. Just pass a variable from your initial frame, when the RadioButton is selected, to the new frame (maybe a boolean variable with true value). Then, in your new fame, simply show the components, based on the value of that variable.
I hope you can handle the passing of variables, by handling the constructor parameters of your new frame.
Hope this helps ! Any clarifications required, please comment.

Retrieve object from a Java Swing component

I've been working on a Java Swing project where I need to retrieve the object/instance that created a panel in order to call a simple save method particular to that instance.
You have a JFrame with a JTabbedPane that has tabs created by instancing a class which builds a JPanel and adds it to the JTabbedPane, I need to find the specific instance from the selected JPanel/tab on the JTabbedPane to then call it's save method.
Any ideas?
Thanks for your time!
public class frame extends JFrame implements ActionListener{
Builds a frame dubbed "frame" that is static.
Builds a static JTabbedPane dubbed "pane"and adds it to the frame.
Creates a button that creates a new instance of sheet.
public void actionPerformed(MAGIC!){
See if a button on the panel has been pressed and uses the currently selected tab to locate the correct instance of sheet to run it's save method.
}
}
public class sheet extends JPanel{
In constructor makes a JPanel and adds it to "pane"
Describes a save method that outputs a variable unique to the instance.
}
I figured out all I needed to do was store new tab objects in an ArrayList derp. Thanks for your attempts though guys!
Rather than just connecting back to the original creator, my approach to this was to create / use an interface that expicitly supports saving. I created something for this in TUS, my sourceforge project
http://tus.svn.sourceforge.net/viewvc/tus/tjacobs/io/filepersist/
Check out Persistable and Persistable2. Of course anything can be a Persistable, but the abstraction let's you get away from explicit ties back to the creator class
You can add a field in the new JPanels that point to the instance of the creator. I don't think there is any such method to point back to parent class in the API.
--EDIT--
You may want to check
http://docs.oracle.com/javase/tutorial/uiswing/components/tabbedpane.html
getSelectedIndex() may be what you are looking for.

Using Inner classes correctly (how to share class in user event)

I am trying to program a java application that consists of several windows using JFrame.
Each JFrame contains a JTextField and buton to go to the next JFrame.
I need to retrieve all the information entered by the user at the end.
I created an event click on the buton to save to a public class all the data that the user introduce in the JTextField. I named that public class myData, which has a static attributes.
The problem is that I can not access this class from the button listener function.
I get an error: cannot refer to an non final variable inside an inner class defined in a different method.
My goal is to be able to share the class myData between different methods of a different class.
E.g. I have a class named myClass1 and myClass2, so I want to share the myData attribute between myClass1 methods and myClass2 methods.
Please anyone can someone help me? or propose another way to do this!
Thanks in advance !
All of the calls about MVC etc. are valid, but this isn't that hard.
What you want to do is in your Main, you can create your Data (Model) class, the class that holds all of your information.
So, you can do something like this:
public class F1 ... {
private final Data myData;
public F1(Data theData) {
myData = theData;
}
....
}
public class Main {
Data myData;
public static void main(String args[]) {
Main m = new Main();
m.setMyData(new Data());
F1 f = new F1(m.getMyData());
...
}
}
Then, later, when F1 calls F2, simply do the same thing -- create F2 with the Data passed in earlier by the constructor. That way, as each Frame runs its course, they're all working on the same instance of Data. When all is done, the single instance of Data is left within the Main class for you to do with what you will.
There are better ways to reorganize your entire program, but this should give you ideas on how to get over the hump you're having right now.
Addenda:
There are several things you can do.
When your get the ActionEvent, it contains a source. That source is the component that generated the event (most likely a Button in this case). If you know where the button is located in the hierarchy of things, you get to your Frame directly. In the pastebin example, you have Frame -> Panel -> Button. So, if you have the Button, you cat get to the Frame.
public void actionPerformed(ActionEvent e) {
JButton sourceButton = (JButton)e.getSource();
F1 f1 = (F1)sourceButton.getParent().getParent();
Data myData = f1.getMyData();
data.setField(...);
}
Again, this is not the recommended ways of doing things. The tutorials have decent examples of using MVC and property change listeners and the whole kit. But this should get you to where you want to go.
Sorry, but your design needs alot of work. I'm going to recommend you read up on MVC. it may seem like alot to chew on right now but it will help you immensely in the long run. On a side note, dont nest your data class definition(s), and remember to always distinguish between classes and objects.
Your overall design of swapping JFrame's seems a bit iffy to me. Why not instead use either dialogs such as a JDialog or JOptionPane or even better a CardLayout to swap views. Also I urge you not to use static fields for any of this as this can cause significant problems in the future and makes your code less compliant with good object oriented principles. With regards to information sharing, about all I can say is that it's all about one class having the proper reference to the other class. For more specific advice you'll likely need to show us more information and code.
Edit
Also, you know of course that you can get a reference to the JButton that stimulated the ActionListener by calling getSource() on the ActionEvent object passed into the actionPerformed method. This may allow you to get a reference to the class that holds the JButton if necessary.

Updating the Jpanel of a class

After some advice on using jpanel - I'm new to java and playing around with the GUI elements.
Bascially what I'm curious about is if I can set up a Jpanel in one class, then somehow add labels etc to the that container, but from another class.
Is this possible ? or do i have to set the entire GUI up in one class, but then I guess I would have the same issue, if I wanted to update those fields I had set up in the main class from another class?
Apologies I don't really have any code that's usefull to demostrate here - I'm just trying to get the idea going, working out if its possible before I go ahead. And I'm not even sure if this is possible. Any advice would be greatly appreciated.
Thanks
As long as you have a reference to the JPanel, you can add whatever GUI-element you want, by calling add(JComponent comp) on the JPanel.
So, you can do something like this:
class Panel extends JPanel{
...
}
class Main{
public Main(JPanel thePanel){
thePanel.add(new JButton("Hello"));
}
}
Was this what you were looking for?
You can also update the fields added to the panel from another class, if you have a public accessor-method set up, in the class. So in your panel class, you have a method:
public JButton getButton(){
return button;
}
Then you can access the button from whatever class with a reference to your panel class, like this:
panel.getButton().setText("Some text");
Note that the button could just as well be public, then you could simply call the method directly: panel.button.setText("Some text"); but this is not considered good code, as it violates some general good OOP practices, not relevant to mention here.

Categories