I'm learning Swing to make GUI in java. My goal is to have 1 mainGUI class to initialize everything and another class that controls all the button.
What I'm doing now is I have a mainGUI which has:
public class mainGUI(){
.... (main and initialize things here) ....
protected JButton btnLogin;
public void initialize(){
btnLogin = new JButton("Login");
btnLogin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
_buttonLogin();
}
});
}
protected void _buttonLogin(){};
}
Then in my buttonControl I have:
public class buttonControl extends mainGUI{
#Override
protected void _buttonLogin(){
if (isLogin == true){
btnLogin.setEnabled(false);
} else {
// somthing else
}
}
}
The program actually works but not as i expected. When i click on the "login" button, the login button is not set to unclickable. If i don't have the _buttonLogin method in the mainGUI class then I cannot call it from buttonControl class.
I'm just wondering is my approach right in this situation? or any other neat way to have a separated listener class?
Thank you so much
For one you're misusing inheritance. You don't use inheritance to gain access to variables. For that you should use composition.
For example, ButtonControl (and note that the first letter of any class should start with an upper case letter), could have a MainGui field which is passed into it via its constructors. Then the control class can call Gui methods.
class ButtonControl extends AbstractAction {
MainGui gui;
public ButtonControl(MainGui gui, String name, int mnemonic) {
super(name);
putValue(MNEMONIC, mnemmonic);
this.gui = gui;
}
public void actionPerformed(ActionEvent e) {
// ....
}
}
And it could be used like so:
ButtonControl btnCtrl = new ButtonControl(this, "My Button", KeyEvent.VK_M);
JButton myButton = new JButton(btnCtrl);
If you need a Single class for control all the buttons you have you can create a ButtonControl class which can register and de-register buttons to it and handle its events inside the control class. A Simple example code is given
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.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
public class MainUI extends JFrame{
ButtonController buttonController;
public MainUI() {
super();
buttonController=new ButtonController(this);
initialize();
}
private void initialize() {
JTextField userName=new JTextField();
JPasswordField passwordField=new JPasswordField();
JButton loginButton=new JButton("Login");
loginButton.setActionCommand(ButtonController.LOGIN_COMMAND);
JButton cancelButton=new JButton("Cancel");
cancelButton.setActionCommand(ButtonController.CANCEL_COMMAND);
JPanel contentPane=new JPanel();
contentPane.setLayout(new GridLayout(3,2));
contentPane.add(new JLabel("Username : "));
contentPane.add(userName);
contentPane.add(new JLabel("Password : "));
contentPane.add(passwordField);
contentPane.add(loginButton);
contentPane.add(cancelButton);
buttonController.registerButton(loginButton);
buttonController.registerButton(cancelButton);
setContentPane(contentPane);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
}
/**
* #param args
*/
public static void main(String[] args) {
MainUI ui=new MainUI();
ui.setVisible(true);
}
}
class ButtonController implements ActionListener
{
private MainUI mainUI;
public static String LOGIN_COMMAND="Login";
public static String CANCEL_COMMAND="Cancel";
public ButtonController(MainUI mainUi ) {
this.mainUI=mainUi;
}
public void registerButton(JButton button)
{
button.addActionListener(this);
}
public void deRegisterButton(Button button)
{
button.removeActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals(LOGIN_COMMAND))
{
((JButton)e.getSource()).setEnabled(false);
}
if(e.getActionCommand().equals(CANCEL_COMMAND))
{
mainUI.dispose();
}
}
}
It's been a long time I've used swing, but we can only call the child class implementation by only from the child class object type :
mainGUI gui = new buttonControl();
we should pass buttonControl object type instance instead of mainGui instance if we want to let the caller use the implementation in buttonControl.
This related to Polymorphism with overidding.
Hopes this help..
Related
I am trying to add functionality to a Jbutton using subclass butt Jbutton is actually declared and defined in super class.
Here is my code:
JButton zz=new JButton(ss);
zz.setBounds(470,70,35,35);
zz.setBorder(oo);
zz.setBackground(new Color(0,170,120));
l.add(zz);
This is my Jbutton located in super class named as realestate in my project.I have created subclass in which i am trying to add action listener for this button.
Here is my subclass:
public class assan extends RealEstate{
zz.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent u)
{
System.out.println("kk");
}
});}
butt i run this program i got different types of errors such as:
Package 'zz' does not exist etc.
This is my full code:
package realestate;
import java.awt.Color;
import javax.swing.*;
public class Realestate extends JFrame {
Realestate()
{
JLabel l=new JLabel(new ImageIcon("C:\\Users\\MUHAMMAD SHAHAB\\Documents\\NetBeansProjects\\Real Estate\\src\\real\\estate\\file (2).jpg"));
l.setBounds(100,50,300,250);
add(l);
ImageIcon ss=new ImageIcon("C:\\Users\\MUHAMMAD SHAHAB\\Documents\\NetBeansProjects\\Real Estate\\src\\real\\estate\\1470672145_Help_mark_query_question_support_talk.png");
public JButton zz=new JButton(ss);
zz.setBounds(470,70,35,35);
zz.setBackground(new Color(0,170,120));
l.add(zz);
}
public class assan extends Realestate{
zz.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent o)
{
System.out.println("Cena");
}
});
}
public static void main(String[] args) {
RealEstate v=new RealEstate();
v.setUndecorated(true);
v.setVisible(true);
v.setBounds(350,200,600,350);
v.setForeground(Color.WHITE);
assan n=new assan();
}
}
what am i doing wrong?
Imagine that this is the superclass:
public class RealEstate{
public JButton button = new JButton("Button Name");
}
And this the subclass:
public class SubClass extends RealEstate{
/**
* Constructor
*/
public SubClass(){
//The Button is public so it is visible to the subclass
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent u){
System.out.println("Hello World!");
}
});
}
}
Also have a look at this (tutorial)
A minimal example of the code you may need:
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.border.Border;
public class RealEstate extends JFrame {
public JButton button = new JButton("Button");
/**
* Constructor
*/
public RealEstate() {
//Button
button.setText("I am a JButton");
// ...rest of the code below
}
/**
* The SubClass
*/
protected class SubClass extends RealEstate {
/**
* Constructor
*/
public SubClass() {
//accessing the button from the SubClass
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent u) {
System.out.println("Hello World!");
}
});
}
}
/**
* Main Method
*
* #param args
*/
public static void main(String[] args) {
RealEstate v = new RealEstate();
v.setUndecorated(true);
v.setVisible(true);
v.setSize(600,600);
v.setForeground(Color.WHITE);
v.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Put the following class in the file RealState.java:
public class RealEstate extends JFrame {
protected JButton zz = null;
RealEstate() {
JLabel l = new JLabel("Label");
l.setBounds(100, 50, 300, 250);
add(l);
// ImageIcon ss = new ImageIcon("path_to_image_file");
zz = new JButton("MyButton");
zz.setBounds(470, 70, 35, 35);
zz.setBackground(new Color(0, 170, 120));
add(zz);
}
}
And put the subclass in its own file too: Assan.java
public class Assan extends RealEstate {
public Assan() {
zz.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent o) {
System.out.println("Cena");
}
});
}
public static void main(String[] args) {
Assan v = new Assan();
v.setUndecorated(true);
v.setVisible(true);
v.setBounds(350, 200, 600, 350);
v.setForeground(Color.WHITE);
}
}
Note that I have made two changes:
make the variable you want to modify in the subclass protected
move the main method to the subclass if you want the event handler to be executed.
And lastly, you have to follow some tutorials, for example
Here you will learn about inheritance
Java Swing tutorials.
Please see the following and read the comments carefully. The code is meant not only to highlight some errors, but also demonstrate the idea of MCVE :
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
//Java is case sensetive. You can't call a class Realestate
//and later use RealEstate v= new RealEstate();
public class RealEstate /*Realestate*/ extends JFrame {
//to make zz visible to other classes it should be a field
public JButton zz;
RealEstate()
{
//remove what is not needed to demonstrate the problem, remove it
//JLabel l
//ImageIcon ss=new ImageIcon("C:\\Users\\MUHAMMAD SHAHAB\\Documents\\NetBeansProjects\\Real Estate\\src\\real\\estate\\1470672145_Help_mark_query_question_support_talk.png");
//wrong
//public JButton zz=new JButton("Button");
zz=new JButton("Button");
zz.setBounds(470,70,35,35);
zz.setBackground(new Color(0,170,120));
add(zz);
//you can't add a button to a JLabel
//l.add(zz);
}
public static void main(String[] args) {
RealEstate v= new RealEstate();
v.setUndecorated(true);
v.setVisible(true);
v.setBounds(350,200,600,350);
v.setForeground(Color.WHITE);
Assan n= new Assan();
}
}
//Use right naming convention. Assan and not assan
class Assan extends RealEstate{
//this code has to be enclosed in a constructor
//or a method
//zz.addActionListener(new ActionListener(){
// public void actionPerformed(ActionEvent o)
// {
// System.out.println("Cena");
// }
//});
Assan(){
zz.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent o)
{
System.out.println("Cena");
}
});
}
}
I didn't really know how else to phrase that but essentially:
-I have a few separate "pieces" that I am trying to add onto a master frame; to keep the code from getting unwieldy I have each "piece" be its own class.
-I'm getting stuck on adding the panells onto the master frame, because the classes themselves aren't panels, rather the method of the class creates the panel, which creates issues that I don't know how to solve.
PIECE (works on its own when I have it make a dialog instead of be a panel):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PieceThing3 extends JPanel //<switched from JDialog
{
//set up variables here
private ActionListener pieceAction = new ActionListener()
{
public void actionPerformed (ActionEvent ae)
{
// Action Listener (this also works)
}
};
private void createPiece()
{
//setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
//setLocationByPlatform(true);
// the above are commented out when I switch from dialog to panel
JPanel contentPane = new JPanel();
//something that uses pieceAction is here
//two buttons, b and s, with action listeners are here
contentPane.add(b);
contentPane.add(s);
add(contentPane);
//pack();
//again, commented out to switch from dialog
setVisible(true);
System.out.println("hi I'm done");
//just to check and make sure it's done
}
public static void main(String[] args)
{
// TODO Auto-generated method stub
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new PieceThing3().createPiece();
}
});
}
}
Sorry that is very vague, but the intricacies are not as important as the general idea - it works perfectly when I have it create its own dialog box, but now I am trying to get it to make a panel within a master code, below:
MASTER:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CollectGUI extends JFrame{
private void createDialog(){
this.setSize(2000,1000);
this.setLocation(0,0);
this.setTitle("TITLE");
PieceThing3 pt = new PieceThing3();
//HERE, if I do pt.main(null); while it is in "dialog mode" (rather than panel) it pops up a dialog box and everything is hunky dory. But I don't know how to get it to add the method as a panel.
this.add(pt.main(null));
//this gives an error
this.setVisible(true);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new CollectGUI().createDialog();
}
}
As I said in the comments, if I just do pt.main(null) when pt is set to make a dialog, it does it, but if I try to add pt.main(null) as a panel it throws an error. Can anybody give me some insight on how to add a method of a class rather than a class? I'm pretty stumped.
THANK YOU!!
You are definitely on the right track working to maintain separation of concerns and implement your gui in a number of distinct components. Try something like this:
Panel1
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Panel1 extends JPanel {
public Panel1() {
this.add(new JLabel("This is panel 1"));
}
}
Panel2
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Panel2 extends JPanel {
public Panel2() {
this.add(new JLabel("This is panel 2"));
}
}
JFrame
import java.awt.BorderLayout;
import javax.swing.JFrame;
import org.yaorma.example.jframe.panel.panel1.Panel1;
import org.yaorma.example.jframe.panel.panel2.Panel2;
public class ExampleJFrame extends JFrame {
public ExampleJFrame() {
super("Example JFrame Application");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(400,400);
this.setLayout(new BorderLayout());
Panel1 pan1 = new Panel1();
Panel2 pan2 = new Panel2();
this.add(pan1, BorderLayout.NORTH);
this.add(pan2, BorderLayout.SOUTH);
this.setVisible(true);
}
}
main:
public class ExampleApplication {
public static void main(String[] args) throws Exception {
new ExampleJFrame();
}
}
EDIT:
Here's a Panel1 with a little more content.
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import org.yaorma.example.action.sayhello.SayHelloAction;
public class Panel1 extends JPanel {
//
// instance variables
//
private JButton pressMeButton;
//
// constructor
//
public Panel1() {
this.setLayout(new BorderLayout());
this.add(new JLabel("This is panel 1"), BorderLayout.NORTH);
this.initPressMeButton();
}
//
// button
//
private void initPressMeButton() {
this.pressMeButton = new JButton("Press Me");
this.pressMeButton.addActionListener(new PressMeButtonActionListener());
this.add(pressMeButton, BorderLayout.SOUTH);
}
//
// method to get the parent jframe
//
private JFrame getParentJFrame() {
Container con = this;
while(con != null) {
con = con.getParent();
if(con instanceof JFrame) {
return (JFrame)con;
}
}
return null;
}
//
// action listener for Press Me button
//
private class PressMeButtonActionListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JFrame jFrame = getParentJFrame();
SayHelloAction action = new SayHelloAction(jFrame);
action.execute();
}
}
}
Action called by button:
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class SayHelloAction {
private JFrame owner;
public SayHelloAction(JFrame owner) {
this.owner = owner;
}
public void execute() {
JOptionPane.showMessageDialog(owner, "Hello World");
}
}
a basic problem that i can't figure out, tried a lot of things and can't get it to work, i need to be able to get the value/text of the variable
String input;
so that i can use it again in a different class in order to do an if statement based upon the result
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class pInterface extends JFrame {
String input;
private JTextField item1;
public pInterface() {
super("PAnnalyser");
setLayout(new FlowLayout());
item1 = new JTextField("enter text here", 10);
add(item1);
myhandler handler = new myhandler();
item1.addActionListener(handler);
System.out.println();
}
public class myhandler implements ActionListener {
// class that is going to handle the events
public void actionPerformed(ActionEvent event) {
// set the variable equal to empty
if (event.getSource() == item1)// find value in box number 1
input = String.format("%s", event.getActionCommand());
}
public String userValue(String input) {
return input;
}
}
}
You could display the window as a modal JDialog, not a JFrame and place the obtained String into a private field that can be accessed via a getter method. Then the calling code can easily obtain the String and use it. Note that there's no need for a separate String field, which you've called "input", since we can easily and simply extract a String directly from the JTextField (in our "getter" method).
For example:
import java.awt.Dialog.ModalityType;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import javax.swing.*;
import javax.swing.text.JTextComponent;
public class TestPInterface {
#SuppressWarnings("serial")
private static void createAndShowGui() {
final JFrame frame = new JFrame("TestPInterface");
// JDialog to hold our JPanel
final JDialog pInterestDialog = new JDialog(frame, "PInterest",
ModalityType.APPLICATION_MODAL);
final MyPInterface myPInterface = new MyPInterface();
// add JPanel to dialog
pInterestDialog.add(myPInterface);
pInterestDialog.pack();
pInterestDialog.setLocationByPlatform(true);
final JTextField textField = new JTextField(10);
textField.setEditable(false);
textField.setFocusable(false);
JPanel mainPanel = new JPanel();
mainPanel.add(textField);
mainPanel.add(new JButton(new AbstractAction("Get Input") {
#Override
public void actionPerformed(ActionEvent e) {
// show dialog
pInterestDialog.setVisible(true);
// dialog has returned, and so now extract Text
textField.setText(myPInterface.getText());
}
}));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
// by making the class a JPanel, you can put it anywhere you want
// in a JFrame, a JDialog, a JOptionPane, another JPanel
#SuppressWarnings("serial")
class MyPInterface extends JPanel {
// no need for a String field since we can
// get our Strings directly from the JTextField
private JTextField textField = new JTextField(10);
public MyPInterface() {
textField.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
JTextComponent textComp = (JTextComponent) e.getSource();
textComp.selectAll();
}
});
add(new JLabel("Enter Text Here:"));
add(textField);
textField.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
Window win = (Window) SwingUtilities.getWindowAncestor(MyPInterface.this);
win.dispose();
}
});
}
public String getText() {
return textField.getText();
}
}
A Good way of doing this is use Callback mechanism.
I have already posted an answer in the same context.
Please find it here JFrame in separate class, what about the ActionListener?.
Your method is a bit confusing:
public String userValue(String input) {
return input;
}
I guess you want to do something like this:
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
Also your JFrame is not visible yet. Set the visibility like this setVisible(true)
Ok guys, I've made some changes in my code as told by you. I have 3 classes:
The second class (and first GUI): I have 4 JButtons - Simulare, CazParticular, Start and HandSelection, some JLabels and 3 JTextFields; When I press the HandSelection button another frame it's created with different content.
The 3rd class (and second GUI): I have 2 JButtons - Ok and Cancel and other stuff. When I press the Ok button I want to the access to the JTextField(QuesHandText) from the first Gui and use the method setText(). I can't figure this out, I'm thinking on this like 4-5 days and still can't get the answer. Please help me!
What code should I write in if statement to be able to modify the text in the JTextField from 2nd class (first GUI) ?
First class:
import javax.swing.JFrame;
public class Main {
public static void main(String[] args){
//other stuff
GuiMain gui = new GuiMain();
gui.frame1.setLocation(150,150);
gui.frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.frame1.setSize(400,250);
gui.frame1.setResizable(false);
gui.frame1.setVisible(true);
//other stuff
}
}
Second class:
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import javax.swing.*;
public class GuiMain {
public static GuiMain instance;
public static GuiMain getInstance(){
if(GuiMain.instance == null){GuiMain.instance = new GuiMain();}
return GuiMain.instance;
}
public JFrame frame1 = new JFrame();
public JTextField QuesHandText, FlopTurnRiverText, RezultatText;
public JButton Simulare, CazParticular, Start, HandSelection;
public int w1,h1;
public JLabel someText;
static int u=0;
public int j=0;
public GuiMain(){
frame1.setTitle("HoldemTool");
frame1.setLayout(null);
QuesHandText = new JTextField(4);
Simulare = new JButton("Simulare");
CazParticular = new JButton("Caz particular");
Start = new JButton("Start");
HandSelection = new JButton(new ImageIcon(getClass().getResource("GuiPic.png")));
Handler handler1 = new Handler();
CazParticular.addActionListener(handler1);
Simulare.addActionListener(handler1);
HandSelection.addActionListener(handler1);
Start.addActionListener(handler1);
QuesHandText.setEditable(false);
FlopTurnRiverText.setEditable(false);
RezultatText.setEditable(false);
frame1.add(Welcome1);
frame1.add(Welcome2);
frame1.add(QuesHand);
frame1.add(FlopTurnRiver);
frame1.add(Rezultat);
frame1.add(QuesHandText);
frame1.add(FlopTurnRiverText);
frame1.add(RezultatText);
frame1.add(Simulare);
frame1.add(CazParticular);
frame1.add(Start);
}
public JTextField getQuesHandText(){
return QuesHandText;
}
public class Handler implements ActionListener{
public void actionPerformed(ActionEvent e){
if(e.getSource()==Simulare)
{
}
if(e.getSource()==CazParticular){
QuesHandText.setEditable(true);
FlopTurnRiverText.setEditable(true);
QuesHandText.setText("");
FlopTurnRiverText.setText("");
RezultatText.setText("");
frame1.setSize(470, 250);
Start.setBounds(3*FlopTurnRiverText.getX(), QuesHand.getY(), 65, h1);
HandSelection.setBounds(3*FlopTurnRiverText.getX(), FlopTurnRiverText.getY(), 65, h1);
frame1.add(HandSelection);
frame1.add(Start);
}
if(e.getSource()==Start){
QuesHandText.setText("Text");
}
if(e.getSource()==HandSelection){
GuiSelection gui2 = new GuiSelection();
gui2.frame2.setVisible(true);
}
}
}}
3rd class
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import javax.swing.*;
public class GuiSelection extends GuiMain {
JFrame frame2 = new JFrame();
GuiMain guiMain;
public JButton Ok,Cancel;
//other stuff
public GuiSelection(){
guiMain = new GuiMain();
frame2.setTitle("Hand selection");
frame2.setSize(1135,535);
frame2.setLayout(null);
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.setVisible(true);
frame2.setResizable(false);
//other stuff
Handler2 handler2 = new Handler2();
Ok.addActionListener(handler2);
Cancel.addActionListener(handler2);
frame2.add(Ok); frame2.add(Cancel);
}
public class Handler2 implements ActionListener{
public void actionPerformed(ActionEvent e){
if(e.getSource()==Cancel){
frame2.hide();
}
if(e.getSource()==Ok)
{
GuiMain.getInstance().getQuesHandText().setText("From Ok");
//When I prees this button "Ok" I want to get access to the JTextField(QuesHandText) in the GuiMain class, and .setText();
//somothing like QuesHandtText.setText("someText");
}
}
}
}
Add to your first GUI the method public JTextField getQuesHandText() and a static method public static JFrame getInstance() which returns the instance of the first GUI. Now you can call SecondClass.getInstance().getQuesHandText() from anywhere to get the JTextField instance. Note that with this method you can only have a single instance of SecondClass at any time.
Your getInstance() method will look as follows:
public class SecondClass extends JFrame {
private static SecondClass instance;
public static SecondClass getInstance() {
if(SecondClass.instance == null)
SecondClass.instance = new SecondClass();
return SecondClass.instance
}
}
Note that you shouldn't create an instance of SecondClass manually.
Use Composition,
1. Create the instance of the class which contains the JFrame, whose JTextField you need to access.
2. Then on that instance call the setter or getter method of the JTextField.
Edited:
Make Sure you have implemented Singleton principle on the Main class, else you will get
a new instance , which you dont want......
In Second class.
public class GuiMain{
Main m = new Main();
m.getText();
m.setText();
// Other stuffs
}
Perhaps you do not really need two Windows. What you need is a Dialog which can be achieved by the class JOptionPane.
Here is a demo code.
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.JOptionPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class YourGui implements ActionListener {
private JFrame frame;
private JTextField text;
private JButton takeInput;
public YourGui() {
frame = new JFrame();
frame.setLayout(new GridLayout(2, 1));
text = new JTextField();
takeInput = new JButton("Take Input!");
frame.add(text);
frame.add(takeInput);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 100);
takeInput.addActionListener(this);
}
public void show() {
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
int selection =
JOptionPane.showConfirmDialog(frame, "Select Hand", "Select",
JOptionPane.OK_CANCEL_OPTION);
if (selection == JOptionPane.OK_OPTION) {
text.setText("You selected ok");
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
YourGui gui = new YourGui();
gui.show();
}
});
}
}
Use the instance of the initiated Class to get access to its public variables. So you should do something like:
GuiMain main=new GuiMain();
...
main.QuesHandtText.setText("someText");
Alternatively if your JTextField is private (though its not) use an instance method that has public access to change its contents - this is the preferred method:
Class A:
class A {
private JTextField tf;
public void setFieldText(String text) {
tf.setText(text);
}
}
Class B:
class B {
A a = new A();
a.setText("hello");
}
In the handler of GuiMain, pass itself (the main JFrame) as an argument to the constructor of GuiSelection:
GuiSelection gui2 = new GuiSelection(this);
And then change the constructor of GuiSelection from
public GuiSelection(){
guiMain = new GuiMain();
...
to
public GuiSelection(GuiMain guiMain){
this.guiMain = guiMain;
...
Also, it seems quite odd that GuiSelection is a subclass of GuiMain. Probably both of these should be direct subclasses of JFrame.
Also, you should wrap everything in the main method within SwingUtilities.invokeLater since everything related to Swing should run on the event-dispatch thread.
Also, you should never use public member variables: it is very un-Java.
I promise that I have read innumerable posts about this so I am guessing I cannot translate what I read to what I am trying to do. First the narrative. At the basis, what I wish to do is develop a list of objects in my example the objects are cars. The list of cars is displayed in my main window. When I want to add a new car, I open a dialog to set the attributes and create it.
The problem is I keep runnning in circles with the object references. I'vre tried creating subclasses with public methods and passing objects in constructors. These attempts result in errors about non-static fields or non-final variables. If I could just see a solid example of how to make the references, I think the rest would fall into place.
the object
public class Car {
private String size;
public Car(String sizeIn){
this.size = sizeIn;
}
public void setSize(String sizeIn){
this.size = sizeIn;
}
public String getSize(){
return this.size;
}
public String toString(){
return this.size;
}
}
main window
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JButton;
import javax.swing.JList;
public class MainGUI {
private JFrame frame;
private LinkedList<Car> carList;
private DefaultListModel model;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainGUI window = new MainGUI();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainGUI() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton btnAddCar = new JButton("Add Car");
btnAddCar.addActionListener(new EditLauncher());
frame.getContentPane().add(btnAddCar, BorderLayout.NORTH);
JList list = new JList(model);
frame.getContentPane().add(list, BorderLayout.CENTER);
}
public void addCar(String size){
Car car = new Car(size);
carList.add(car);
model.addElement(car);
frame.getContentPane().invalidate();
frame.getContentPane().validate();
}
public class EditLauncher implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
}
the dialog
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JTextField;
import javax.swing.JLabel;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
public class EditDialog extends JDialog {
private final JPanel contentPanel = new JPanel();
private JTextField fldSize;
private MainGUI mainGUI;
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
EditDialog dialog = new EditDialog(mainGUI); //<<ERROR - Cannot make a static reference to the non-static field mainGU
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Create the dialog.
*/
public EditDialog(MainGUI mainGUI) {
this.mainGUI = mainGUI;
setBounds(100, 100, 225, 125);
getContentPane().setLayout(new BorderLayout());
contentPanel.setLayout(new FlowLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
JLabel lblSize = new JLabel("Size");
contentPanel.add(lblSize);
fldSize = new JTextField();
contentPanel.add(fldSize);
fldSize.setColumns(10);
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
JButton okButton = new JButton("OK");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
mainGUI.addCar(fldSize.getText()); // << ERROR Cannot refer to a non-final variable mainGUI inside an inner class defined in a different method
}
});
okButton.setActionCommand("OK");
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
JButton cancelButton = new JButton("Cancel");
cancelButton.setActionCommand("Cancel");
buttonPane.add(cancelButton);
}
}
For "Cannot make a static reference to the non-static field mainGUI"
The problem is (EditDialogs) main is static and can therefor only access static members or a member of an explicit object instance (e.g. object.member form). In this case, mainGUI is not a static member and therefor cannot be accessed: which is fine, because no MainGUI instance is created if that "main" is called! (Remember, only one main is used each time the application is launched! Get rid of the "main" in EditDialog to avoid this confusion.)
Instead, consider this (but please see the comment by Dave for a better approach entirely!):
btnAddCar.addActionListener(new ActionListener () {
public void actionPerformed(ActionEvent e) {
EditDialog dialog = new EditDialog(MainGUI.this);
dialog.show(); // or whatever
}
});
For "Cannot refer to a non-final variable mainGUI inside an inner class defined in a different method"
The error is because only member variables (of the enclosing type) or "final" local variables can be used from within an anonymous inner type (new ActionListener() { ... }).
Now, one might go "but mainGUI is a member variable!"
Well, it is, but it is being shadowed by a local variable with the same name (this.mainGUI vs mainGUI). Here are the solutions I know of:
Change the local variable name to avoid the shadowing: public EditDialog(MainGUI theMainGUI) ...
Qualify mainGUI to tell Java the member variable is desired, which bypasses the shadowing: EditDialog.this.mainGUI.addCar(...), where EditDialog is the name of the enclosing type. (This same approach was done above for MainGUI.this.)
Annotate the mainGUI parameter with final: public EditDialog(final MainGUI mainGUI) .... The member variable will still be shadowed, but the local variable will meet the access requirements as it's "final".
Happy coding.