Java Swing - Why is my first window not disposing/closing? - java

So I'm creating an application. I want main to initialize a login window, which I've done. And for now I want the login window to close whenever I click on the button, and when it closes, a new window (called MainWindow) opens with different buttons/info/text.
All these classes are separate, but in the same package.
The problem is: The main window opens when I click login, however the login window doesn't terminate/close.
My main method, from which I call the login window:
import javax.swing.*;
public class Main {
// Display Login Window
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new LoginWindow();
LoginWindow.createAndShowLoginGUI();
});
}
}
My login window class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class LoginWindow extends JFrame implements ActionListener {
public void prepareLoginGUI() {
// Frame with GridBagLayout
JFrame loginFrame = new JFrame("Login Window");
loginFrame.setSize(1200, 800);
loginFrame.setLayout(new GridBagLayout());
// Button for logging in, with respective GridBagConstraint
// setFocusable is set to false to take out the border around the text
JButton loginButton = new JButton("Login");
loginButton.addActionListener(this::actionPerformed);
loginButton.setActionCommand("Open");
GridBagConstraints lButtonC = new GridBagConstraints();
loginButton.setFocusable(false);
// Username text-field and JLabel with respective GridBagConstraints
JTextField tfUsername = new JTextField(15);
GridBagConstraints tfUserC = new GridBagConstraints();
JLabel txtUser = new JLabel("Username: ");
GridBagConstraints txtUserC = new GridBagConstraints();
// Password text-field and JLabel with respective GridBagConstraints
JPasswordField tfPassword = new JPasswordField(15);
GridBagConstraints tfPassC = new GridBagConstraints();
JLabel txtPassword = new JLabel("Password: ");
GridBagConstraints txtPassC = new GridBagConstraints();
// Add all components to the JFrame
// Making sure to add the text before the text-fields
loginFrame.add(txtUser, txtUserC);
loginFrame.add(tfUsername, tfUserC);
loginFrame.add(txtPassword, txtPassC);
loginFrame.add(tfPassword, tfPassC);
loginFrame.add(loginButton, lButtonC);
// Show and set close parameters
loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
loginFrame.setVisible(true);
}
// Instructions for when the login button is clicked
// Close this window, if button == open, which it does
#Override
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
if (cmd.equals("Open")) {
this.dispose();
this.setVisible(false);
new MainWindow();
MainWindow.createAndShowMainWGUI();
}
}
// Callable from Main class
public static void createAndShowLoginGUI() {
LoginWindow loginW = new LoginWindow();
loginW.prepareLoginGUI();
}
}
My Main Window Class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MainWindow extends JFrame implements ActionListener {
public void prepareMainWGUI(){
// Frame with GridBagLayout
JFrame loginFrame = new JFrame("Main Window");
loginFrame.setSize(1200, 800);
loginFrame.setLayout(new GridBagLayout());
// Username text-field and JLabel with respective GridBagConstraints
JLabel txtUser = new JLabel("It worked!");
GridBagConstraints txtUserC = new GridBagConstraints();
loginFrame.add(txtUser, txtUserC);
loginFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
loginFrame.setVisible(true);
}
// Callable from Main class
public static void createAndShowMainWGUI() {
MainWindow mainWind = new MainWindow();
mainWind.prepareMainWGUI();
}
}
If you use this code, when the main window opens, the login window will be right behind it.

