Open a JPAnel After Pressing a Button in a Jframe

Open a JPanel after pressing a button in a JFrame

Let's start with, you should avoid, wherever possible, extending directly from a top level container, like JFrame. This ties you down to a single use component, you couldn't, for example, re-use the login controls in another window (as part of a large component hierarchy) or within an applet context. You're also not adding any new functionality to the class itself.

You should also limit the number of windows you are push onto your user, as it can become confusing quickly. Take a look at The Use of Multiple JFrames, Good/Bad Practice? for more details.

Instead, you should consider using a MVC (Model-View-Controller) design to reduce the amount of coupling between classes and exposure of your components to unwarrented/undesirable modifications.

Contract (view)

Lets start by defining the contracts, this defines what each element in the process can and is expected to do and the information which is passed around

View

This defines the core functionality of each view in your application. Each view can have a controller (as defined by C) and is expected to provide a JComponent as the base representation, which is used to physically add the view to the Container

public interface View<C> {

public JComponent getView();
public void setController(C controller);
public C getController();

}

LoginView

This defines what information the login view is expected to provide, in this example, we provide the username and password information as well as a means by which the controller can tell the view that the login attempt failed. This allows the view to reset the view and display an error message if required

public interface LoginView extends View<LoginController> {

public String getUserName();
public char[] getPassword();

public void loginFailed(String errorMessage);

}

LoginController

This defines the expected actions a controller for the login view can expected to occur, this are called by the view to tell the controller it should do something...

public interface LoginController {

public void performLogin(LoginView view);
public void loginCanceled(LoginView view);

}

ApplicationView

I've not provided an example of this, but you can imagine that you'd need to provide the details you might like to provide for interested parties to extract details from the view.

Implementation

LoginPane

This is the basic LoginView implementation...

public class LoginPane extends JPanel implements LoginView {

private JTextField userName;
private JPasswordField password;
private JButton okButton;
private JButton cancelButton;
private LoginController controller;

public LoginPane() {
setLayout(new GridBagLayout());
userName = new JTextField(10);
password = new JPasswordField(10);
okButton = new JButton("Ok");
cancelButton = new JButton("Cancel");

GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.insets = new Insets(2, 2, 2, 2);
gbc.anchor = GridBagConstraints.WEST;

add(new JLabel("User name: "), gbc);
gbc.gridy++;
add(new JLabel("Password: "), gbc);

gbc.gridx = 1;
gbc.gridy = 0;
gbc.gridwidth = 2;
add(userName, gbc);
gbc.gridy++;
add(password, gbc);

gbc.gridwidth = 1;
gbc.gridy++;
add(okButton, gbc);
gbc.gridx++;
add(cancelButton, gbc);

okButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getController().performLogin(LoginPane.this);
}
});

cancelButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
getController().loginCanceled(LoginPane.this);
}
});
}

@Override
public String getUserName() {
return userName.getText();
}

@Override
public char[] getPassword() {
return password.getPassword();
}

@Override
public void loginFailed(String errorMessage) {
JOptionPane.showMessageDialog(this, errorMessage, "Login failed", JOptionPane.ERROR_MESSAGE);
}

@Override
public void setController(LoginController controller) {
this.controller = controller;
}

@Override
public JComponent getView() {
return this;
}

@Override
public LoginController getController() {
return controller;
}

}

ApplicationPane

The basic application View

public class ApplicationPane extends JPanel implements View {

public ApplicationPane() {
setLayout(new GridBagLayout());
add(new JLabel("Welcome to my awesome application"));
}

@Override
public JComponent getView() {
return this;
}

@Override
public void setController(Object controller) {
// What ever controller you want to use...
}

@Override
public Object getController() {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}

}

Putting it all together...

We'll, that's a lot of info, but how do you use it?

public class CoreApplicationCPane extends JPanel {

protected static final String LOGIN_VIEW = "View.login";
protected static final String APPLICATION_VIEW = "View.application";

private LoginView loginView;
private ApplicationPane applicationView;
private CardLayout cardLayout;

public CoreApplicationCPane() {

cardLayout = new CardLayout();
setLayout(cardLayout);

loginView = new LoginPane();
applicationView = new ApplicationPane();
add(loginView.getView(), LOGIN_VIEW);
add(applicationView.getView(), APPLICATION_VIEW);
loginView.setController(new LoginController() {

@Override
public void performLogin(LoginView view) {
// Do what ever you need to do...
String name = view.getUserName();
char[] password = view.getPassword();
//...

cardLayout.show(CoreApplicationCPane.this, APPLICATION_VIEW);
}

@Override
public void loginCanceled(LoginView view) {
SwingUtilities.windowForComponent(CoreApplicationCPane.this).dispose();
}
});

cardLayout.show(this, LOGIN_VIEW);

}

}

