How to call setVisible from another class? - java

What I have:
Two Classes that instantiate two JFrames.
What I am trying to achieve:
One with a button and the other that will become invisible when a action is fired on the button.
Problems:
I do not know how to pursue this. How should I go about coding this?
Class 1
public class test1{
public static void main(String[] args){
JFrame frame = new JFrame("Blinkly Frame");
frame.setSize(100, 100);
frame.setVisible(true);
}
}
Class 2
public class test2{
public static void main(String[] args){
JButton button = new JButton();
//when i will click this button i want to make invisible frame
}
}

Solution:
Create an instance of the class that has a Jframe or extends a JFrame.
First we need the JFrame that will be disappearing.
public class BClass extends JFrame{
// Disappearing frame
public BClass()
{
this.setSize(300,300);//sets frame properties
this.setLocationRelativeTo(null);
}
}
Next we need the Frame that will be holding the buttons. (Documentation added)
public class ACLass {
public static void main(String[] args) {
JFrame frame = new JFrame("Magician"); // instantiates
BClass b = new BClass(); // instantiates class that extends JFrame
b.setVisible(true);//
frame.setSize(300,300);//
frame.setVisible(true);//
frame.setLocationRelativeTo(null);//
JButton disappearButton = new JButton("Disappear"); //Adds button
disappearButton.addActionListener(new ActionListener() { // Adds action -When button is "clicked"
public void actionPerformed(ActionEvent e) { // method called when action fired
b.setVisible(false); //visibility changed
}
});
disappearButton.setBounds(0,0,300,150);
JButton appearButton = new JButton("appear"); //Adds button
appearButton.addActionListener(new ActionListener() { // Adds action -When button is "clicked"
public void actionPerformed(ActionEvent e) { // method called when action fired
b.setVisible(true); //visibility changed
}
});
disappearButton.setBounds(0,100,300,150);
frame.add(disappearButton, BorderLayout.PAGE_START); //adds button to frame
frame.add(appearButton, BorderLayout.PAGE_END); //adds button to frame
//I used border layout however use the a layout manager that works with your components/frame
}
}
Exotic Explanation
I'm going to explain this in terms of a magic show as it provides better understanding.
So first, we have one magician(JFrame) and his wand(JButton) and then we have the helper(the second JFrame) that will disappear and a stage that has been set(all properties defined etc.)
First the magician adds some magic power to his wand(actionListener that handles the button being pushed) that will react when the magician waves it(action fired a.k.a button being pushed).
Next we show the audience the helper(instantiating JFrame to disappear).
As we have shown the audience the helper, we can now show him/her disappearing (Now we can call setVisible through the instance variable of the class).
Finally, the magician waves his wand(firing an action), and the helper gets the signal(actionPerformed method) to disappear. The helper then can call the
b.setVisible(false); //making the frame invisible
General Explanation
https://docs.oracle.com/javase/tutorial/java/javaOO/usingobject.html
Basically, by instantiating an object in another class you can also call the objects methods in that class i.e. setVisible(boolean b).
Other less preferable solutions:
If your disappearing class has does not extend a JFrame but instantiates one..
You would need to create an instance variable
private JFrame j;
Then use getters/setters to access the object which will then allow you to call its methods.
secondClass.getFrame().setVisible(true);//getFrame returns the JFrame
Then add that to the actionPerformed method.
You can also use a static instance variable and statically reference it in the actionPerformed method... (not recommended)
secondClass.frame.setVisible(true);

Related

How to close a Java JFrame based on action event from a JPanel