You can use when pressing button
System.exit(0);
This will terminate your application. To close one window use(if you have open multiple windows) without affecting to others,
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE)
Then, to open new one,
new frameName().setvisible(true);
Example:
JButton closeButton = new JButton("Close");
closeButton .addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
this.dispose();//current(close only this) frame
new frameName().setvisible(true);
}
});
Take a look at this question.
UPDATE:
In below line you have extends JFrame but you didnot use it.
public class LoginWindow extends JFrame implements ActionListener {
Rather than that you have create new object from JFrame
JFrame loginFrame = new JFrame("Login Window");
All the component you are adding to the loginFrame. But when actionPerformed trying to this.dispose(), since you are not using extended JFrame nothing will happen.
Solution:
Declare your JFrame as a instance variable:
public class LoginWindow implements ActionListener {
JFrame loginFrame;
public void prepareLoginGUI() {
Then change,
this.dispose();
To:
loginFrame.dispose();
In this this.dispose(); call to the extended JFrame, no effect for your JFrame object(loginForm).
And one last thing, make sure to remove extends JFrame. Because you are not doing anything with extended JFrame. Read this post about extended JFrame.

Related

Unable to put buttons on frame?

I'm using currently Intellij to create a GUI with 3 buttons on the top of the main frame. I'm fairly new to GUI's and still learning as I go. When I try to run the code I get an error telling me that I cannot have the main method as static but if I remove the static I get an error saying I need it to be static. Is there a way to easily avoid this?
package CA3;
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent;
public class Main extends JFrame{
public static void main(String[] args) {
// Attach window listener
addWindowListener(new WindowCloser()); // Just in-case it's needed
// Adding first customer panel
JPanel pCustomerL = new JPanel();
pCustomerL.setBounds(0,0,750,750);
pCustomerL.setBackground(Color.BLUE);
// Adding second customer panel
JPanel pCustomerR = new JPanel();
pCustomerR.setBounds(750,0,750,750);
pCustomerR.setBackground(Color.BLACK);
// Adding first invoice panel
JPanel pInvoiceL = new JPanel();
pInvoiceL.setBounds(0,0,750,750);
pInvoiceL.setBackground(Color.BLUE);
// Adding second product panel
JPanel pInvoiceR = new JPanel();
pInvoiceR.setBounds(750,0,750,750);
pInvoiceR.setBackground(Color.BLACK);
// Button Listener
ButtonListener listener = new ButtonListener();
// Adding "Customer" Button
JButton b = new JButton("Customer");
b.addActionListener(listener);
add(b);
b.setBounds(1300,10,150,35);
// Adding "Product" Button
b = new JButton("Product");
b.addActionListener(listener);
add(b);
b.setBounds(1150,10,150,35);
// Adding "Invoice" Button
b = new JButton("Invoice");
b.addActionListener(listener);
add(b);
b.setBounds(1000,10,150,35);
// Adding first product panel
JPanel pProductL = new JPanel();
pProductL.setBounds(0,0,750,750);
//pProductL.setBackground(Color.BLUE);
// Adding second product panel
JPanel pProductR = new JPanel();
pProductR.setBounds(750,0,750,750);
//pProductR.setBackground(Color.BLACK);
// Frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setSize(1500,750);
frame.setVisible(true);
// Add panels
frame.add(pCustomerL);
frame.add(pCustomerR);
frame.add(pProductL);
frame.add(pProductR);
frame.add(pInvoiceL);
frame.add(pInvoiceR);
// Customer Panel Settings
pCustomerL.setVisible(true);
pCustomerR.setVisible(true);
// Product Settings
pProductL.setVisible(false);
pProductR.setVisible(false);
// Invoice settings
pInvoiceL.setVisible(false);
pInvoiceR.setVisible(false);
}
// Listener for buttons
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent evt) {
String buttonLabel = evt.getActionCommand();
}
}
// Listener for window
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent evt) { System.exit(0);}
}
}
You have to move your code inside the main to another method not-static or you can put it on a Constructor. The errors are because you are using normal methods like addWindowsListener which inherits from JFrame. And you also have to remove:
JFrame frame = new JFrame();
That's not necessary because your class already inherits from JFrame so your code must be like this:
public class Main extends JFrame
{
public Main(){
// Attach window listener
addWindowListener(new WindowCloser()); // Just in-case it's needed
// Adding first customer panel
JPanel pCustomerL = new JPanel();
pCustomerL.setBounds(0,0,750,750);
pCustomerL.setBackground(Color.BLUE);
// Adding second customer panel
JPanel pCustomerR = new JPanel();
pCustomerR.setBounds(750,0,750,750);
pCustomerR.setBackground(Color.BLACK);
// Adding first invoice panel
JPanel pInvoiceL = new JPanel();
pInvoiceL.setBounds(0,0,750,750);
pInvoiceL.setBackground(Color.BLUE);
// Adding second product panel
JPanel pInvoiceR = new JPanel();
pInvoiceR.setBounds(750,0,750,750);
pInvoiceR.setBackground(Color.BLACK);
// Button Listener
ButtonListener listener = new ButtonListener();
// Adding "Customer" Button
JButton b = new JButton("Customer");
b.addActionListener(listener);
add(b);
b.setBounds(1300,10,150,35);
// Adding "Product" Button
b = new JButton("Product");
b.addActionListener(listener);
add(b);
b.setBounds(1150,10,150,35);
// Adding "Invoice" Button
b = new JButton("Invoice");
b.addActionListener(listener);
add(b);
b.setBounds(1000,10,150,35);
// Adding first product panel
JPanel pProductL = new JPanel();
pProductL.setBounds(0,0,750,750);
//pProductL.setBackground(Color.BLUE);
// Adding second product panel
JPanel pProductR = new JPanel();
pProductR.setBounds(750,0,750,750);
//pProductR.setBackground(Color.BLACK);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
this.setSize(1500,750);
this.add(pCustomerL);
this.add(pCustomerR);
this.add(pProductL);
this.add(pProductR);
this.add(pInvoiceL);
this.add(pInvoiceR);
// Customer Panel Settings
pCustomerL.setVisible(true);
pCustomerR.setVisible(true);
// Product Settings
pProductL.setVisible(false);
pProductR.setVisible(false);
// Invoice settings
pInvoiceL.setVisible(false);
pInvoiceR.setVisible(false);
this.setVisible(true);
}
// Listener for buttons
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent evt) {
String buttonLabel = evt.getActionCommand();
}
}
// Listener for window
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent evt) { System.exit(0);}
}
public static void main(String[] args) {
new Main();
}
}

