I'm new to java coming from C# so I'm not familiar with java best practices.
I have a main class that opens a JFrame to get several input strings from a user. When the user clicks submit the GUI should close and the main class continue processing using the input.
This is the main class:
public class Main {
FInput fInput;
public void main(String[] args) {
if(args.length==0)
{
fInput = new FInput();
fInput.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fInput.pack();
fInput.setVisible(true);
}
else
startProcess(args);
}
public void startProcess(String[] args) {
// Do stuff
}
The main class will use this frame to get input from the user:
public class FInput extends JFrame{
private JTextField txtSourceDirectory;
private JTextField txtTargetDirectory;
private JTextField txtDefectNumber;
private JTextField txtSliceTokens;
private JButton btnStart;
public FInput() {
// Initialize text fields and button
JButton.addActionListener(something);
}
}
In all the examples I could find, the listener would be a FMain itself. However in this case I want Main to listen and use the input in method startProcess.
Would having Main implement ActionListener, and passing it to FMain constructor is the way to go?
Yes, that is the right idea. You must do two things in order to be able to do that, though:
Put this at the beginning of the FInput class:
Main m = new Main(this);
Then, put these lines somewhere in the Main class...
FInput gui;
public Main(FInput in) { gui = in; }
Now you can refer to any component in the FInput class from the Main class by doing something like this.
gui.someComponent ...
To set up listeners just write someComponent.addItemListener(m); or something of the sort.
Hope this helps!
#Yoav In response to your latest comment...
You don't have to separate the listening class from the GUI class; you can combine the two into one class...
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends JFrame implements ActionListener {
private JTextField txtSourceDirectory;
private JTextField txtTargetDirectory;
private JTextField txtDefectNumber;
private JTextField txtSliceTokens;
private JButton btnStart;
public Main() {
txtSourceDirectory = new JTextField(40); //change this to the amount of characters you need
txtTargetDirectory = new JTextField(40);
txtDefectNumber = new JTextField(40);
txtSliceTokens = new JTextField(40);
btnStart = new JButton("Start");
add(txtSourceDirectory);
add(txtTargetDirectory);
add(txtDefectNumber);
add(txtSliceTokens);
add(btnStart);
btnStart.addActionListener(this);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setVisible(true);
}
public void actionPerformed(ActionEvent event) {
//do stuff
}
static void startProcess(String[] ARGS) {
//do stuff
}
public static void main(String[] args) {
if (args.length == 0) {
Main frame = new Main();
} else {
startProcess(args);
}
}
}
Also consider using JOptionPane, shown here, in your Main class. You can customize the appearance, including button text, as shown in How to Make Dialogs.
First main method in java always must be public static void. Below is example how this can be done.
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.JPanel;
import javax.swing.JTextField;
/**
* Main class is frame but also implements ActionListener interface.
*/
public class Main extends JFrame implements ActionListener {
private JButton btnStart;
private static Main frame;
public Main() {
JPanel panel = new JPanel();
btnStart = new JButton("Press me");
// Add action listener. Listener could be any class that implements
// ActionListener
btnStart.addActionListener(this);
// This means add button btnStart to panel
panel.add(btnStart);
// This means add panel to frame
this.add(panel);
}
// main method in java always must be public, static and void. You forgot to
// put static.
public static void main(String[] args) {
if (args.length == 0) {
frame = new Main();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
} else
frame.startProcess(args);
}
public void startProcess(String[] args) {
// TODO
}
#Override
public void actionPerformed(ActionEvent arg0) {
// Here you put your code that is executed every time you press button.
// For example you just want to show message.
JOptionPane.showMessageDialog(this, "You pressed Button.");
}
}
But it is much better to have special class. For example:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class ButtonListener implements ActionListener {
JFrame parent;
public ButtonListener(JFrame parent) {
this.parent = parent;
}
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(parent, "You pressed Button");
}
}
And in the main class you just add action listener to button:
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.JPanel;
import javax.swing.JTextField;
/**
* Main class is frame but also implements ActionListener interface.
*/
public class Main extends JFrame {
private JButton btnStart;
private static Main frame;
public Main() {
JPanel panel = new JPanel();
btnStart = new JButton("Press me");
ButtonListener listener = new ButtonListener(this);
// Add action listener. Listener could be any class that implements
// ActionListener
btnStart.addActionListener(listener);
// This means add button btnStart to panel
panel.add(btnStart);
// This means add panel to frame
this.add(panel);
}
// main method in java always must be public, static and void. You forgot to
// put static.
public static void main(String[] args) {
if (args.length == 0) {
frame = new Main();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
} else
frame.startProcess(args);
}
public void startProcess(String[] args) {
// TODO
}
}
Related
Here I have this code below which reverses a text.
TextFrame Class the main frame of my GUI
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
public class TextFrame extends JFrame implements ActionListener{
private Controls theControls;
private ReverseText theReverseText;
private InputOutputPanel theInputOutputPanel;
public TextFrame(){
this.getContentPane().setLayout(new BorderLayout());
theInputOutputPanel = new InputOutputPanel();
theReverseText = new ReverseText(this);
theControls = new Controls(theReverseText);
this.getContentPane().add(theInputOutputPanel, BorderLayout.NORTH);
this.getContentPane().add(theControls, BorderLayout.SOUTH);
this.pack();
this.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent ae) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
public Controls getControls(){
return this.theControls;
}
public InputOutputPanel getInputOutPanel(){
return this.theInputOutputPanel;
}
public static void main(String[] args) {
// All we need to do is create the frame, as the constructor does everything required.
TextFrame theFrame = new TextFrame();
// theFrame.setSize(150, 150);
// theFrame.setVisible(true);
}
}
InputOutPut Class Panel which handles the input and output
import java.awt.GridLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class InputOutputPanel extends JPanel {
private JTextField input;
private JTextField output;
private JTextField situation;
public InputOutputPanel() {
this.setLayout(new GridLayout(2, 2));
this.add(new JLabel("header"));
this.add(situation = new JTextField("Situation"));
this.add(input = new JTextField("input text here"));
this.add(output = new JTextField());
}
public void setSituation(String sit){
situation.setText(sit);
}
public void setOutPut(String s){
output.setText(s);
}
public String getInput(){
return input.getText();
}
}
Controls class
import javax.swing.JButton;
import javax.swing.JPanel;
public class Controls extends JPanel {
private ReverseText reverseText; //the Event handler
private TextFrame theTextFrame; // the main frame to display the text
public Controls(ReverseText reverseText){
this.reverseText = reverseText;
reverseText = new ReverseText(theTextFrame);
JButton reversetheTextButton;
this.add(reversetheTextButton = new JButton("Text-Reverse"));
reversetheTextButton.addActionListener(reverseText);
}
}
ReverseText Class which is my event handler
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
import java.awt.event.ActionListener;
public class ReverseText implements ActionListener {
private TextFrame theTextFrame;
private InputOutputPanel inputOutPanel;
public ReverseText(TextFrame theTextFrame) {
this.theTextFrame = theTextFrame;
}
#Override
public void actionPerformed(ActionEvent event) {
String buttonAction = event.getActionCommand();
// trying to use the mainframe to get other components
inputOutPanel = theTextFrame.getInputOutPanel(); // but this line complaining about null pointer error
String input = inputOutPanel.getInput();
if (buttonAction.equals("Text-Reverse"))
System.out.println("yes");
inputOutPanel.setSituation(buttonAction);
//Reverse The Text and send it to the Output
String reversedText = new StringBuffer(input).reverse().toString();
//
inputOutPanel.setOutPut(reversedText);
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
}
}
I want to use the mainframe in my event handler class to call these components butthis is not working.
I have get and set methods in my main Frame called TextFrame.
My question is how do I use my event handler class using the main frame cato take input from the GUI and reverse this input.
You never set the Controls TextFrame field with any TextFrame instance. You need to pass it into the Controls constructor via a parameter, just as you do the model.
public class Controls extends JPanel {
private ReverseText reverseText; //the Event handler
private TextFrame theTextFrame; // the main frame to display the text
// **** note changes to constructor
public Controls(ReverseText reverseText, TextFrame theTextFrame){
this.reverseText = reverseText;
this.theTextFrame = textFrame; // ***** added
reverseText = new ReverseText(theTextFrame);
Then change:
theControls = new Controls(theReverseText, this); // **** note change
after new JButton(...), call setActionCommand on the button. Otherwise you just set the label, and the listener won't get an ActionCommand of the button even when the listener is fired.
I had a problem and found a solution, but I can't understand why this following code is not working.
What I want to do is, that the tab is switching when a button gets pressed in the "Administration.class".
I got a JTabbedPane which is added in the "Main.class". It is declared as a private variable.
private JTabbedPane JPT;
then I have a simple method, which shall change the tab, when called:
public void SetPane() {
JTP.setSelectedIndex(2);
}
Then I am creating a object of the Main.class in the Administration.class and calling this method, when the button is pressed:
btnRework.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Main m = new Main();
m.SetPane();
}
});
But this is not working. Nothing happens, when the button gets clicked, I even get not error.
This works:
Main.class
public static JTabbedPane JTP;
Administration.class
btnRework.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Main.JTP.setSelectedIndex(2);
}
});
Why example first is not working, and maybe you guys have a link, where I could have a look to a content which is describing this problem. If you just wanna handle a variable and their methods, what is the better way?
Thanks in advance!
Main.class:
public class Main extends JDialog {
private static final long serialVersionUID = 1L;
private Home home = new Home();
private Insertation insertation = new Insertation();
private Edit edit = new Edit();
private Administration administration = new Administration();
private Addition addition = new Addition();
public static JTabbedPane JTP;
/**
* Launch the application.
*/
public static void main(String[] args) {
try {
Main dialog = new Main();
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Create the dialog.
*/
public Main() {
super(null, java.awt.Dialog.ModalityType.TOOLKIT_MODAL);
setResizable(false);
setSize(1030, 720);
getContentPane().setLayout(new BorderLayout());
setTitle("Ebay Manager");
JTP = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
JTP.addTab("Home", home);
JTP.addTab("Inserat", insertation);
JTP.addTab("Bearbeitung", edit);
JTP.addTab("Verwaltung", administration);
JTP.addTab("Zusatz", addition);
getContentPane().add(JTP);
}
}
Administration.class:
public class Administration extends JPanel {
private static final long serialVersionUID = 1L;
private JButton btnRework;
private Main main;
/**
* Create the panel.
*/
public Administration() {
setLayout(null);
setSize(1000, 650);
setDoubleBuffered(true);
btnRework = new JButton("Bearbeiten");
btnRework.setBounds(42, 571, 116, 32);
add(btnRework);
btnRework.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
main.SetPane();
}
});
}
}
You are switching panes in a new undrawn frame that you create and throw away inside your action listener. You need to switch panes in the frame that you have (presumably) packed and drawn in your application.
So instead of
Main m = new Main();
m.SetPane();
you need
myMainFrame.SetPane();
Exactly how you create and remember myMainFrame is beyond the scope of this answer (unless you add more code to your question).
Main m = new Main();
m.SetPane();
Here, you are creating an instance of Main but you are not adding to it anywhere.
Edit:
import java.awt.BorderLayout;
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.JTabbedPane;
public class Administrator extends JFrame {
private Main main;
public Administrator() {
main = new Main();
add(main);
JButton button = new JButton("Set");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
main.setPane();
}
});
add(button, BorderLayout.SOUTH);
}
public static void main(String[] args) {
Administrator adminFrame = new Administrator();
adminFrame.setSize(400, 400);
adminFrame.setVisible(true);
}
}
class Main extends JPanel {
private JTabbedPane jtp;
public Main() {
super(new BorderLayout());
jtp = new JTabbedPane();
jtp.add("tab1", new JLabel("Content1"));
jtp.add("tab2", new JLabel("Content2"));
add(jtp);
}
public void setPane() {
jtp.setSelectedIndex(1);
}
}
I found my own solution because of the answer of rdonuk. Since I can't make another instance of the Main.class I set the JTabbedPane as variable in the Administration.class when creating the Main.class. Just a easy setter method. Thanks for all answers!
I have a program which displays two buttons and changes the image of one of the buttons on roll over. I am getting an error on my
press.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
part, And it looks like this: The method setDefaultCloseOperation(int) is undefined for the type ButtonClass. Even with the exit on close commented out there are more errors, please help.
Main class (with error):
package Buttons;
import javax.swing.JFrame;
public class Main_buttons{
public static void main(String[] args) {
ButtonClass press = new ButtonClass();
press.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
press.setSize(300,200);
press.setVisible(true);
}
}
ButtonClass class:
package Buttons;
import java.awt.FlowLayout; //layout proper
import java.awt.event.ActionListener; //Waits for users action
import java.awt.event.ActionEvent; //Users action
import javax.swing.JFrame; //Window
import javax.swing.JButton; //BUTTON!!!
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane; //Standard dialogue box
public class ButtonClass extends JButton {
private JButton regular;
private JButton custom;
public ButtonClass() { // Constructor
super("The title"); // Title
setLayout(new FlowLayout()); // Default layout
regular = new JButton("Regular Button");
add(regular);
Icon b = new ImageIcon(getClass().getResource("img.png"));
Icon x = new ImageIcon(getClass().getResource("swag.png"));
custom = new JButton("Custom", b);
custom.setRolloverIcon(x); //When you roll over the button that says custom the image will change from b to x
add(custom);
Handlerclass handler = new Handlerclass();
regular.addActionListener(handler);
custom.addActionListener(handler);
}
private class Handlerclass implements ActionListener { // This class is inside the other class
public void actionPerformed(ActionEvent eventvar) { // This will happen
// when button is
// clicked
JOptionPane.showMessageDialog(null, String.format("%s", eventvar.getActionCommand()));//Opens a new window with the name of the button
}
}
}
I have searched everywhere for this problem and found nothing. Please tell me how to resolve this issue about exiting my window.
Thanks!
You're a little confused as you're creating a class that extends JButton, and calling setVisible(true) on it as if it were a top-level window such as a JFrame or JDialog, and that doesn't make sense. Since it isn't a top-level window it also makes sense to not have a default close operation or understand what that means.
I suggest that you call this method only on top-level windows such as on a JFrame or JDialog and the like. As a side recommendation, I usually avoid setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); and instead more often do setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); which gives it a little more flexibility.
Edit: actually, just change your class to extends JFrame not extends JButton.
Make sure your image path to your resources is correct. For example:
that method is defined for JFrame, not JButton. You're calling it on an instance of a class that extends JButton
The JFrame.Exit_on_close must be used in a JFrame, and you are extending from JButton.
To set a JButton to close a JFrame its something like this.
public class MyClass extends JFrame implements ActionListener{
private JButton button = new JButton("Button");
private JPanel panel = new JPanel();
public static void main(String args[]) {
new MyClass();
}
public MyClass() {
setSize(300, 300);
button.addActionListener(this);
panel.add(button);
add(panel);
setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
this.dispose();
}
}
I probably have a really simple problem. I want to create two frames - mainfr (in the class called Pag) and dscrpt (in a class called Apras). I managed to create the first frame (mainfr) and the second frame (dscrpt) using button skaiciav from the frame mainfr. When question is how to come back to the first frame using the button griz located in frame dscrp?
package grap;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Pag implements ActionListener {
JFrame mainfr;
JFrame apras;
JLabel psl_apras;
JLabel galim_veiksm;
JLabel paspaud;
public Pag() {
//Create JFrame container
mainfr = new JFrame("Turinys");
//Choosing layout type
mainfr.setLayout(new FlowLayout());
//window resolution
mainfr.setSize(500, 300);
//Program terminates on close
mainfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Label's
psl_apras = new JLabel("Mokomoji programa");
galim_veiksm = new JLabel("Galimi veiksmai");
//adding them to main frame
mainfr.add(psl_apras);
mainfr.add(galim_veiksm);
//Button
JButton skaiciav = new JButton("Description");
//action listener
skaiciav.addActionListener(this);
//adding button to frame
mainfr.add(skaiciav);
//another label
paspaud = new JLabel("Press button");
//adding label to frame
mainfr.add(paspaud);
//making frame visible
mainfr.setVisible(true);
}
//action listener method
public void actionPerformed(ActionEvent a) {
if(a.getActionCommand().equals("Description"))
{
Apras.suk();
mainfr.setVisible(false);
}
//Started to get confused here
/*if(a.getActionCommand().equals("back")){
mainfr.setVisible(true);
apras.setVisible(false);
dscrp.dispose();
*/
}
public static void main (String args[]) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new Pag();
}
});
}
}
Second class
package grap;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Apras {
static JFrame dscrp;
static void suk() {
dscrp = new JFrame("Description");
dscrp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame2.setLocationByPlatform(true);
dscrp.setBackground(Color.WHITE);
JButton griz = new JButton("back");
//griz.addActionListener();
dscrp.add(griz);
dscrp.setSize(500, 300);
dscrp.setVisible(true);
}
}
Working in Java: I have a JFrame class, and separate classes for my two JPanels that are added to the JFrame. One of the JPanel classes has some buttons in it, which can interact with each other(when I click on one button, it can disable another button). However, I can't figure out how to get the button to call a method in the other JPanel (written in a separate class).
So, my program look like this:
JFrame
Jpanel1
Jpanel2 - This class has my buttons in it, I'm trying to get them to interact with the JPanel1 object.
Any tips appreciated, thanks!
One way to do this is to pass an instance of (to use your terminology) Jpanel1 into Jpanel2. This doesn't have to be done in the constructor, you can have a setConnectedPanel(JPanel) method, for example.
Here's some code that demonstrates what you want to do:
MyFrame.java
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class MyFrame extends JFrame {
public MyFrame() {
ReactionPanel rp = new ReactionPanel();
ActionPanel ap = new ActionPanel(rp);
setLayout(new GridLayout(2, 1));
add(ap);
add(rp);
pack();
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new MyFrame();
}
});
}
}
ActionPanel.java
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JPanel;
public class ActionPanel extends JPanel implements ActionListener {
private ReactionPanel rp;
private JButton button;
public ActionPanel(ReactionPanel rp) {
this.rp = rp;
button = new JButton("Click");
button.addActionListener(this);
this.add(button);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(button)) {
rp.react();
}
}
}
ReactionPanel.java
import javax.swing.JLabel;
import javax.swing.JPanel;
public class ReactionPanel extends JPanel {
private JLabel label;
public ReactionPanel() {
label = new JLabel("PING");
this.add(label);
}
public void react() {
if(label.getText().equals("PING")) {
label.setText("PONG");
} else {
label.setText("PING");
}
}
}
As you can see, I tend to override all of my JFrames/JPanels when I write Swing GUIs as I find it easier and more flexible but YMMV.