How would I go about closing a JFrame based on an ActionEvent from a button click within a JPanel?
I have a total of three classes:
Application: contains the main method and runs the program by creating a FrameStartUp object.
FrameStartUp: extends the JFrame class and displays the contents within StartUpPanel.
StartUpPanel: extends the JPanel class and has all the components and ActionEvents.
Within the StartUpPanel class, I have a button with an ActionEventListener waiting for the button to be clicked.
When the button is clicked I want the application to shut down completely. I know of a method called .dispose() for the JFrame class, but I can't use it because creating an object of FrameStartUp would just run another GUI (run by the constructor).
As I am new to programming and swing, I do not know any other way to fix this, other than getting rid of the StartUpPanel and just creating a JPanel within the FrameStartUp class.
Are there any methods provided by Swing that can access the current JFrame that the panel is on, so the program can close when the ActionEvent is triggered?
I know of a method called .dispose() for the JFrame class
This will work if you explicitly set setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Are there any methods provided by Swing that can access the current JFrame that the panel is on
Yes... SwingUtilities provides one called getWindowAncestor().
button.addActionListener(e -> {
SwingUtilities.getWindowAncestor((Component)e.getSource()).dispose();
});
... or more commonly, you can chose to reference a final variable to achieve the same effect...
final JFrame swingStuff = this; // or expose via a getter/setter
button.addActionListener(e -> {
swingStuff.dispose();
});
... however the final variable placement and setter/getter would need a small reproducible code example.
And finally, as others have mentioned, System.exit(0) works quite fantastically well too, so as long as it doesn't break the lifecycle of any of your other components.
My test class:
import javax.swing.*;
import java.awt.*;
public class SwingStuff extends JFrame {
// Our main JFrame
public SwingStuff() {
super();
// The button
JButton button = new JButton("Close");
button.addActionListener(e -> {
SwingUtilities.getWindowAncestor((Component)e.getSource()).dispose();
});
// The JPanel and nested components
JPanel startupPanel = new JPanel();
startupPanel.add(button);
add(startupPanel);
pack();
// Make sure the app exits when closed
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// Just our entry point
public static void main(String ... args) {
SwingUtilities.invokeLater(() -> {
new SwingStuff().setVisible(true);
});
}
}

Unable to implement mouse listener

I am trying to implement mouse listener however I can not seem to get it to work. My code doesnt have any errors, but when I click on the frame I I can not get a message to print out. I have tried extending the class HandleClassOne to viewOne, but that also wouldn't work. Any thoughts?
The main class creates a frame and then creates an instance of viewOne on the frame.
public class main{
protected static JFrame window;
public static void main(String args[]){
window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(400,400);
window.setVisible(true);
new viewOne(window);
}
}
The viewOne class adds a panel and a label to a frame. It also adds a mouse listener to the panel.
public class viewOne {
private static JPanel panel1;
private static JLabel label1;
public viewOne(JFrame frame) {
panel1 = new JPanel();
label1 = new JLabel("View One");
panel1.add(label1);
frame.add(panel1);
panel1.setBackground(Color.red);
frame.validate();
}
public static void mouseAdd() {
HandleClassOne handle = new HandleClassOne();
panel1.addMouseListener(handle);
panel1.addMouseMotionListener(handle);
}
public static void main(String[] args) {
mouseAdd();
}
}
The HandleClassOne class should print out a message when the panel created in viewOne is clicked.
public class HandleClassOne extends main implements MouseListener, MouseMotionListener {
public void mouseClicked(MouseEvent e) {
System.out.println("mouse clicked");
}
}
While you have defined the function mouseAdd(...) I don't see you calling it.
Try (within the constructor)
public viewOne(JFrame frame) {
...
mouseAdd();
...
}
naturally, you'll need to do this after the panel1 is set.
Note that there are other issues, too
You don't invoke presenting the JFrame properly within your main function in your main class. Look up a basic tutorial on Java Swing, where it talks about the event dispatch thread and the requirements to not present within your program's main thread of execution.
You have an additional main function in your viewOne class, which is not how these things are wired up.
You added the mouseAdd() method (which is responsible for registering the mouse listener) inside the main method of viewOne class.
Please keep in mind that main method only gets called whenever you are running it as entry point class for your application. Here you have main class to act as an entry point.
You kept main method in viewOne class as well and it will get called only when you are running it as an individual piece (not along with main class).
To fix the issue here, keep your mouseAdd() method call inside viewOne() constructor as constructor gets called every time whenever object is getting created.
public viewOne(JFrame frame) {
panel1 = new JPanel();
label1 = new JLabel("View One");
panel1.add(label1);
frame.add(panel1);
panel1.setBackground(Color.red);
mouseAdd();
frame.validate();
}

Why do add(); is always written in constructor while adding button to frame

import java.awt.*;
import java.awt.event.*;
public class but extends Frame {
but() {
Button b = new Button("OK");
add(b);
b.addActionListener(new MyAn_innerclass());
}
public static void main(String args[]) {
but obj = new but();
obj.setSize(200, 100);
obj.setVisible(true);
}
}
class MyAn_innerclass implements ActionListener {
public void actionPerformed(ActionEvent ae) {
System.exit(0);
}
}
i have this code and i wonder why do we write this add(b); in constructor of the button class while adding button to the frame.I know that add(b); is used to push button to the frame but why write it in constructor,also if i remove the constructor the add function is not recognized by the compiler.why is it so?
Sorry if it sounds lame but i am a beginner to java
because when you creating swing frames you need to add components as soon as you start frame .when you create new instance of a class ,constructor get called .adding component is good to do in constructor .but you can also make a method and call it from constructor instead putting add in constructor but both are same ..
public class but extends Frame
{
but(){
Button b= new Button("OK");//add component immediately to frame
add(b);
}
}
if you didn't add in the constructor you will see empty frame until you add components to it.
you can also add component in another method but you have to call it from constructor
public class but extends Frame
{
but(){
initcomponent();//call component creating and adding method
}
public void initcomponent(){
Button b= new Button("OK");//add component immediately to frame
add(b);
}
}
If you asking about Button class itself (i.e Button b = new Button("OK");), then "OK" is the label of the button and you DON'T have to add it to the button while creating it. You can create the button then add the label after that:
Button b = new Button();
b.setLabel("OK");
If you asking about add(b);, at first it's a method not a constructor, then it's pretty logical to enforce you to add an argument to it, as you are adding some component to the frame, so what's that component? an empty one? it must be some component(Button, Text, ...etc).

Linking two frames in java

I am creating a java application which consists of two frames(JFrame1 and JFrame2)
JFrame1 has a grid 6x6 button; and JFrame2 has 6 radio buttons representing colours. How can I link the two frames so that when a button in JFrame1 is clicked, JFrame2 pops up and when a colour is chosen from that the JFrame2 closes and the clicked button gets the respective colour?
It is better to have one JFrame for every application. Use one for the 6x6 JButtons and create a modal JDialog for your color JRadioButtons.
The color selection JDialog should have a public getSelectedColor() method in order to return the selected color to the caller class.
Instantiate the ColorDialog in main and do not set it visible.
The ActionListener of each JButton should make the modal JDialog visible.
The RadioButton ActionPerformed should set the selected color and make the JDialog invisible.
Call getSelectedColor() and apply the returned color to your JButton.
In your frame1's button action listner, you can do something like this
public void actionPerformed(ActionEvent e) {
Frame2 frame = new Frame2(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
where "this" refers to the frame1 object. This is you can access its jTEXTFIELD and jBUTTONs from the second frame. So naturally you have store it in Frame1 object declared in your second class.
Suppose you have a clickable color field in frame2 object, once you click on it, you should trigger a function that get the input field from frame1 (using your locale object reference) and store it in it. something like this:
public void actionPerformed(ActionEvent e) {
frame1.getMyTextField().setText(WHAT_THE_CLICKED_ON);
this.close();
}
Sorry if I made any syntax errors, it's been a long time I didnt work with java :)
Just create another class, let us say FrameMananger, then use the singleton pattern to manage them.
Then in any class, you can use FrameManager.getFrame1() to get the frame1, same as the frame2. You can add logic judgement inside, like dynamically dispose some frame or only create them when needed.
This issue is fairly common concept when you create a game and try to navigate between your every view(like the show score panel from everywhere).
public class FrameManager
{
Frame1 frame1;
Frame1 frame2;
public static Frame1 getFrame1()
{
if(frame1 == null)
frame1 = new Frame1();
return frame1;
}
public static Frame1 getFrame2()
{
if(frame2 == null)
frame2 = new Frame1();
return frame2;
}
public class Frame1 extends JFrame
{
}
public class Frame2 extends JFrame
{
}
}

Difficulty removing all components from a Jpanel

G'day all,
I am coding a main menu for a project. The menu displays properly. I have also set up ActionListeners for the three buttons on the menu.
What I wish to do is reuse the JPanel for a new set of radio buttons when the user chooses "Start a New Game".
However, coding ActionPerformed to remove the existing components from the JPanel has me stumped. I know removeAll is somehow important, but unfortunately NetBeans informs me I cannot call it on my mainMenu JPanel object within ActionPerformed. So i have commented it out in my code below, but left it in so you can see what I am trying to do.
Your thoughts or hints are appreciated.
Here is my main code:
public class Main {
public static void main(String[] args) {
MainMenu menu = new MainMenu();
menu.pack();
menu.setVisible(true);
}
}
Here is my mainMenu code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MainMenu extends JFrame implements ActionListener {
JButton startNewGame = new JButton("Start a New Game");
JButton loadOldGame = new JButton("Load an Old Game");
JButton seeInstructions = new JButton("Instructions");
public MainMenu() {
super("RPG Main Menu");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel mainMenu = new JPanel();
mainMenu.setLayout(new FlowLayout());
startNewGame.setMnemonic('n');
loadOldGame.setMnemonic('l');
seeInstructions.setMnemonic('i');
startNewGame.addActionListener(this);
loadOldGame.addActionListener(this);
seeInstructions.addActionListener(this);
mainMenu.add(startNewGame);
mainMenu.add(loadOldGame);
mainMenu.add(seeInstructions);
setContentPane(mainMenu);
}
public void actionPerformed(ActionEvent evt) {
Object source = evt.getSource();
if (source == startNewGame) {
// StartNewGame code goes here
// mainMenu.removeAll();
}
if (source == loadOldGame) {
// LoadOldGame code goes here
}
if (source == seeInstructions) {
// Quit code goes here
}
}
}
Consider using a CardLayout instead, which manages two or more components (usually JPanel instances) that share the same display space. That way you don't have to fiddle with adding and removing components at runtime.
You need mainMenu to be a member variable:
public class MainMenu extends JFrame implements ActionListener {
JButton startNewGame = new JButton("Start a New Game");
JButton loadOldGame = new JButton("Load an Old Game");
JButton seeInstructions = new JButton("Instructions");
JPanel mainMenu = new JPanel();
Why do you feel the need to re-use this object?
You don't have a reference to mainMenu actionPerformed use. If you declare mainMenu with the buttons. It would work.
The problem is that the actionPerformed method is trying to call the JPanel mainMenu which is out of scope, i.e. the mainMenu variable is not visible from the actionPerformed method.
One way to get around this is to have the JPanel mainMenu declaration in the class itself and make it an instance field which is accessible to all instance methods of the class.
For example:
public class MainMenu extends JFrame implements ActionListener
{
...
JPanel mainMenu;
public MainMenu()
{
...
mainMenu = new JPanel();
...
}
public void actionPerformed(ActionEvent e)
{
...
mainMenu.removeAll();
}
}
Avoid attempting to "reuse" stuff. Computers are quite capable of tidying up. Concentrate on making you code clear.
So instead of attempting to tidy up the panel, simply replace it with a new one.
Generally a better way to write listeners is as anonymous inner classes. Code within these will have access to final variables in the enclosing scope and to members of the enclosing class. So, if you make mainMenu final and you ActionListeners anonymous inner classes, your code should at least compile.
Also don't attempt to "reuse" classes. Try to make each class do one sensible thing, and avoid inheritance (of implementation). There is almost never any need to extend JFrame, so don't do that. Create an ActionListener for each action, rather than attempting to determine the event source.
Also note, you should always use Swing components on the AWT Event Dispatch Thread. Change the main method to add boilerplate something like:
public static void main(final String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() { public void run() {
runEDT();
}});
}

Categories

Resources