Simple Java GUI Program - java

My JPanel and JTextField are for some reason not appearing. The programs only task is to add a number to the counter every time the button is clicked. No compiling errors nor console issues. Simply not showing up??
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Swing
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
final JFrame mainFrame = new JFrame ("Counter (Program 1/2)");
mainFrame.setVisible(true);
mainFrame.setSize(400, 200);
mainFrame.setLayout(new BorderLayout());
mainFrame.setLocationRelativeTo(null);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton countButton = new JButton("Count up");
mainFrame.add(countButton, BorderLayout.SOUTH);
countButton.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
JTextField clicks = new JTextField(BorderLayout.CENTER);
JPanel firstPanel = new JPanel();
mainFrame.add(firstPanel);
mainFrame.add(clicks, BorderLayout.NORTH);
int counter = 1;
counter++;
String textField = String.valueOf(counter);
clicks.setText(textField);
}
});
}
});
}
}

Don't add the JTextField and JPanel inside the ActionListener. This makes no sense since you'll be re-adding new components each time the button is pressed. Instead add them on GUI creation, before calling setVisible(true) on the GUI. Then update the text field's text in the ActionListener.
As a side recommendation: try to make your class more object oriented by giving it fields, a constructor, and getting most all of that code out of the static main method.

Your mistakes:
Add clicks and firstpanel to the frame in run method, not in the actionPerformed
BorderLayout.CENTER should be pass as a parameter to add method, not to the text field constructor.
Define count as static. This is not the best way but in your situation it is the easiest way.
Call mainFrame.setVisible(true); after you added all your components.
Here is the working code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Swing {
public static int counter = 1;
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
final JFrame mainFrame = new JFrame("Counter (Program 1/2)");
mainFrame.setSize(400, 200);
mainFrame.setLayout(new BorderLayout());
mainFrame.setLocationRelativeTo(null);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton countButton = new JButton("Count up");
mainFrame.add(countButton, BorderLayout.SOUTH);
final JTextField clicks = new JTextField(String.valueOf(counter));
JPanel firstPanel = new JPanel();
mainFrame.add(firstPanel, BorderLayout.CENTER);
mainFrame.add(clicks, BorderLayout.NORTH);
countButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
counter++;
String textField = String.valueOf(counter);
clicks.setText(textField);
}
});
mainFrame.setVisible(true);
}
});
}
}

Related

how to send string from ChildFrame to ParentFrame and repaint ParentFrame?