This is basically where everything gets plugged together. The LoginView and ApplicationView's are instantiated and added to the main view and the controller's are plugged in.

Sample ImageSample Image

Take a look at:

  • Laying Out Components Within a Container
  • How to Use CardLayout

for more details.

For a more detail example, take a look at Java and GUI - Where do ActionListeners belong according to MVC pattern?

Clicking a button within a JFrame passes an data to a JPanel

The Coordinates and Number classes weren't included, so I had to modify the code somewhat.

Here's the GUI I created.

Draw Letter

The first thing I did was create a model class for the GUI. By creating a model class, I could make the display string and the drawing coordinate available to the view and the controller classes. This is a simple example of the model / view / controller pattern.

package com.ggl.drawing;

import java.awt.Point;

public class GUIModel {

private String displayString;

private Point coordinate;

public GUIModel(String displayString) {
this.displayString = displayString;
}

public Point getCoordinate() {
return coordinate;
}

public void setCoordinate(int x, int y) {
this.coordinate = new Point(x, y);
}

public void setCoordinate(Point coordinate) {
this.coordinate = coordinate;
}

public void setDisplayString(String displayString) {
this.displayString = displayString;
}

public String getDisplayString() {
return displayString;
}

}

Now that we have a model, lets look at the DrawFrame class.

package com.ggl.drawing;

import java.awt.BorderLayout;
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;
import javax.swing.SwingUtilities;

public class DrawFrame implements Runnable {
private final int WIDTH = 500;
private final int HEIGHT = 300;

private JFrame frame;

private GUIModel model;

public DrawFrame() {
this.model = new GUIModel("A");
}

@Override
public void run() {
frame = new JFrame("Draw Letters");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

frame.add(createSelectionPanel(), BorderLayout.WEST);
frame.add(new DrawPanel(WIDTH, HEIGHT, model), BorderLayout.CENTER);

frame.pack();
frame.setVisible(true);
}

private JPanel createSelectionPanel() {
JPanel numberPanel = new JPanel();
ButtonListener listener = new ButtonListener();

JButton number1 = new JButton("A");
number1.addActionListener(listener);

JButton number2 = new JButton("B");
number2.addActionListener(listener);

numberPanel.setLayout(new GridLayout(0, 2));
numberPanel.add(number1);
numberPanel.add(number2);

return numberPanel;
}

private class ButtonListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent event) {
model.setDisplayString(event.getActionCommand());
}
}

// creates a drawing frame
public static void main(String[] args) {
SwingUtilities.invokeLater(new DrawFrame());
}
}

I started the Java Swing application on the Event Dispatch thread with the call to the SwingUtilities invokeLater method.

I separated the JFrame construction from the 2 JPanels construction. I used a JFrame, rather than extend a JFrame. The only time you should extend any Java class is if you want to override one or more of the class methods.

I used the same ButtonListener for both JButtons. I'm guessing what you want, but I drew either an "A" or a "B", depending on which button you left clicked.

Let's look at the DrawPanel class.

package com.ggl.drawing;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;

public class DrawPanel extends JPanel {

private static final long serialVersionUID = 3443814601865936618L;

private GUIModel model;

public DrawPanel(int width, int height, GUIModel model) {
this.setPreferredSize(new Dimension(width, height));
this.model = model;
// add mouse listeners
MouseHandler mouseHandler = new MouseHandler();
this.addMouseListener(mouseHandler);
}

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);

if (model.getCoordinate() != null) {
Point p = model.getCoordinate();
Font font = g.getFont().deriveFont(48F);
g.setFont(font);
g.drawString(model.getDisplayString(), p.x, p.y);
}
}

// class to handle all mouse events
private class MouseHandler extends MouseAdapter {

@Override
public void mousePressed(MouseEvent event) {
model.setCoordinate(event.getPoint());
}

@Override
public void mouseReleased(MouseEvent event) {
DrawPanel.this.repaint();
}

}
}

The major change I made in this class was to use the paintComponent method, rather than the paint method. The paintComponent method is the correct method to override.

I set the size of the drawing panel in the DrawPanel constructor. It's much better to let Swing figure out the size of the JFrame. That's what the pack method in the DrawFrame run method does.

I increased the font size so you can see the drawn letter better.

I removed the mouse motion listener code, as it wasn't needed.

I hope this was helpful to you.

How to open a new JPanel with a JButton?

The problem is that you have duplicate variables home and clients .

The folllowing is your modified code to fix that, with comments on the changed lines (five lines total) :

import java.awt.CardLayout;
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;
import javax.swing.border.EmptyBorder;

