I have created three classes:
public class Gui extends JFrame {
private final JButton buttonClose = new JButton("Close");
private final MyButtonListener buttonListener = new MyButtonListener(this);
private final MyWindowListener windowListener = new MyWindowListener();
public SwitchGuiExtListeners() {
super("Switch");
setSize(200, 150);
setLayout(new BorderLayout());
add(buttonClose, BorderLayout.EAST);
buttonClose.addActionListener(this.buttonListener);
this.addWindowListener(this.windowListener);
setVisible(true);
}
public JButton getButtonClose() {
return buttonClose;
}
}
public class SwitchGuiWindowListener implements WindowListener{
...
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
...
}
public class MyButtonListener implements ActionListener {
private final Gui gui;
public MyButtonListener (final Gui gui) {
this.gui = gui;
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == gui.getButtonClose()){
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//System.exit(0);
}
}
}
If I use the gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); my frame doesn't close. But when I use the System.exit(0) it works. Why can't I use the setDefaultCloseOperation(..)?
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); does not close a JFrame. It simply tells that the JFrame must exit when the close button on top-right corner of a window is clicked i.e., just sets the behavior but does trigger an exit.
To close a JFrame, use something like this:
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
Source: https://stackoverflow.com/a/1235994/1866196
Related
I have two frames in separate classes (FrameOne and FrameTwo) FrameOne has two buttons. One to open FrameTwo and One shall close FrameTwo. How to open FrameTwo I know. But not how to close from Frame One. How do I code it to make it working? Thanks. (I know that there are similar questions. I red them all. But it didn't gave me the answer. Also GUI guides didn't helped.)
public class Main {
public static void main(String[] args) {
FrameOne frame = new FrameOne();
}
}
FrameOne class:
public class FrameOne extends JFrame implements ActionListener{
private JButton btn1, btn2;
FrameOne () {
setVisible(true);
setSize(400,400);
setLayout(new FlowLayout());
setTitle("Main");
setDefaultCloseOperation(EXIT_ON_CLOSE);
btn1 = new JButton("opens FrameTwo");
btn2 = new JButton("close FrameTwo");
btn1.addActionListener(this);
btn2.addActionListener(this);
add(btn1);
add(btn2);
}
#Override
public void actionPerformed (ActionEvent e) {
if(e.getSource()== btn1) {
FrameTow frameTwo = new FrameTwo();
}
else if(e.getSource()== btn2) ;
// {???.dispose(); }
}
}
`
Frame2 class:
public class FrameTow extends JFrame {
FrameTwo () {
setVisible(true);
setSize(400,400);
setTitle("FrameTwo");
setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLocation(400, 400);
}
}
Any of the below solutions will work
frameTwo.dispatchEvent(new WindowEvent(frameTwo, WindowEvent.WINDOW_CLOSING));
OR
frameTwo.setVisible(false);
The short answer is modify FrameOne :
private JFrame frameTwo; //introduce a field
#Override
public void actionPerformed (ActionEvent e) {
if(e.getSource()== btn1) {
frameTwo = new FrameTwo(); //use field in action listener
}
else if(e.getSource()== btn2){
frameTwo.dispose(); //use field in action listener
}
}
The longer answer: using a JDialog for the 2nd frame is a better practice:
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
public class Main {
public static void main(String[] args) {
new FrameOne();
}
}
class FrameOne extends JFrame implements ActionListener{
private final JButton btn1, btn2;
private JDialog frameTwo; //introduce a field
FrameOne () {
setSize(400,400);
setLayout(new FlowLayout());
setTitle("Main");
setDefaultCloseOperation(EXIT_ON_CLOSE);
btn1 = new JButton("opens FrameTwo");
btn2 = new JButton("close FrameTwo");
btn1.addActionListener(this);
btn2.addActionListener(this);
add(btn1);
add(btn2);
setVisible(true); //make it visible after construction is completed
}
#Override
public void actionPerformed (ActionEvent e) {
if(e.getSource()== btn1) {
frameTwo = new FrameTwo(); //use field in action listener
}
else if(e.getSource()== btn2){
frameTwo.dispose(); //use field in action listener
}
}
}
class FrameTwo extends JDialog {
FrameTwo() {
setSize(400,400);
setTitle("FrameTwo");
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
this.setLocation(400, 400);
setVisible(true); //make it visible after construction is completed
}
}
In the example you show, one can open several instances of FrameTwo. Which one should the second button close?
Assuming you want there to be only one, you could introduce a field in in FrameOne, initially set to null. btn1 would then only open a frame if the field is null, and assign it to the field. Then btn2 can call dispose() on the field (and reset it to null).
Example, based on your attempt:
public class FrameOne extends JFrame implements ActionListener {
private JButton btn1, btn2;
private FrameTwo frameTwo = null;
FrameOne () {
setVisible(true);
setSize(400,400);
setLayout(new FlowLayout());
setTitle("Main");
setDefaultCloseOperation(EXIT_ON_CLOSE);
btn1 = new JButton("opens FrameTwo");
btn2 = new JButton("close FrameTwo");
btn1.addActionListener(this);
btn2.addActionListener(this);
add(btn1);
add(btn2);
}
#Override
public void actionPerformed (ActionEvent e)
{if(e.getSource()== btn1)
{
if (frameTwo == null) {
frameTwo = new FrameTwo();
}
}
else if(e.getSource()== btn2) {
frameTwo.dispatchEvent(new WindowEvent(frameTwo, WindowEvent.WINDOW_CLOSING));
frameTwo = null;
}}}
I am learning Java with GUI using JFrame, I would like to seek help regarding on how to call an ActionListener using an ActionListener. Here is some of my codes. The bottom part has the two action listeners and I added a simple comment for easy understanding.
package onlinedelivery;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MainMenu extends JFrame {
public JButton mainMenuButton;
public JButton exitButton;
public MainMenuButtonHandler mmHandler;
public ExitButtonHandler exHandler;
public static final int width = 400;
public static final int heigth = 300;
public MainMenu() {
Font bigFont = new Font("Arial",Font.BOLD,12);
mainMenuButton = new JButton("Main Menu");
mmHandler = new MainMenuButtonHandler();
mainMenuButton.addActionListener(mmHandler);
exitButton = new JButton("Exit");
exHandler = new ExitButtonHandler();
exitButton.addActionListener(exHandler);
setTitle("Main Menu");
Container pane = getContentPane();
pane.setLayout(new GridLayout(5,2));
pane.add(mainMenuButton);
setSize(WIDTH,HEIGHT);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public class MainMenuButtonHandler implements ActionListener {
#Override public void actionPerformed(ActionEvent e) {
// ExitButtonHandler should be called here
// When I click Main Menu Button Handler, ExitButtonHandler shall perform
}
}
public class ExitButtonHandler implements ActionListener {
#Override public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
}
If both Actions logic is the same you can define just one and use it for both menu and button.
If not you can extend one action from another
public class MainMenuButtonHandler extends ExitButtonHandler {
#Override public void actionPerformed(ActionEvent e) {
// An additional logic here
super.actionPerformed(e);
}
}
You can use the doClick() method in JButton (inherited from AbstractButton)
With that alter the Handler Class of MainMenuButton like this:
public class MainMenuButtonHandler implements ActionListener {
private JButton exitButton;
public void setExitButton(JButton exitButton){
this.exitButton = exitButton;
}
#Override public void actionPerformed(ActionEvent e) {
//Do your work and invoke Click of exitButton
this.exitButton.doClick();
}
}
Also the MainMenu():
exitButton = new JButton("Exit");
exHandler = new ExitButtonHandler();
exitButton.addActionListener(exHandler);
mainMenuButton = new JButton("Main Menu");
mmHandler = new MainMenuButtonHandler();
mmHandler.setExitButton(exitButton) // newly added
mainMenuButton.addActionListener(mmHandler);
I am trying to set a new text into a button when you press on it. However it does not seem to work, I am doing something wrong, and I do not know what...
EDIT -----I attach the code for easier comprehension of what I mean
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GrowAndShrinkSquareGUItest {
JFrame frame;
SquareDrawPanel bigGreen;
SquareDrawPanel smallGreen;
JButton button;
growAndShrinkListener listener;
public class SquareDrawPanel extends JPanel {
int width;
int height;
SquareDrawPanel(int w, int h) {
width = w;
height = h;
}
public void paintComponent(Graphics g) {
g.setColor(Color.green);
g.fillRect(frame.getWidth() / 2 - (width / 2), frame.getHeight()
/ 2 - (height / 2) - 15, width, height);
}
}
public class growAndShrinkListener implements ActionListener {
// JButton button;
growAndShrinkListener(JButton button) {
button = new JButton("Click me to grow the Square");
frame.add(button, BorderLayout.NORTH);
button.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
button.setText("Unselect all");
}
}
public static void main(String[] args) {
GrowAndShrinkSquareGUItest test = new GrowAndShrinkSquareGUItest();
test.go();
}
private void createPanels() {
bigGreen = new SquareDrawPanel(400, 400);
smallGreen = new SquareDrawPanel(100, 100);
}
private void drawPanel(JPanel panel) {
frame.add(panel);
panel.setVisible(true);
frame.add(panel, BorderLayout.CENTER);
}
private void createListenerButton() {
listener = new growAndShrinkListener(button);
}
private void loop(){}
public void go() {
frame = new JFrame();
frame.setSize(500, 500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
createPanels();
drawPanel(smallGreen);
createListenerButton();
frame.setVisible(true);
}
}
It is because you use the button variable that is not defined in the scope of actionPerformed method. Java variables have scope and they are available inside curly braces where they're defined. The actionPerformed method is out of the curly braces of growAndShrinkListener method. The fixed code:
public class growAndShrinkListener implements ActionListener {
growAndShrinkListener(JButton button) {
button = new JButton("Click me to grow the Square");
frame.add(button, BorderLayout.NORTH);
button.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if(source instanceof JButton) {
button = (JButton) source;
button.setText("Click to shrink square");
}
}
}
Alternatively, you can use a private variable:
public class growAndShrinkListener implements ActionListener {
private JButton button;
growAndShrinkListener() {
button = new JButton("Click me to grow the Square");
frame.add(button, BorderLayout.NORTH);
button.addActionListener(this);
}
#Override
public void actionPerformed(ActionEvent e) {
button.setText("Click to shrink square");
}
}
Note: You should not overwrite the content of the argument in the constructor. The argument that you got is not a "pointer" to the callee's variable, but just a simple reference to that. If you overwrite, then the content will be lost for you and calle will not know that.
change like this..
public class YourSuperClass{
private JButton button;
public YourSuperClass(){
// your logics
button = new JButton();
button.addActionListener(new GrowAndShrinkListener(button));
frame.add(button, BorderLayout.NORTH);
}
class GrowAndShrinkListener implements ActionListener {
GrowAndShrinkListener(JButton button) {
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == button){
button.setText("Click to shrink square");
}
}
}
}
Try This :
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class frame extends JFrame
{
JButton b;
public frame()
{
setLayout(new BorderLayout());
b=new JButton("Press");
add(b,BorderLayout.SOUTH);
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
b.setText("Clicked");
}
});
}
public static void main (String[] args) {
frame f=new frame();
f.setExtendedState(MAXIMIZED_BOTH);
f.setVisible(true);
}
}
I'm using webcam-capture libraries and AWT to develop a simple interface for taking pictures from a webcam. The buttons and the combobox in my JFrame disappear after minimizing the window or after moving another window on top of it. Moving the pointer over the frame restores the components' visibility. I'm not skilled with Java UI, I can't figure out what's wrong with my code.
#SuppressWarnings("serial")
public class ImageCaptureManager extends JFrame {
private class SkipCapture extends AbstractAction {
public SkipCapture() {
super(“Skip”);
}
#Override
public void actionPerformed(ActionEvent e) {
/*SOME CODE HERE*/
}
}
private class SnapMeAction extends AbstractAction {
public SnapMeAction() {
super(“Snap”);
}
#Override
public void actionPerformed(ActionEvent e) {
/*SOME CODE HERE*/
}
}
private class captureCompleted extends AbstractAction {
public captureCompleted() {
super(“Completed”);
}
#Override
public void actionPerformed(ActionEvent e) {
/*SOME CODE HERE*/
}
}
private class saveImage extends AbstractAction {
public saveImage() {
super(“Save”);
}
#Override
public void actionPerformed(ActionEvent e) {
/*SOME CODE HERE*/
}
}
private class deleteImage extends AbstractAction {
public deleteImage() {
super(“Delete”);
}
#Override
public void actionPerformed(ActionEvent e) {
/*SOME CODE HERE*/
}
}
private class StartAction extends AbstractAction implements Runnable {
public StartAction() {
super(“Start”);
}
#Override
public void actionPerformed(ActionEvent e) {
btStart.setEnabled(false);
btSnapMe.setEnabled(true);
executor.execute(this);
}
#Override
public void run() {
panel.start();
}
}
private Executor executor = Executors.newSingleThreadExecutor();
private Dimension captureSize = new Dimension(640, 480);
private Dimension displaySize = new Dimension(640, 480);
private Webcam webcam = Webcam.getDefault();
private WebcamPanel panel;
private JButton btSnapMe = new JButton(new SnapMeAction());
private JButton btStart = new JButton(new StartAction());
private JButton btComplete = new JButton(new captureCompleted());
private JButton btSave = new JButton(new saveImage());
private JButton btDelete = new JButton(new deleteImage());
private JButton btSkip = new JButton(new SkipCapture());
private JComboBox comboBox = new JComboBox();
public ImageCaptureManager() {
super(“Frame”);
this.addWindowListener( new WindowAdapter()
{
#Override
public void windowDeiconified(WindowEvent arg0) {
}
public void windowClosing(WindowEvent e)
{
}
});
List<Webcam> webcams = Webcam.getWebcams();
for (Webcam webcam : webcams) {
System.out.println(webcam.getName());
if (webcam.getName().startsWith("USB2.0 Camera 1")) {
this.webcam = webcam;
break;
}
}
panel = new WebcamPanel(webcam, displaySize, false);
webcam.setViewSize(captureSize);
panel.setFPSDisplayed(true);
panel.setFillArea(true);
btSnapMe.setEnabled(false);
btSave.setEnabled(false);
btDelete.setEnabled(false);
setLayout(new FlowLayout());
Panel buttonPanel = new Panel();
buttonPanel.setLayout(new GridLayout(10, 1));
buttonPanel.add(Box.createHorizontalStrut(20));
buttonPanel.add(btSnapMe);
buttonPanel.add(Box.createHorizontalStrut(20));
buttonPanel.add(btSave);
buttonPanel.add(Box.createHorizontalStrut(20));
buttonPanel.add(btDelete);
buttonPanel.add(Box.createHorizontalStrut(20));
buttonPanel.add(btComplete);
buttonPanel.add(Box.createHorizontalStrut(20));
buttonPanel.add(btSkip);
JLabel label1 = new JLabel("Test");
label1.setText(“Bla bla bla”);
JLabel label2 = new JLabel("Test");
label2.setText(" ");
Panel captionAndWebcamPanel = new Panel();
captionAndWebcamPanel.add(label1);
captionAndWebcamPanel.add(label2);
captionAndWebcamPanel.add(panel);
captionAndWebcamPanel.add(label2);
captionAndWebcamPanel.add(comboBox);
captionAndWebcamPanel.setLayout(new BoxLayout(captionAndWebcamPanel, BoxLayout.Y_AXIS));
add(captionAndWebcamPanel);
add(buttonPanel);
pack();
setVisible(true);
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
btStart.doClick();
setSize(900,600);
}
}
You are mixing AWT and Swing components.
"Historically, in the Java language, mixing heavyweight and lightweight components in the same container has been problematic."
http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html
I suggest you try using JPanels instead of Panels for captionAndWebcamPanel and buttonPanel, I'd also set layout to captionAndWebcamPanel before adding components.
I have a button in a java frame that when pressed it reads a value from a text field and uses that string as a port name attempting to connect to a serial device.
If this connection is successful the method returns true if not it returns false. If it returns true I want the frame to disappear. A series of other frames specifed in other classes will then appear with options to control the serial device.
My problem is: the button is connected to an action listener, when pressed this method is invoked. If I try to use the frame.setVisible(true); method java throws a abstract button error because I'm effectively telling it to disappear the frame containing the button before the button press method has exited. Removing the frame.setVisible(true); allow the program to run correctly however I am left with a lingering connection frame that is no longer any use.
How to I get the frame to disappear upon pressing a the button?
package newimplementation1;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
*
* #author Zac
*/
public class ConnectionFrame extends JPanel implements ActionListener {
private JTextField textField;
private JFrame frame;
private JButton connectButton;
private final static String newline = "\n";
public ConnectionFrame(){
super(new GridBagLayout());
textField = new JTextField(14);
textField.addActionListener(this);
textField.setText("/dev/ttyUSB0");
connectButton = new JButton("Connect");
//Add Components to this panel.
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
add(connectButton, c);
connectButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
boolean success = Main.mySerialTest.initialize(textField.getText());
if (success == false) {System.out.println("Could not connect"); return;}
frame.setVisible(false); // THIS DOES NOT WORK!!
JTextInputArea myInputArea = new JTextInputArea();
myInputArea.createAndShowGUI();
System.out.println("Connected");
}
});
}
public void actionPerformed(ActionEvent evt) {
// Unimplemented required for JPanel
}
public void createAndShowGUI() {
//Create and set up the window.
frame = new JFrame("Serial Port Query");
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
//Add contents to the window.
frame.add(new ConnectionFrame());
frame.setLocation(300, 0);
//Display the window.
frame.pack();
frame.setVisible(true);
frame.addComponentListener(new ComponentAdapter() {
#Override
public void componentHidden(ComponentEvent e) {
System.out.println("Exiting Gracefully");
Main.mySerialTest.close();
((JFrame)(e.getComponent())).dispose();
System.exit(0);
}
});
}
}
Running your snippet (after removing/tweaking around the custom classes), throws an NPE. Reason is that the frame you'r accessing is null. And that's because it's never set. Better not rely on any field, let the button find its toplevel ancestor and hide that, like in
public void actionPerformed(final ActionEvent e) {
boolean success = true;
if (success == false) {
System.out.println("Could not connect");
return;
}
Window frame = SwingUtilities.windowForComponent((Component) e
.getSource());
frame.setVisible(false); //no problem :-)
}
Your problem is with this line:
frame.add(new ConnectionFrame());
You're creating a new ConnectionFrame object, and so the frame that your button tries to close on is not the same as the one being displayed, and this is the source of your problem.
If you change it to,
//!! frame.add(new ConnectionFrame());
frame.add(this);
so that the two JFrames are one and the same, things may work more smoothly.
But having said that, your whole design smells bad and I'd rethink it in a more OOP and less static fashion. Also, use dialogs where dialogs are needed, not frames, and rather than dialogs consider swapping views (JPanels) via CardLayout as a better option still.
Myself, I'd create a "dumb" GUI for this, one that creates a JPanel (here in my example it extends a JPanel for simplicity, but I'd avoid extending if not necessary), and I'd let whoever is calling this code decide what to do with the information via some control. For e.g.,
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class ConnectionPanel extends JPanel {
private JTextField textField;
private JButton connectButton;
private ConnectionPanelControl control;
public ConnectionPanel(final ConnectionPanelControl control) {
super(new GridBagLayout());
this.control = control;
ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (control != null) {
control.connectButtonAction();
}
}
};
textField = new JTextField(14);
textField.addActionListener(listener);
textField.setText("/dev/ttyUSB0");
connectButton = new JButton("Connect");
GridBagConstraints c = new GridBagConstraints();
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
add(textField, c);
c.fill = GridBagConstraints.BOTH;
c.weightx = 1.0;
c.weighty = 1.0;
add(connectButton, c);
connectButton.addActionListener(listener);
}
public String getFieldText() {
return textField.getText();
}
}
Again, something outside of the simple GUI would make decisions on what to do with the text that the textfield contains and what to do with the GUI that is displaying this JPanel:
public interface ConnectionPanelControl {
void connectButtonAction();
}
Also, you will likely do any connecting in a background thread so as to not freeze your GUI, probably a SwingWorker. Perhaps something like this:
import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyMain extends JPanel {
public MyMain() {
add(new JButton(new ConnectionAction("Connect", this)));
}
private static void createAndShowGui() {
JFrame frame = new JFrame("My Main");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new MyMain());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class ConnectionAction extends AbstractAction {
private MyMain myMain;
private ConnectionPanel cPanel = null;
private JDialog dialog = null;
public ConnectionAction(String title, MyMain myMain) {
super(title);
this.myMain = myMain;
}
#Override
public void actionPerformed(ActionEvent e) {
if (dialog == null) {
dialog = new JDialog(SwingUtilities.getWindowAncestor(myMain));
dialog.setTitle("Connect");
dialog.setModal(true);
cPanel = new ConnectionPanel(new ConnectionPanelControl() {
#Override
public void connectButtonAction() {
final String connectStr = cPanel.getFieldText();
new MySwingWorker(connectStr).execute();
}
});
dialog.getContentPane().add(cPanel);
dialog.pack();
dialog.setLocationRelativeTo(null);
}
dialog.setVisible(true);
}
private class MySwingWorker extends SwingWorker<Boolean, Void> {
private String connectStr = "";
public MySwingWorker(String connectStr) {
this.connectStr = connectStr;
}
#Override
protected Boolean doInBackground() throws Exception {
// TODO: make connection and then return a result
// right now making true if any text in the field
if (!connectStr.isEmpty()) {
return true;
}
return false;
}
#Override
protected void done() {
try {
boolean result = get();
if (result) {
System.out.println("connection successful");
dialog.dispose();
} else {
System.out.println("connection not successful");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
Your code would be much more readable if you named JFrame instances xxxFrame, and JPanel instances xxxPanel. Naming JPanel instances xxxFrame makes things very confusing.
It would also help if you pasted the stack trace of the exception.
I suspect the problem comes from the fact that frame is null. This is due to the fact that the frame field is only initialized in the createAndShowGUI method, but this method doesn't display the current connection panel, but a new one, which thus have a null frame field:
ConnectionFrame firstPanel = new ConnectionFrame();
// The firstPanel's frame field is null
firstPanel.createAndShowGUI();
// the firstPanel's frame field is now not null, but
// the above call opens a JFrame containing another, new ConnectionFrame,
// which has a null frame field
The code of createAndShowGUI should contain
frame.add(this);
rather than
frame.add(new ConnectionFrame());
for Swing GUI is better create only once JFrame and another Top-Level Containers would be JDialog or JWindow(un-decorated by default),
simple example here
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SuperConstructor extends JFrame {
private static final long serialVersionUID = 1L;
public SuperConstructor() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(300, 300));
setTitle("Super constructor");
Container cp = getContentPane();
JButton b = new JButton("Show dialog");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
FirstDialog firstDialog = new FirstDialog(SuperConstructor.this);
}
});
cp.add(b, BorderLayout.SOUTH);
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
System.exit(0);
}
});
add(bClose, BorderLayout.NORTH);
pack();
setVisible(true);
}
public static void main(String args[]) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
SuperConstructor superConstructor = new SuperConstructor();
}
});
}
private class FirstDialog extends JDialog {
private static final long serialVersionUID = 1L;
FirstDialog(final Frame parent) {
super(parent, "FirstDialog");
setPreferredSize(new Dimension(200, 200));
setLocationRelativeTo(parent);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setModalityType(Dialog.ModalityType.DOCUMENT_MODAL);
JButton bNext = new JButton("Show next dialog");
bNext.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
SecondDialog secondDialog = new SecondDialog(parent, false);
}
});
add(bNext, BorderLayout.NORTH);
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
setVisible(false);
}
});
add(bClose, BorderLayout.SOUTH);
pack();
setVisible(true);
}
}
private int i;
private class SecondDialog extends JDialog {
private static final long serialVersionUID = 1L;
SecondDialog(final Frame parent, boolean modal) {
//super(parent); // Makes this dialog unfocusable as long as FirstDialog is visible
setPreferredSize(new Dimension(200, 200));
setLocation(300, 50);
setModal(modal);
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
setTitle("SecondDialog " + (i++));
JButton bClose = new JButton("Close");
bClose.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
setVisible(false);
}
});
add(bClose, BorderLayout.SOUTH);
pack();
setVisible(true);
}
}
}
better would be re-use Top-Level Containers, as create lots of Top-Level Containers on Runtime (possible memory lack)