ParentFrame shows ArrayList and one "ADD" Button. Once I click "ADD" Button on ParentFrame, then ChildFrame shows up.
On ChildFrame, I type in a String and click "OK" Button then it should transfer its String to ParentFrame. Finally ParentFrame should be repainted with newly added String.
I'm having trouble with repainting but also I might failed to send String from Child to Parent since Parent didn't get repainted.
I tried several things in two or three other points of view but following code seems like to work but......
I need your help!!
ParentFrame
import javax.swing.*;
import java.awt.event.*;
import java.util.*;
import java.awt.*;
#SuppressWarnings("serial")
public class parentFrame extends JFrame {
ArrayList<String> list = new ArrayList<>(){{add("test1"); add("test2");}};
JButton add;
JPanel big, small;
JLabel content;
childFrame addFrame;
public parentFrame() {
super("parent frame");
super.setLayout(new BorderLayout());
super.setSize(600,600);
big = new JPanel();
for(int i=0; i<list.size(); i++) {
content = new JLabel();
content.setText(list.get(i));
big.add(content);
}
super.add(big, BorderLayout.CENTER);
add = new JButton("ADD");
add.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
addFrame = new childFrame();
/* By next 3 lines, I'm trying to transfer the value of childFrame's test to this parentFrame's list. */
list.add(addFrame.getTestString());
big.revalidate();
big.repaint();
}
});
super.add(add, BorderLayout.SOUTH);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new parentFrame();
}
}
2.ChildFrame
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
#SuppressWarnings("serial")
public class childFrame extends JFrame {
String test;
JTextField name;
JButton ok, cancel;
public childFrame() {
super("child frame");
super.setLayout(new BorderLayout());
super.setSize(400,200);
JPanel centerPanel = new JPanel(new GridLayout(1,1));
centerPanel.setSize(150, 100);
name = new JTextField();
centerPanel.add(name);
JPanel bottomPanel = new JPanel(new FlowLayout());
ok = new JButton("OK");
ok.addActionListener(new OKListener());
super.add(ok);
cancel = new JButton("CANCEL");
cancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dispose();
}
});
bottomPanel.add(cancel);
bottomPanel.add(ok);
super.add(centerPanel, BorderLayout.CENTER);
super.add(bottomPanel, BorderLayout.SOUTH);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class OKListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
test = name.getText();
dispose();
}
}
public String getTestString() {
return test;
}
}
Your problem is here:
public void actionPerformed(ActionEvent e) {
addFrame = new childFrame();
list.add(addFrame.getTestString());
big.revalidate();
big.repaint();
}
Since your child frame is not a modal window (for example, a JOptionPane is a modal dialog window), it does not halt program flow in the calling window. You call .getTestString() immediately on creation of the child frame but before the user has had any chance to enter in any data (again, because program flow in the calling window is not halted).
The solution is to make your child "frame" in fact a modal JDialog. This will pretty much solve the whole issue. So, don't have the child frame extend from JFrame, but rather extend JDialog, and use the JDialog constructor that makes it modal (see the JDialog API).
e.g.,
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
#SuppressWarnings("serial")
// note that class names should begin with an upper-case letter
public class ChildFrame extends JDialog {
String test;
JTextField name;
JButton ok, cancel;
public ChildFrame(JFrame parentFrame) {
// the true parameter makes this modal
super(parentFrame, "child frame", true);
Now this dialog window will freeze program flow from the calling code as soon as the dialog is set visible, and the calling code flow won't resume until this dialog is no longer visible.
Also, please have a look at The Use of Multiple JFrames, Good/Bad Practice?
An alternative to this is to continue to use multiple JFrames (not recommended!!), and add a WindowListener to the "child" window, listening for windows closing events, and then getting the information from your dialog in call-back method that is activated when the windows closing event occurs.
For a working example:
import java.awt.BorderLayout;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class ParentGuiPanel extends JPanel {
private DefaultListModel<String> listModel = new DefaultListModel<>();
private JList<String> jList = new JList<>(listModel);
private JButton addButton = new JButton("Add");
private JDialog childDialog;
private ChildGuiPanel childPanel = new ChildGuiPanel();
public ParentGuiPanel() {
listModel.addElement("Test 1");
listModel.addElement("Test 2");
jList.setPrototypeCellValue("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
jList.setVisibleRowCount(8);
JScrollPane scrollPane = new JScrollPane(jList);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
addButton.addActionListener(e -> addActionPerformed(e));
addButton.setMnemonic(KeyEvent.VK_A);
JPanel buttonPanel = new JPanel();
buttonPanel.add(addButton);
setLayout(new BorderLayout());
add(scrollPane);
add(buttonPanel, BorderLayout.PAGE_END);
}
private void addActionPerformed(ActionEvent e) {
Window window = null;
if (childDialog == null) {
window = SwingUtilities.getWindowAncestor(this);
if (window == null) {
return;
}
childDialog = new JDialog(window, "Child GUI", ModalityType.APPLICATION_MODAL);
childDialog.add(childPanel);
childDialog.pack();
childDialog.setLocationRelativeTo(window);
}
if (childDialog != null) {
childDialog.setVisible(true);
String text = childPanel.getText();
if (!text.trim().isEmpty()) {
listModel.addElement(text);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
JFrame mainGui = new JFrame("Main GUI");
mainGui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
ParentGuiPanel mainPanel = new ParentGuiPanel();
mainGui.add(mainPanel);
mainGui.pack();
mainGui.setLocationRelativeTo(null);
mainGui.setVisible(true);
});
}
}
#SuppressWarnings("serial")
class ChildGuiPanel extends JPanel {
private JTextField textField = new JTextField(15);
private JButton okButton = new JButton("OK");
private JButton cancelButton = new JButton("Cancel");
public ChildGuiPanel() {
okButton.addActionListener(e -> okActionPerformed(e));
cancelButton.addActionListener(e -> cancelActionPerformed(e));
textField.addActionListener(e -> okActionPerformed(e));
okButton.setMnemonic(KeyEvent.VK_O);
cancelButton.setMnemonic(KeyEvent.VK_C);
add(new JLabel("Text: "));
add(textField);
add(okButton);
add(cancelButton);
}
public String getText() {
return textField.getText();
}
private void disposeWindow() {
textField.selectAll();
Window window = SwingUtilities.getWindowAncestor(this);
if (window != null) {
window.dispose();
}
}
private void okActionPerformed(ActionEvent e) {
disposeWindow();
}
private void cancelActionPerformed(ActionEvent e) {
textField.setText("");
disposeWindow();
}
}

JPanel does not appear when i try to add it to ContentPane

I'm having a problem trying to change JPanels by using buttons. I have a JFrame with 2 panels, 1 of them is for the buttons, which i want them to always be showed. The other one is the one that i will be switching everytime i press one ot the buttons of the other panel. The problem is that everytime i press them nothing really ever displays, i keep my buttons but the other panel that i call does not appear.
Code for one of the buttons is as follows
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
ReparacaoPanel r = new ReparacaoPanel(this, this.jPanel1);
this.getContentPane().remove(this.jPanel1);
this.getContentPane().add(r);
//this.setContentPane(r);
this.visiblePanel.setVisible(false);
this.visiblePanel = r;
this.pack();
this.setVisible(true);
r.setLocation(200, 200);
this.getContentPane().revalidate();
this.repaint();
}
If i try to use "this.setContentPane(r);" (it sets the frame to only show the panel) the panel shows. But when i try to call it as i'm trying to do in the code above nothing is showed apart from the panel that has the buttons.
I have no idea what i'm doing wrong, it does not seem to be a problem with the JPanel that i'm trying to call as it shows if used alone.
Anyone can help me out?
Consider this working example for switching manually between panels. Which produces this output.
.........
Some tiny NumberPanel
Every new instance shows another number in the center.
import javax.swing.JPanel;
public class NumberPanel extends JPanel {
private static int counter = 0;
public NumberPanel() {
setLayout(new BorderLayout(0, 0));
JLabel lblNewLabel = new JLabel("" + counter++);
lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);
add(lblNewLabel);
}
}
Setting up a frame
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.getContentPane().add(panel, BorderLayout.SOUTH);
JButton btnNewButton = new JButton("New button");
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.getContentPane().remove(numberPanel);
numberPanel = new NumberPanel();
frame.getContentPane().add(numberPanel, BorderLayout.CENTER);
frame.pack();
}
});
panel.add(btnNewButton);
numberPanel = new NumberPanel();
frame.getContentPane().add(numberPanel, BorderLayout.CENTER);
frame.pack();
}
Testprogram
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TestPanelSwitch {
private JFrame frame;
private NumberPanel numberPanel;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TestPanelSwitch window = new TestPanelSwitch();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public TestPanelSwitch() {
initialize();
}
private void initialize() {
// see above
}
}
Back to the Question
I think you only need to pack your frame, like in the anonymous ActionListener.
frame.getContentPane().remove(numberPanel);
numberPanel = new NumberPanel();
frame.getContentPane().add(numberPanel, BorderLayout.CENTER);
frame.pack();
EDIT
As leonidas mentioned it is also possible to revalidate the frame. This requires only to replace the upper call to pack by theese.
frame.invalidate();
frame.validate();