public class IA extends JFrame {

private final JPanel contentPane;
// private final JPanel home; // REMOVED
// private JPanel clients; // REMOVED

/**
* Launch the application.
*/
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
IA frame = new IA();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

/**
* Create the frame.
*/
public IA() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new CardLayout(0, 0));

final JPanel home = new JPanel();
contentPane.add(home, "name_714429679706141");
home.setLayout(null);

final JPanel clients = new JPanel(); // MOVED UP
contentPane.add(clients, "name_714431450350356"); // MOVED UP
clients.setLayout(null); // MOVED UP

JButton btnClients = new JButton("Clients");
btnClients.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
home.setVisible(false);
clients.setVisible(true);
}
});
btnClients.setBounds(160, 108, 89, 23);
home.add(btnClients);

JButton btnHome = new JButton("Home");
btnHome.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
clients.setVisible(false);
home.setVisible(true);
}
});
btnHome.setBounds(169, 107, 89, 23);
clients.add(btnHome);
}

}

Java Swing. Opening a new JPanel from a JButton and making the buttons pretty

Start by using a different layout manager, FlowLayout or GridBagLayout might work better

JPanel centerPanel = new JPanel(new FlowLayout());
centerPanel.add(openReportSelection);
centerPanel.add(closeButton);

These layouts will honour the preferred sizes of your buttons

As for opening another window, well, you've already create one, so the process is pretty much the same. Having said that, you might consider having a look at The Use of Multiple JFrames: Good or Bad Practice? before you commit yourself to far.

A better approach might be to use a JMenuBar and JMenuItems to act as the "open" and "exit" actions. Take a look at How to Use Menus then you could use a CardLayout to switch between views instead, for example

From a pure design perspective (I know it's only practice, but perfect practice makes perfect), I wouldn't extend anything from JFrame and instead would rely on building your main GUIs around something like JPanel instead.

This affords you the flexibility to decide how to use these components, as you could add them to frames, applets or other components...

How do I open a JFrame from a button click

Create ActionListeners for your buttons. Define your frames, and you can access them with your class name. For example;

class mainClient extends JPanel {
JFrame mainClientFrame = new JFrame();
}

and then;

mainClient mc = new mainClient();
mc.mainClientFrame.setVisible(true);

if you want to use this frames in your main void, define them static.

class mainClient extends JPanel {
static JFrame mainClientFrame = new JFrame();
}

change JPanel after clicking on a button

Simple as:

jframe.setContentPane(your_new_panel);
jframe.invalidate();
jframe.validate();

Make a Panel open when i click a button

I guess JDialog is what you need.

See this for details : How to Make Dialogs

Here is a sample :

Sample Image

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class CreateDialogFromOptionPane {

public static void main(final String[] args) {
JFrame parent = new JFrame();
JButton button = new JButton();

button.setText("Click me to show dialog!");
parent.add(button);
parent.pack();
parent.setVisible(true);

button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
JOptionPane optionPane = new JOptionPane("Is this what you need?", JOptionPane.QUESTION_MESSAGE,JOptionPane.YES_NO_OPTION);
JDialog dialog = optionPane.createDialog("Dialog");
dialog.setVisible(true);
}
});
}
}

Switch between panels using a button inside one of them

Your Program Works

That is, it switches panels.

The reason nothing happens when you try to switch to another panel using a button (by button you mean, JLabel with MouseListener) inside the scene0 class is that, in your jLabel1MouseClicked method, you are actually creating a new instance of MainPanel.

So, instead of changing panels in the already visible MainPanel, you are changing panels in a new MainPanel frame.

Solution:

Although there are other solutions, the solution that I could think for the long run is that, you should create a Main class in your Vista package. In that class you should create the instances of all your panels. Whenever, you run your program, run this class instead of running MainPanel class.

Demo-code of the Main class:

public class Main
{
public static MainPanel mainPanel;
public static scene0 firstScene = new scene0();
public static scene1 secondScene = new scene1();

public static void main(String[] args)
{
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
mainPanel = new MainPanel()
}
});
}
}

Now, whenever you are trying to access MainPanel,scene0 or scene1, access it using
Main.mainPanel or Main.scene0 or Main.scene1.

Modify your jLabel1MouseClicked method in this manner :

private void jLabel1MouseClicked(java.awt.event.MouseEvent evt) {                                     
Main.mainPanel.loadscene1();
}

You should also modify the sol() and loadscene1() method in this manner:

public void sol() {
mostrarPanel(Main.firstScene);
}

public void loadscene1(){
mostrarPanel(Main.secondScene);
}

Note: The code is not tested but I am sure it will work.



Related Topics



Leave a reply



Submit