I'm trying to update the GUI from a different Class. Every time I have tried calling the method on a different class it doesn't work but If I do it in the GUI Class it works just fine.
GUI Class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Test7 extends JPanel implements ActionListener {
private JButton jcomp1;
private JButton jcomp2;
private JButton jcomp3;
private JTextField jcomp4;
public Test7() {
//construct components
jcomp1 = new JButton("Button 1");
jcomp2 = new JButton("Button 2");
jcomp3 = new JButton("Button 3");
jcomp4 = new JTextField(5);
jcomp1.addActionListener(this);
//adjust size and set layout
setPreferredSize(new Dimension(723, 455));
setLayout(null);
//add components
add(jcomp1);
add(jcomp2);
add(jcomp3);
add(jcomp4);
//set component bounds (only needed by Absolute Positioning)
jcomp1.setBounds(160, 320, 100, 20);
jcomp2.setBounds(340, 320, 100, 20);
jcomp3.setBounds(490, 315, 140, 20);
jcomp4.setBounds(180, 125, 365, 110);
}
public static void main(String[] args) {
JFrame frame = new JFrame("MyPanel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Test7());
frame.pack();
frame.setVisible(true);
}
public void setTextArea(JTextField jcomp4) {
this.jcomp4 = jcomp4;
}
public JTextField getTextArea() {
return this.jcomp4;
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jcomp1) {
Class class1 = new Class();
class1.start();
}
}
}
Second Class:
public class Class extends Test7{
public void start(){
Test7 form = new Test7();
form.getTextArea().setText("nesto");
}
}
I have also tried putting the code on a same Thread but that doesn't seem to work either.
Test7 is JPanel. It is added to JFrame in your main method. When you call Class.start() you create new Test7. This new JPanel is not related to JPanel previously added to JFrame, so it is not even visible.
Your Class class should neither extend nor create new Test7 instance. Instead Test7 instance could be passed in constructor to Class:
Class class1 = new Class(this);
class1.start();
Your Class class:
public class Class {
private final Test7 test;
public Class(Test7 test) {
super();
this.test = test;
}
public void start() {
test.getTextArea().setText("nesto");
}
}
Andrew`s comments are also worthwile to think about.
Related
I'm working on a very complicated, multi-layered Swing GUI, and the main issue I'm running into right now involves having a JButton ActionListener perform setVisible() on a separate JFrame and immediately dispose() of the current JFrame. Because of the length of my code, it's important that main, both JFrames, and the ActionListener are all split into individual class files. I wrote a VERY simplified version of my problem, split into 4 tiny class files. Here they are:
File 1:
import javax.swing.*;
public class Test {
public static void main(String[] args) {
JFrame g1 = new GUI1();
g1.pack();
g1.setLocation(200,200);
g1.setVisible(true);
JFrame g2 = new GUI2();
g2.pack();
g2.setLocation(400,200);
g2.setVisible(false);
}
}
File 2:
import javax.swing.*;
public class GUI1 extends JFrame {
JPanel panel;
JButton button;
public GUI1() {
super("GUI1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
button = new JButton("Create GUI2");
button.addActionListener(new Listener());
add(panel);
add(button);
}
}
File 3:
import javax.swing.*;
public class GUI2 extends JFrame {
JPanel panel;
JLabel label;
public GUI2() {
super("GUI2");
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
label = new JLabel("I'm alive!");
add(panel);
add(label);
}
}
File 4:
import java.awt.event.*;
public class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
GUI2.setVisible(true);
GUI1.dispose();
}
}
As you can see, the only function of the ActionListener is to set GUI2 to visible and dispose of GUI1, but it runs the error "non-static method (setVisible(boolean) and dispose()) cannot be referenced from a static context". I figure this is because both methods are trying to reference objects that were created in main, which is static. My confusion is how to get around this, WITHOUT combining everything into one class.
Any suggestions? Thanks!
EDIT:
Here's the above code compiled into one file... although it returns the exact same error.
import javax.swing.*;
import java.awt.event.*;
public class Test {
public static void main(String[] args) {
JFrame g1 = new GUI1();
g1.pack();
g1.setLocation(200,200);
g1.setVisible(true);
JFrame g2 = new GUI2();
g2.pack();
g2.setLocation(400,200);
g2.setVisible(false);
}
}
class GUI1 extends JFrame {
JPanel panel;
JButton button;
public GUI1() {
super("GUI1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
button = new JButton("Create GUI2");
button.addActionListener(new Listener());
add(panel);
add(button);
}
}
class GUI2 extends JFrame {
JPanel panel;
JLabel label;
public GUI2() {
super("GUI2");
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
label = new JLabel("I'm alive!");
add(panel);
add(label);
}
}
class Listener implements ActionListener {
public void actionPerformed(ActionEvent e) {
GUI2.setVisible(true);
GUI1.dispose();
}
}
You have to pass instances of frame1 and frame2 to your ActionListener.
import java.awt.event.*;
public class Listener implements ActionListener {
private JFrame frame1, frame2;
public Listener(JFrame frame1, JFrame frame2) {
this.frame1 = frame1;
this.frame2 = frame2;
}
public void actionPerformed(ActionEvent e) {
frame2.setVisible(true);
frame1.dispose();
}
}
This means you have to pass an instance of frame2 to your GUI1 class.
import javax.swing.*;
public class GUI1 extends JFrame {
JPanel panel;
JButton button;
public GUI1(JFrame frame2) {
super("GUI1");
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new JPanel();
button = new JButton("Create GUI2");
button.addActionListener(new Listener(this, frame2));
add(panel);
add(button);
}
}
This means you have to create the frames in the reverse order.
import javax.swing.*;
public class Test {
public static void main(String[] args) {
JFrame g2 = new GUI2();
g2.pack();
g2.setLocation(400,200);
g2.setVisible(false);
JFrame g1 = new GUI1(g2);
g1.pack();
g1.setLocation(200,200);
g1.setVisible(true);
}
}
I want to dispose a JDialog from another class, because i am trying to keep classes and methods clean, and not create buttons and handle the listeners in the same class. So here is the problem.
I tried creating a get method from the first class to get the dialog and then dispose it on the third but didnt work.
public class AddServiceListener extends JFrame implements ActionListener {
/**
* Creates listener for the File/New/Service button.
*/
public AddServiceListener() {
}
/**
* Performs action.
*/
public void actionPerformed(ActionEvent e) {
AddServiceWindow dialog = new AddServiceWindow();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
}
public class AddServiceWindow extends JDialog {
private JPanel contentPanel;
private JFrame frame;
private JPanel buttonPanel;
private JLabel nameLabel;
private JTextField nameField;
private JLabel destinationLabel;
private JTextField destinationField;
private JButton destinationButton;
private JButton okButton;
private JButton cancelButton;
/**
* Creates the dialog window.
*/
public AddServiceWindow() {
ManageMinder mainFrame = new ManageMinder();
frame = mainFrame.getFrame();
contentPanel = new JPanel();
contentPanel.setLayout(null);
setTitle("New Service File");
setSize(340, 220);
setLocationRelativeTo(frame);
getContentPane().setLayout(new BorderLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPanel, BorderLayout.SOUTH);
createLabels();
createTextFields();
createButtons();
addListeners();
}
/**
* Creates the labels.
*/
private void createLabels() {
nameLabel = new JLabel("Name:");
nameLabel.setHorizontalAlignment(SwingConstants.RIGHT);
nameLabel.setBounds(25, 25, 52, 16);
contentPanel.add(nameLabel);
destinationLabel = new JLabel("Path:");
destinationLabel.setHorizontalAlignment(SwingConstants.RIGHT);
destinationLabel.setBounds(7, 70, 70, 16);
contentPanel.add(destinationLabel);
}
/**
* Creates the text fields.
*/
private void createTextFields() {
nameField = new JTextField();
nameField.setBounds(87, 22, 220, 22);
contentPanel.add(nameField);
nameField.setColumns(10);
destinationField = new JTextField();
destinationField.setBounds(87, 68, 220, 20);
contentPanel.add(destinationField);
destinationField.setColumns(10);
}
/**
* Creates the buttons of the window.
*/
private void createButtons() {
destinationButton = new JButton("Select...");
destinationButton.setBounds(87, 99, 82, 23);
destinationButton.setFocusPainted(false);
contentPanel.add(destinationButton);
okButton = new JButton("OK");
okButton.setFocusPainted(false);
buttonPanel.add(okButton);
cancelButton = new JButton("Cancel");
cancelButton.setFocusPainted(false);
buttonPanel.add(cancelButton);
}
/**
* Adds listeners to buttons.
*/
private void addListeners() {
ActionListener destinationAction = new AddDestinationListener(destinationField);
destinationButton.addActionListener(destinationAction);
ActionListener okAction = new SaveNewServiceFileListener(nameField, destinationField);
okButton.addActionListener(okAction);
}
}
public class SaveNewServiceFileListener extends JFrame implements ActionListener {
private JTextField nameField;
private JTextField destinationField;
private String path;
private File newService;
/**
* Creates listener for the File/New/Add Service/OK button.
*/
public SaveNewServiceFileListener(JTextField nameField, JTextField destinationField) {
this.nameField = nameField;
this.destinationField = destinationField;
}
/**
* Performs action.
*/
public void actionPerformed(ActionEvent e) {
path = destinationField.getText() + "\\" + nameField.getText() + ".csv";
try {
newService = new File(path);
if(newService.createNewFile()) {
System.out.println("Done!");
// DISPOSE HERE
}
else {
System.out.println("Exists!");
}
} catch (IOException io) {
throw new RuntimeException(io);
}
}
}
What should i do, so the dialog disposes on the third one, when OK is clicked and file is created?
The way to change the state of another object is to 1) have a reference to that object, and 2) call a public method on it.
Here the other object is the JDialog, and the state that you wish to change is its visibility by calling either .close() or .dispose() on it. The problem that you're having is that the reference to the JDialog is not readily available since it is buried within the actionPerformed(...) method of your AddServiceListener class.
So don't do this -- don't bury the reference but rather put it into a field of the class that needs it.
If you absolutely need to have stand-alone ActionListener classes, then I think that the simplest thing to do is to take the dialog out of the listener class and into the view class, your main GUI, and then have the listener call methods on the view. For example
Assume that the dialog class is called SomeDialog and the main GUI is called MainGui. Then put the reference to the dialog in the MainGui class:
public class MainGui extends JFrame {
private SomeDialog someDialog = new SomeDialog(this);
And rather than have your listeners create the dialog, have them call a method in the main class that does this:
public class ShowDialogListener implements ActionListener {
private MainGui mainGui;
public ShowDialogListener(MainGui mainGui) {
// pass the main GUI reference into the listener
this.mainGui = mainGui;
}
#Override
public void actionPerformed(ActionEvent e) {
// tell the main GUI to display the dialog
mainGui.displaySomeDialog();
}
}
Then MainGUI can have:
public void displaySomeDialog() {
someDialog.setVisible(true);
}
An example MRE program could look like so:
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Window;
import java.awt.event.*;
import javax.swing.*;
public class FooGui002 {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
MainGui mainGui = new MainGui();
mainGui.setVisible(true);
});
}
}
#SuppressWarnings("serial")
class MainGui extends JFrame {
private SomeDialog someDialog;
private JButton showSomeDialogButton = new JButton("Show Some Dialog");
private JButton closeSomeDialogButton = new JButton("Close Some Dialog");
public MainGui() {
super("Main GUI");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setPreferredSize(new Dimension(500, 200));
someDialog = new SomeDialog(this);
showSomeDialogButton.addActionListener(new ShowDialogListener(this));
showSomeDialogButton.setMnemonic(KeyEvent.VK_S);
closeSomeDialogButton.addActionListener(new CloseSomeDialogListener(this));
closeSomeDialogButton.setMnemonic(KeyEvent.VK_C);
setLayout(new FlowLayout());
add(showSomeDialogButton);
add(closeSomeDialogButton);
pack();
setLocationByPlatform(true);
}
public void displaySomeDialog() {
someDialog.setVisible(true);
}
public void closeSomeDialog() {
someDialog.setVisible(false);
}
}
#SuppressWarnings("serial")
class SomeDialog extends JDialog {
public SomeDialog(Window window) {
super(window, "Some Dialog", ModalityType.MODELESS);
setPreferredSize(new Dimension(300, 200));
add(new JLabel("Some Dialog", SwingConstants.CENTER));
pack();
setLocationByPlatform(true);
}
}
class ShowDialogListener implements ActionListener {
private MainGui mainGui;
public ShowDialogListener(MainGui mainGui) {
this.mainGui = mainGui;
}
#Override
public void actionPerformed(ActionEvent e) {
mainGui.displaySomeDialog();
}
}
class CloseSomeDialogListener implements ActionListener {
private MainGui mainGui;
public CloseSomeDialogListener(MainGui mainGui) {
this.mainGui = mainGui;
}
#Override
public void actionPerformed(ActionEvent e) {
mainGui.closeSomeDialog();
}
}
This is my code and when I execute, all I get is a blank window. First when I tried to do main.setContentPane() I got this error:
"Cannot make a static reference to the non-static field panel"
So i put it in the constructor, but nothing would show.
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainFrame extends JFrame{
private JPanel panel;
private JButton performance;
private JButton concordance;
private JButton discordance;
private JButton resultat;
public void MainFrame() {
panel = new JPanel(new GridLayout(4, 1, 10, 10));
performance = new JButton("performance");
concordance = new JButton("concordance");
discordance = new JButton("discordance");
resultat = new JButton("resultat");
performance.setSize(50, 30);
concordance.setSize(50, 30);
discordance.setSize(50, 30);
resultat.setSize(50, 30);
panel.add(performance);
panel.add(concordance);
panel.add(discordance);
panel.add(resultat);
getContentPane().add(panel);
}
public static void main(String[] args) {
MainFrame main = new MainFrame();
main.setSize(300, 200);
main.setDefaultCloseOperation(EXIT_ON_CLOSE);
main.setVisible(true);
}
}
You have a method (returning void) called MainFrame that is never being called.
You should either make that the constructor, or create a constructor that calls that method like so:
public class MainFrame extends JFrame {
private JPanel panel;
private JButton performance;
private JButton concordance;
private JButton discordance;
private JButton resultat;
public MainFrame() {
super();
MainFrame();
}
public void MainFrame() {
panel = new JPanel(new GridLayout(4, 1, 10, 10));
performance = new JButton("performance");
concordance = new JButton("concordance");
discordance = new JButton("discordance");
resultat = new JButton("resultat");
performance.setSize(50, 30);
concordance.setSize(50, 30);
discordance.setSize(50, 30);
resultat.setSize(50, 30);
panel.add(performance);
panel.add(concordance);
panel.add(discordance);
panel.add(resultat);
this.getContentPane().add(panel);
}
public static void main(String[] args) {
MainFrame main = new MainFrame();
main.setSize(300, 200);
main.setDefaultCloseOperation(EXIT_ON_CLOSE);
main.setVisible(true);
main.MainFrame();
}
}
Hi, I'm new to Java and I have the following problem:
I created a JFrame and I want the JPanel to change when clicking a JButton. That does almost work.The only problem is that the program creates a new window and then there are two windows. One with the first JPanel and one with the second JPanel.
Here is my current code:
first class:
public class Program {
public static void main (String [] args) {
new window(new panel1());
}
}
second class:
import java.awt.Toolkit;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Window extends JFrame {
private static final long serialVersionUID = 1L;
Window(JPanel panel) {
setLocation((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() / 2 - 200,
(int) Toolkit.getDefaultToolkit().getScreenSize().getHeight() / 2 - 100);
setSize(400, 200);
setTitle("test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setResizable(false);
setContentPane(panel);
setVisible(true);
}
}
third class:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class Panel1 extends JPanel {
private final long serialVersionUID = 1L;
Panel1() {
JButton nextPanelButton = new JButton("click here");
add(nextPanelButton);
ActionListener changePanel = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
new window(new panel2());
}
};
nextPanelButton.addActionListener(changePanel);
}
}
fourth class:
public class Panel2 extends JPanel {
private static final long serialVersionUID = 1L;
Panel2() {
JLabel text = new JLabel("You pressed the Button!");
add(text);
}
}
But I just want to change the JPanel without opening a new window. Is there a way to do that?
Thanks in advance!
This is a demo
import javax.swing.*;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new MainFrame("Title").setVisible(true);
});
}
}
MainFrame.java
import javax.swing.*;
import java.awt.*;
public class MainFrame extends JFrame {
private JPanel viewPanel;
public MainFrame(String title) {
super(title);
createGUI();
}
private void createGUI() {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLayout(new BorderLayout());
setMinimumSize(new Dimension(600, 480));
viewPanel = new JPanel(new BorderLayout());
add(viewPanel, BorderLayout.CENTER);
showView(new View1(this));
pack();
}
public void showView(JPanel panel) {
viewPanel.removeAll();
viewPanel.add(panel, BorderLayout.CENTER);
viewPanel.revalidate();
viewPanel.repaint();
}
}
View1.java
import javax.swing.*;
import java.awt.*;
public class View1 extends JPanel {
final private MainFrame owner;
public View1(MainFrame owner) {
super();
this.owner = owner;
createGUI();
}
private void createGUI() {
setLayout(new FlowLayout());
add(new JLabel("View 1"));
JButton button = new JButton("Show View 2");
button.addActionListener(event -> {
SwingUtilities.invokeLater(() -> owner.showView(new View2(owner)));
});
add(button);
}
}
View2.java
import javax.swing.*;
import java.awt.*;
public class View2 extends JPanel {
final private MainFrame owner;
public View2(MainFrame owner) {
super();
this.owner = owner;
createGUI();
}
private void createGUI() {
setLayout(new FlowLayout());
add(new JLabel("View 2"));
JButton button = new JButton("Show View 1");
button.addActionListener(event -> {
SwingUtilities.invokeLater(() -> owner.showView(new View1(owner)));
});
add(button);
}
}
First of all, take a look at Java naming conventions, in particular your class names should start with a capitalized letter.
If you want to avoid to open a new window every time you click the button, you could pass your frame object to Panel1 constructor, and setting a new Panel2 instance as the frame content pane when you click the button. There is also no need to pass Panel1 to Window constructor (please note that Window class is already defined in java.awt package, it would be better to avoid a possible name clash renaming your class ApplicationWindow, MyWindow or something else).
You could change your code like this (only relevant parts):
public class Program
{
public static void main (String [] args) {
SwingUtilities.invokeLater (new Runnable () {
#Override public void run () {
new Window ().setVisible (true);
}
};
}
}
class Window extends JFrame
{
// ...
Window () {
// ...
setContentPane(new Panel1 (this));
}
}
class Panel1 extends JPanel
{
// ...
Panel1 (JFrame parent) {
// ...
ActionListener changePanel = new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
parent.setContentPane (new Panel2 ());
}
};
// ...
}
Also note the SwingUtilities's invokeLater call, which is the best way to initialise your GUI in the EDT context (for more info look at this question).
Finally, you could avoid to create a new Panel2 instance every time you click the button, simply by using a CardLayout.
Take a look at the official tutorial.
This is an old post, but it may be useful to answer it in a simplified way. Thanks to mr mcwolf for the first answer.
If we want to make 1 child jframe interact with a main jframe in order to modify its content, let's consider the following case.
parent.java and child.java.
So, in parent.java, we have something like this:
Parent.java
public class Parent extends JFrame implements ActionListener{
//attributes
//here is the class we want to modify
private some_class_to_modify = new some_class_to_modify();
//here is a container which contains the class to modify
private JPanel container = new JPanel();
private some_class = new some_class();
private int select;
//....etc..etc
//constructor
public Parent(){
this.setTitle("My title");
//etc etc
//etc....etc
container.add(some_class_to_modify,borderLayout.CENTER);
}
//I use for instance actionlisteners on buttons to trigger the new JFrame
public void actionPerformed(ActionEvent arg0){
if((arg0.getSource() == source_button_here)){
//Here we call the child class and send the parent's attributes with "this"
Child child = new Child(this);
}
//... all other cases
}//Here is the class where we want to be able to modify our JFrame. Here ist a JPanel (Setcolor)
public void child_action_on_parent(int selection){
this.select = selection;
System.out.println("Selection is: "+cir_select);
if(select == 0) {
//Do $omething with our class to modify
some_class_to_modify.setcolor(Color.yellow);
}
}
In child.java we would have something like this:
public class Child extends JFrame implements ActionListener {
//Again some attributes here
private blabla;
//Import Parent JFrame class
private Parent owner;
private int select_obj=0;
//Constructor here and via Parent Object Import
public Child(Parent owner){
/*By calling the super() method in the constructor method, we call the parent's
constructor method and gets access to the parent's properties and methods:*/
super();
this.owner = owner;
this.setTitle("Select Method");
this.setSize(400, 400);
this.setContentPane(container);
this.setVisible(true);
}
class OK_Button implements ActionListener {
public void actionPerformed(ActionEvent e) {
Object Selection = select;
if(Selection == something) {
select_obj=0;
valid = JOptionPane.showConfirmDialog(null,"You have chosen option 1. Do you want to continue?","Minimum diameter",2);
}
System.out.println("Option is:"+valid);
if(valid == 0) {
setVisible(false);
//Here we can use our herited object to call the child_action_on_parent public class of the Parent JFrame. So it can modify directly the Panel
owner.child_action_on_parent(select_obj);
}
}
}
There are two players who will input their name in the JTextFields. What I want to do is that the data I entered from the Welcome frame in Enter.java will be transferred to the JLabels in ActualGame.java.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
public class Enter extends JFrame implements ActionListener {
private String one = "";
private String two = "";
private JTextField txtOne = new JTextField();
private JTextField txtTwo = new JTextField();
public Enter() {
this.setLayout(new FlowLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Welcome");
setSize(200, 130);
setVisible(true);
setResizable(false);
setLocationRelativeTo(null);
add(txtOne);
add(txtTwo);
enter.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
Main main = new Main();
this.setVisible(false);
one = txtOne.getText();
two = txtTwo.getText();
}
}
Main is the main class that holds the JFrame of ActualGame() and also the main class of Enter().
import javax.swing.*;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
public class Main extends JFrame {
public Main() {
add(new ActualGame());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Main");
setSize(400, 557);
setVisible(true);
setResizable(false);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
Enter enter=new Enter();
}
}
the ActualGame:
import java.awt.*;
import javax.swing.*;
public class ActualGame extends JPanel{
private JLabel lblOne = new JLabel(one);//how i wish it would be that easy
private JLabel lblTwo = new JLabel(two);
public ActualGame() {
setLayout(new FlowLayout());
add(lblOne);
add(lblTwo);
}
}
What should I do to be able to use the String variable one and two from Enter.java to ActualGame.java?
I'm new and noob in programming especially java swing. Open to criticisms and suggestions. Thank you.
Suggestions:
Passing information from one object to another is no different with Swing as with other Java programs. You can call methods or constructors and pass information in via parameters.
A key difference though is when to pass information. With event driven programs, this is often triggered by an event, a listener, and so use of the observer design pattern is comment.
For your purposes, the first window could be a modal dialog such as a JOptionPane or a modal JDialog which will make it easier to figure out when to pass information. When using a modal dialog, all code flow in the calling program is paused while the dialog is visible, and then resumes once the dialog is no longer visible. It's easy then to have the calling program query the dialog once this occurs, because you'll know precisely where in your code this will occur.
You'll want to avoid excessive showing of different windows in your application as it can quickly get annoying to the user. A few dialogs here and there are OK, especially if you need the information to be given in a modal fashion, but in general it's better to swap GUI "views" when needed, and a CardLayout is good for this.
But having said this, separate views are often created by separate classes, so the problem of passing information back and forth remains a problem with similar solutions as described above.
Specifically, give your Enter class a getText method that will allow other objects to query it for the state of its JTextField:
public String getTxtOneText() {
return txtOne.getText();
}
Also, change your ActualGame class so that it can accept String information when needed:
class ActualGame extends JPanel {
private JLabel lblOne = new JLabel();
public ActualGame(String text) {
lblOne.setText(text);
setLayout(new FlowLayout());
add(lblOne);
}
public void setLblOneText(String text) {
lblOne.setText(text);
}
}
e.g.,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Foo {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ActualGame actualGame = new ActualGame("");
Main main = new Main(actualGame);
main.pack();
Enter enter = new Enter(main);
enter.setVisible(true);
actualGame.setLblOneText(enter.getTxtOneText());
main.pack();
main.setLocationRelativeTo(null);
main.setVisible(true);
}
});
}
}
class Enter extends JDialog implements ActionListener {
private String one = "";
private JTextField txtOne = new JTextField(10);
private JButton enter = new JButton("Enter");
public Enter(JFrame frame) {
super(frame, "Welcome", true);
this.setLayout(new FlowLayout());
enter.addActionListener(this);
txtOne.addActionListener(this);
add(txtOne);
add(enter);
pack();
setLocationRelativeTo(null);
// this has to be done last
// setVisible(true);
}
public String getTxtOneText() {
return txtOne.getText();
}
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
}
class Main extends JFrame {
ActualGame actualGame;
public Main(ActualGame actualGame) {
super("Main");
this.actualGame = actualGame;
add(actualGame);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
class ActualGame extends JPanel {
private JLabel lblOne = new JLabel();
public ActualGame(String text) {
lblOne.setText(text);
setLayout(new FlowLayout());
add(lblOne);
}
public void setLblOneText(String text) {
lblOne.setText(text);
}
}
Try to make ActualGam as a underclass of Enter
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import static javax.swing.JFrame.EXIT_ON_CLOSE;
public class Enter extends JFrame implements ActionListener {
private String one = "";
private JTextField txtOne = new JTextField();
public Enter() {
this.setLayout(new FlowLayout());
setDefaultCloseOperation(EXIT_ON_CLOSE);
setTitle("Welcome");
setSize(200, 130);
setVisible(true);
setResizable(false);
setLocationRelativeTo(null);
add(txtOne);
enter.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
Main main = new Main();
this.setVisible(false);
one = txtOne.getText();
}
class ActualGame extends JPanel{
private JLabel lblOne = new JLabel(one);
public ActualGame() {
setLayout(new FlowLayout());
Enter.this.add(lblOne);
}
}
}