Java GUI is launching but nothing appears, no errors in stack trace

I'm trying to play around with ActionListeners and inner classes through a simple GUI where a user will press a button which will cause a message to be displayed.
My code compiles - however, upon launch, the icon will appear in my tray (OSX), but then immediate terminate. No errors appear in my console.
Here is my code:
import javax.swing.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
public class GUI {
private JFrame myFrame;
private JPanel messagePanel;
private JPanel buttonPanel;
private JLabel myMessage;
public GUI() {
myFrame = new JFrame("My GUI");
messagePanel = new JPanel();
buttonPanel = new JPanel();
myMessage = new JLabel();
myFrame.setLayout(new BorderLayout());
myFrame.setSize(500, 500);
myFrame.add(messagePanel, BorderLayout.SOUTH);
myFrame.add(buttonPanel, BorderLayout.CENTER);
messagePanel.add(myMessage);
addButtons();
}
public void addButtons() {
JButton button1 = new JButton(new ImageIcon("circle.png"));
buttonPanel.add(button1);
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
myMessage.setText("Button pressed!");
}
});
}
public static void main(String[] args) {
GUI myGUI = new GUI();
}
}
What's going on here?
You need to make the JFrame, myFrame, visible via myFrame.setVisible(true);
Also, you should not run any Swing GUI related code outside the Event Dispatch Thread (EDT). The correct way to start your program would be:
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
GUI myGUI = new GUI();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
After addButtons() in your constructor, add the following statement:
myFrame.setVisible(true);

How to add JPanel by clicking JButton?