How can I dynamically add these elements to my JFrame?

I separated my GUI/JFrame from my Panel class so that I can keep the Swing components away from the rest of my code. However, I have a button that I would like to update my Frame in real time before I run a method from my Main class, but I can't get it to work. It looks something like (pseudocode):
public class GUI extends JFrame
{
public GUI()
{
//frame setup
Login login = new Login(this);
frame.add(login);
while(login.shouldContinue){login.panel.revalidate()}
//continue
}
}
public class Login
{
Jpanel panel;
Main main;
Frame frame;
boolean shouldContinue;
public Login(Frame frame)
{
this.frame = frame;
this.panel= new JPanel();
this.main = new Main();
//other panel elements
JButton btn1 = new JButton ("Login");
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0){
JLabel label = new JLabel("Logging in");
panel.add(label);
frame.add(panel);
main.login();
panel.remove(label1);
JLabel label2 = new JLabel("Login Successful");
panel.add(label2);
frame.add(panel);
this.shouldContinue=false;
}
}
}
The other elements of the panel display just fine, but when I click the button, nothing happens. How can I make the frame display the updated panel before running main.login()? I tried revalidating/repainting the panel but it didn't work.
You are describing the functionality provided by (J)Dialog.setModal(). But these days, an even easier way to do this is to just use JOptionPane
Login l = new Login();
res = JOptionPane.showConfirmDialog(null, login, "login", JOptionPane.OK_CANCEL_OPTION);
if (res == JOptionPane.OK_OPTION) {
...
}

Why is my text field not appearing?

