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();
}
}
Related
Okay I can get text fields and normal text and even images to show but I can not get a button to show. I am not sure what I am doing wrong because I have done the same steps for the rest. Any help would be great thanks!
package EventHandling2;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import EventHandling.GUITest;
public class EventMain extends JFrame{
private JLabel label;
private JButton button;
public static void main(String[] args) {
EventMain gui = new EventMain ();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // when click x close program
//gui.setSize(600, 300);
gui.setVisible(true);
gui.setTitle("Button Test");
}
public void EventMain(){
setLayout(new FlowLayout());
button = new JButton ("click for text");
add(button);
label = new JLabel ("");
add(label);
Events e = new Events();
button.addActionListener(e);
}
public class Events implements ActionListener {
public void actionPerformed(ActionEvent e) {
label.setText("Now you can see words");
}
}
}
The problem is with the method: void EventMain()
Constructor has NO return type. Just remove "void". The code will work just fine.
Your actionListener(e) contains a minor control structure error:
public void actionPerformed(ActionEvent e) {
label.setText("Now you can see words");
}
Change to:
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button) {
label.setText("Now you can see words");
}
}
First off, you have to remove void keyword in EventMain's constructor. Then, creating JPanel and add components into it, then add the JPanel to the JFrame.contentPane.
The following code should work:
public class EventMain extends JFrame {
private final JLabel label;
private final JButton button;
public static void main(String[] args) {
EventMain gui = new EventMain();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // when click x
// close program
gui.setSize(600, 300);
gui.setTitle("Button Test");
gui.setVisible(true);
}
public EventMain() {
// setLayout(new FlowLayout());
JPanel panel = new JPanel(new FlowLayout());
button = new JButton("click for text");
panel.add(button);
label = new JLabel("");
panel.add(label);
Events e = new Events();
button.addActionListener(e);
this.getContentPane().add(panel);
}
public class Events implements ActionListener {
public void actionPerformed(ActionEvent e) {
label.setText("Now you can see words");
}
}
}
I'm writing a program in Java where I'm using JTabbedPane. Each tab is associated with a different panel with labels, textfields and a button. I have used GridBagLayout in the panels.
I have added an actionlistener to the button, but when I click it nothing happens.
EDIT: I also have other buttons outside the JTabbedPane which works perfectly fine.
I can see that nothing is happening because I do this:
public void actionPerformed( ActionEvent e ) {
if ( e.getSource() == button ) {
System.out.println("blablabla");
}
and nothing is printed out.
Is there any common problems with using buttons and GridBagLayout/JTabbedPane?
EDIT with SSCCE
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.*;
public class Hjelp extends JFrame {
private FlowLayout layout;
private JButton button1;
private JButton button2;
private JPanel menu, frontpage;
private JPanel present, previous, something;
public Hjelp() {
layout = new FlowLayout(FlowLayout.CENTER, 10, 20);
setLayout(layout);
setSize(900, 900);
setLocationRelativeTo(null);
setVisible(true);
setPanels();
something = something();
add(something, BorderLayout.CENTER);
something.setVisible(false);
button1 = new JButton("CLICK ME");
add(button1);
buttonListener();
}
private void buttonListener() {
Buttonlistener listener = new Buttonlistener();
button1.addActionListener(listener);
button2.addActionListener(listener);
}
private void setPanels() {
menu = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 0));
frontpage = new JPanel();
previous = frontpage;
present = frontpage;
add(menu);
}
public void visiblePanel() {
previous.setVisible(false);
present.setVisible(true);
}
private JPanel something() {
visiblePanel();
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1, 1));
JTabbedPane tabbedPane = new JTabbedPane();
JComponent panel1 = tab();
tabbedPane.addTab("Click me", panel1);
tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
panel.add(tabbedPane);
return panel;
}
private JComponent tab() {
JPanel panel = new JPanel(false);
panel.setPreferredSize(new Dimension(870, 300));
panel.setLayout(new GridBagLayout());
GridBagConstraints cs = new GridBagConstraints();
cs.fill = GridBagConstraints.HORIZONTAL;
button2 = new JButton("Click me");
cs.gridx = 1;
cs.gridy = 6;
cs.gridwidth = 1;
panel.add(button2, cs);
return panel;
}
private class Buttonlistener implements ActionListener {
#Override
public void actionPerformed( ActionEvent e ) {
if ( e.getSource() == button1 ) {
present = something;
button1.setVisible(false);
something();
previous = something;
}
else if (e.getSource() == button2) {
System.out.println("Blablabla");
}
}
}
public static void main(String [] args) {
final Hjelp vindu = new Hjelp();
vindu.addWindowListener(
new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
} );
}
}
SOLVED
Solution
You don't need the getSource check at all—your listener is (hopefully) attached to just one button, so if it was invoked, that already means the button was clicked. Remove the check and unconditionally print your string. If you still don't see anything, then you have a problem.
You may not have attached a handler to the actual button, and therefore the event will never get called.
Part 1:
ButtonHandler handler = new ButtonHandler();
button.addActionListener( handler );
Part 2:
public class ButtonHandler implements ActionListener
{
#Override
public void actionPerformed(ActionEvent event) {
}
}
ALSO: Java GUI can be finicky, rather than using "e.getSource() == button" you could try "button..isFocusOwner()"
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
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.
What am I missing here?
public class abc extends JFrame {
private JButton save = new JButton("Save");
public abc() {
JPanel p = new JPanel();
save.addActionListener(new SaveL());
p.add(save);
Container cp = getContentPane();
p = new JPanel();
p.setLayout(new GridLayout(2, 1));
cp.add(p, BorderLayout.NORTH);
}
}
class SaveL implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("Hello"); // nothing happens
}
}
Why doesn't my ActionListener work here
You are creating a JPanel, adding your JButton to it, then creating a new JPanel and adding that panel to your JFrame. You need to be adding the original panel to your content pane.
Your code is completely messed up. You instantiate your JPanel p twice, your button is declared "open" but is actually "save". You mix GridLayout with BorderLayour constraints. The following code works:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class abc extends JFrame {
private JButton save = new JButton("Save");
public abc() {
JPanel p = new JPanel();
save.addActionListener(new SaveL());
p.add(save);
p.setLayout(new GridLayout(2, 1));
add(p);
}
public static void main(String[] args) {
abc abc = new abc();
abc.pack();
abc.setVisible(true);
}
}
class SaveL implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Hello"); // nothing happens
}
}
Your code is re-creating the panel. It's losing the button.
I changed it to:
public class abc extends JFrame{
private JButton save = new JButton("Save");
public abc() {
JPanel p = new JPanel();
save.addActionListener(new SaveL());
p.add(save);
Container cp = getContentPane();
cp.add(p, BorderLayout.NORTH);
}
}
class SaveL implements ActionListener {
public void actionPerformed(ActionEvent e) {
System.out.println("Hello"); // nothing happens
}
}
and it worked
private JButton open = new JButton("Save");
save.addActionListener(new SaveL());
Did u declare your save as open?