I'm trying to create a small GUI, it has 2 JButtons, and 2 JPanels with some drawing animation on each of them. By default it must show first JPanel, and by clicking on second JButton I want to see my second JPanel. So : I create JFrame, Panel1 and Panel2, where I have drawn my animations, create Button1 and Button2 and adding to them ActionListeners. I have also MainPanel which has in a fields variable i. By changing this "i" my constructor adds to MainPanel either Panel1 (default) or Panel2 (by clicking on JButton2 I change i). Than I add this MainPanel to my frame. So my question : in the class MainPanel I have refreshMe method, what should I write there to make my GUI working properly? Thanks. Here is my code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GuiTest {
public static void main(String[] args) {
JFrame f = new JFrame();
MainPanel myPanel = new MainPanel();
f.add(myPanel);
Button1 button1 = new Button1();
Button2 button2 = new Button2();
myPanel.add(button1);
myPanel.add(button2);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
}
class MainPanel extends JPanel {
Panel1 p1 = new Panel1();
Panel2 p2 = new Panel2();
public int i = 1; //this is being changed later by clicking JButton
// I use this setter later in actionPerformed in order to change i
public void setI(int i) {
this.i = i;
}
MainPanel() {
if (i == 1) {
this.add(p1);
}
if (i == 2) {
this.add(p2);
}
}
public void refreshMe() {
// Need some help here:
// I don't know what should I write, how to make a repaint of myPanel?
System.out.println("just test, if the method refreshMe working by clicking some button");
}
}
class Panel1 extends JPanel {
public Panel1() {
this.setBackground(Color.BLUE);
// a lot of drawing stuff going on here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
class Panel2 extends JPanel {
public Panel2() {
this.setBackground(Color.GREEN);
// a lot of drawing stuff going on here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
class Button1 extends JButton {
MainPanel someObj1 = new MainPanel();
Button1() {
setText("Show Annimation A");
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
someObj1.setI(1);
System.out.println("The variable i is now: " + someObj1.i);
someObj1.refreshMe();
}
});
}
}
class Button2 extends JButton {
MainPanel someObj2 = new MainPanel();
Button2() {
setText("Show Annimation B");
addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
someObj2.setI(2);
System.out.println("The variable i is now: " + someObj2.i);
someObj2.refreshMe();
}
});
}
}
In order to reflect changes after adding/removing or resizing a component that is on a visible container call revalidate() and repaint() on the containers instance after adding/removing or resizing the component.
Though this will not work in your code the main reason being inside JButton classes you recreate a new instance of MainPanel when in fact the 2 JButtons should share the single instance which is being used (you could pass MainPanel instance to the JButtons constructors, but you shouldn't really be extending a JButton unless adding custom functionality):
class Button2 extends JButton {
MainPanel someObj2 = new MainPanel();//you create an instance of MainPanel which isnt even showing and than do changes on that, this way you will never see any of the changes
Button2() {
}
}
A few other suggestions on your code:
Dont extend JButton class unnecessarily, simply create an instance of JButton like you did with JFrame and call methods on JButton instance.
Dont forget to create/manipulate Swing components on Event Dispatch Thread, via SwingUtilities.invokeLater(..) block, read here for more.
Here is your code fixed (above suggestions ect implemented):
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
final MainPanel myPanel = new MainPanel();
f.add(myPanel);
JButton button1 = new JButton("Show Animation A");
JButton button2 = new JButton("Show Animation B");
button1.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myPanel.setI(1);
System.out.println("The variable i is now: " + myPanel.i);
myPanel.refreshMe();
}
});
button2.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
myPanel.setI(2);
System.out.println("The variable i is now: " + myPanel.i);
myPanel.refreshMe();
}
});
myPanel.add(button1);
myPanel.add(button2);
myPanel.checkPanel();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
});
}
}
class MainPanel extends JPanel {
Panel1 p1 = new Panel1();
Panel2 p2 = new Panel2();
public int i = 1; //this is being changed later by clicking JButton
// I use this setter later in actionPerformed in order to change i
public void setI(int i) {
this.i = i;
}
public void refreshMe() {
checkPanel();
revalidate();
repaint();
// Need some help here:
// I don't know what should I write, how to make a repaint of myPanel?
System.out.println("just test, if the method refreshMe working by clicking some button");
}
public void checkPanel() {
if (i == 1) {
this.add(p1);
this.remove(p2);//or it will remain there as this is default flowlayout
} else if (i == 2) {
this.add(p2);
this.remove(p1);
}
}
}
class Panel1 extends JPanel {
public Panel1() {
this.setBackground(Color.BLUE);
// a lot of drawing stuff going on here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
class Panel2 extends JPanel {
public Panel2() {
this.setBackground(Color.GREEN);
// a lot of drawing stuff going on here
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
However Id suggest something simpler, fortunately you have 2 choices:
1) Use CardLayout which will allow you to flip between multiple components on a single JFrame/container.
Here is an example I made:
import java.awt.BorderLayout;
import java.awt.CardLayout;
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.SwingUtilities;
public class Test {
private final static String PANEL1 = "panel 1";
private final static String PANEL2 = "panel 2";
public Test() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
private void initComponents() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel1 = new JPanel();
panel1.add(new JLabel("Panel 1"));
JPanel panel2 = new JPanel();
panel2.add(new JLabel("Panel 2"));
//Create the panel that contains the "cards".
final JPanel cards = new JPanel(new CardLayout());
cards.add(panel1, PANEL1);
cards.add(panel2, PANEL2);
//create button to allow chnage to next card
JButton buttonNext = new JButton(">");
buttonNext.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
CardLayout cl = (CardLayout) (cards.getLayout());//get cards
cl.next(cards);
}
});
//create button to allow chnage to previous card
JButton buttonPrev = new JButton("<");
buttonPrev.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
CardLayout cl = (CardLayout) (cards.getLayout());//get cards
cl.previous(cards);
}
});
//create panel to hold buttons which will allow switching between cards
JPanel buttonPanel = new JPanel();
buttonPanel.add(buttonPrev);
buttonPanel.add(buttonNext);
frame.add(cards);
frame.add(buttonPanel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
}
}
2) Use removeAll() technique i.e call frame.getContentPane().removeAll() which will remove all components currently on JFrame and than add the new content and call revalidate() and repaint() (also might want to add pack() in there) on JFrame instance to reflect changes. Though Id recommend CardLayout.
I think you can just use CardLayout to implement your function. Please refer to here