I have to create a text field, a text area, and two buttons, but I am stuck on the text field because I cant get it to appear when I run my program. My JFrame keeps appearing empty.
public class SentanceBuilder extends JFrame {
private JTextField textField = new JTextField(50);
private JTextArea textArea = new JTextArea(200,200);
private JButton Submit = new JButton();
private JButton Cancel = new JButton();
public SentanceBuilder(){
textField.setVisible(true);
textField.setLocation(50, 50);
this.textField();
this.setSize(400, 300);
this.setLocationRelativeTo(null);
this.setVisible(true);
}
public void textField(){
String textContent = textField.getText();
}
}
You never add the textField variable to a container such as a JPanel that is held by the top-level window, such as a JFrame. In fact, in your code, you add nothing to your JFrame!
If this were my GUI, I'd
Create my JTextField
Create a main JPanel to hold my components.
Add it and other components to the main JPanel via the JPanel's add(...) method.
Add the main JPanel to the JFrame's contentPane via the JFrame's add(...) method.
Call pack() and then setVisible(true) on the JFrame, but only after adding all components to it, not before.
Read the Swing tutorials since this beats guessing every time. You can get links to the tutorials at the Swing Tag Info link.
e.g.,
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class MyFoo extends JFrame {
private static final long serialVersionUID = 1L;
private JTextField textField = new JTextField(10);
private JButton button = new JButton("Foo Button");
public MyFoo() {
super("My JFrame");
// so Java will end when GUI is closed
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
// code to be called when button is pushed
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// TODO code that runs when button is pushed.
}
});
// panel to hold everything
JPanel mainPanel = new JPanel();
// add all to the panel
mainPanel.add(new JLabel("Text Field:"));
mainPanel.add(textField);
mainPanel.add(button);
// add the panel to the main GUI
add(mainPanel);
}
// start up code
private static void createAndShowGui() {
JFrame mainFrame = new MyFoo();
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
public static void main(String[] args) {
// call start up code in a Swing thread-safe way
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Java gui Jbutton

I have a program but I can't combine the textfield and the button in the same frame like in top textfield and below that the button:
Here is my source code:
import java.awt.*;
import javax.swing.*;
public class FirstGui extends JFrame
{
JTextField texts;
JButton button;
public FirstGui()
{
texts = new JTextField(15);
add(texts);
button = new JButton("Ok");
add(button);
}
public static void main(String args [])
{
FirstGui gui = new FirstGui();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setSize(200,125);
gui.setVisible(true);
}
}
Add a layout like FlowLayout:
public FirstGui()
{
setLayout(new FlowLayout());
texts = new JTextField(15);
add(texts);
button = new JButton("Ok");
add(button);
}
at the very beginning of your constructor, before anything else.
The default layout is BorderLayout for JFrame. When you add components to a BorderLayout, if you don't specify their BorderLayout position, like BorderLayout.SOUTH, the component will automatically be add to BorderLayout.CENTER. Bthe thing is though, each position can only have one component. So when you add texts it gets added to the CENTER. Then when you add button, it gets added to the CENTER but texts gets kicked out. So to fix, you can do
add(texts, BorderLayout.NORTH);
add(button, BorderLayout.CENTER);
See Laying out Components Within a Container to learn more about layout managers.
UPDATE
import java.awt.*;
import javax.swing.*;
public class FirstGui extends JFrame {
JTextField texts;
JButton button;
public FirstGui() {
texts = new JTextField(15);
add(texts, BorderLayout.CENTER);
button = new JButton("Ok");
add(button, BorderLayout.SOUTH);
}
public static void main(String args[]) {
FirstGui gui = new FirstGui();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.pack();
gui.setVisible(true);
}
}

how can I make this class an applet

I have the following class which is a simple gui, and I would like to make it an applet so it can be displayed in the browser. I know how to embed the code into an html page(got that done)... but how can make my class an applet? Also, I assuming I don't need a web server just to display the applet in my browser...
package tester1;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class PanelTest implements ActionListener {
JFrame frame;
JLabel inputLabel;
JLabel outputLabel;
JLabel outputHidden;
JTextField inputText;
JButton button;
JButton clear;
JButton about;
public PanelTest() {
frame = new JFrame("User Name");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(3, 2, 10, 10));
//creating first row
JPanel row1 = new JPanel();
inputLabel = new JLabel("Your Name");
inputText = new JTextField(15);
// FlowLayout flow1 = new FlowLayout(FlowLayout.CENTER, 10, 10);
// row1.setLayout(flow1);
row1.add(inputLabel);
row1.add(inputText);
frame.add(row1);
//creating second row
JPanel row2 = new JPanel();
button = new JButton("Display");
clear = new JButton("Clear");
about = new JButton("About");
button.addActionListener(this);
clear.addActionListener(this);
about.addActionListener(new displayAbout());
row2.add(button);
row2.add(clear);
row2.add(about);
frame.add(row2);
//creating third row
JPanel row3 = new JPanel();
outputLabel = new JLabel("Output:", JLabel.LEFT);
outputHidden = new JLabel("", JLabel.RIGHT);
// FlowLayout flow2 = new FlowLayout(FlowLayout.CENTER, 10, 10);
// row3.setLayout(flow2);
row3.add(outputLabel);
row3.add(outputHidden);
frame.add(row3);
frame.pack();
frame.setVisible(true);
}
//same method listen for two different events
#Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if(command.equals("Display")) {
outputHidden.setText(inputText.getText());
}
if(command.equals("Clear")) {
outputHidden.setText("");
inputText.setText("");
}
}
//another way to listen for events
class displayAbout implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(frame, "Username 1.1 \n by Jorge L. Vazquez");
}
}
public static void main(String[] args) {
PanelTest frameTest = new PanelTest();
}
}
Use a JApplet rather than a JFrame. Make sure you read the relevant Java Tutorial, which covers the applet lifecycle methods like init, start, stop, and destroy.
As a side note, you should not be building your UI outside of the event dispatch thread.
Use a JApplet instead of a JFrame like veer said, but you must also remove frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);, frame.pack();, and frame.setVisible(true);
Also, replace main(String[] args) with init().

Categories