FocusListener behavior

I have a JFrame that I want closed when the user clicks off of it. I have two JTextFields and a JButton (username, password, submit). When I give them all the FocusListener, anytime the user goes from one field to another the window closes. How can I allow the user to go from field to field and only close it if the user clicks anywhere OUT of the pop up window?
public class LoginForm {
static JTextField userName;
static JTextField password;
static JButton submit;
JFrame main;
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
UserSession session;
public LoginForm(){
Handler handle = new Handler(); //inner class
LoginFormFocusListener fl = new LoginFormFocusListener(); //inner class
main = new JFrame("Please Login");
main.setUndecorated(true);
main.setBounds((dim.width/2) - (500/2),(dim.height/2) - (150/2),500,150);
main.setVisible(true);
main.setAlwaysOnTop(true);
main.setResizable(false);
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
userName = new JTextField(10);
password = new JTextField(10);
main.setLayout(new GridLayout(0,1));
JPanel panel = new JPanel();
main.add(panel);
panel.add(new JLabel("Username: "));
panel.add(userName);
panel.add(new JLabel("Password: "));
panel.add(password);
submit = new JButton("Submit");
panel.add(submit);
userName.addFocusListener(fl);
password.addFocusListener(fl);
submit.addFocusListener(fl);
submit.addActionListener(handle);
}
}
... (unimportant methods and "Handler" class omitted)
public class LoginFormFocusListener implements FocusListener{
public void focusGained(FocusEvent fe) {
System.out.println("focus gained...");
System.out.println("click off of this window to close...");
}
public void focusLost(FocusEvent fe){
System.out.println("focus lost...");
WindowEvent winEvt = new WindowEvent(main, 0);
winEvt.getWindow().dispose();
}
}
//test
public static void main(String args[]){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new LoginForm();
}
});
}
Don't use a FocusListener for this since these are for components that gain and lose the focus, not for top level windows. Perhaps use a WindowListener listening for the window is deactivated or iconified.
For example:
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class WindowListenerFun {
public static void main(String[] args) {
JPanel panel = new JPanel();
panel.add(new JTextField(10));
panel.add(new JButton("button"));
JFrame frame = new JFrame("Bad Frame");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowIconified(WindowEvent wEvt) {
((JFrame)wEvt.getSource()).dispose();
}
#Override
public void windowDeactivated(WindowEvent wEvt) {
((JFrame)wEvt.getSource()).dispose();
}
});
}
}
EDIT: I misread your code; the other answer is correct--you need to use a WindowFocusListener instead of a FocusListener.
public class Listener extends WindowAdapter
{
public void windowLostFocus(WindowEvent e)
{
Window w = e.getWindow();
e.setVisible(false);
e.dispose();
}
}
and
main.addWindowFocusListener(new Listener());
Edit2: replaced placeholder with window closing code.
Then you add a focus listener to individual menu components, it gets fired whenever a component loses focus. You only want it to get fired when the window loses focus, so add it to the window instead.
main.addWindowFocusListener(f1);
should fix your problem.

Categories

Resources