i want to add panel from "newWork" class on pressing of "drop" button in "menuPan" class.
i cant add panel.
simply how to add Panel from different class on pressing button.
here are the three different classes .
MainClass :-
public class userFrame extends JFrame{
public void Frame()
{
setTitle("TEST CASE");
setSize(900,670);
add(new MenuPan(),BorderLayout.NORTH);
add(new WorkPan(),BorderLayout.CENTER);
setLocationRelativeTo(this);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String [] args){
userFrame u =new userFrame();
u.Frame();
}
}
MenuPan
public class MenuPan extends JPanel implements ActionListener{
WorkPan work=new WorkPan();
JButton view;
public menuPan() {
setBackground(Color.white);
setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
setLayout(new FlowLayout(1, 15, 10));
view=new JButton(" Registered Courses ");
view.addActionListener(this);
add(view);
}
#Override
public void actionPerformed(ActionEvent e) {
work.TaskPannel();
}
}
WorkPAN class :-
class WorkPan extends JPanel{
JPanel work=new JPanel();
public WorkPan() {
setBackground(Color.LIGHT_GRAY);
setLayout(new BorderLayout(40, 50));
}
void TaskPannel() {
System.out.println("here");
add(new NewWork(),BorderLayout.CENTER);// adds NewWork panel
}
}
NewWork Class
class NewWork extends JPanel{
public NewWork(){
setBackground(Color.red);
}
}
One issue -- you create one workPan (which should be renamed WorkPan), change its state in your ActionListener, but never add it to your GUI. So you appear to be changing the state of a non-displayed GUI component, and so it would make sense that nothing will show in the GUI.
Suggestions:
Be sure to create only one WorkPan reference,
Be sure to display this single reference in the GUI
Be sure that your ActionListener calls the appropriate method on the same reference.
Side recommendation:
Learn and follow Java naming conventions so you others can more easily understand and follow your code.
To swap JPanels within a GUI, I strongly advise you to use a CardLayout rather than adding and removing components manually as you're currently doing. Please check out the CardLayout Tutorial.
And my solution does work, but you also must call revalidate and repaint to get the GUI to layout the new component and repaint it. Note additions and changes as marked by the \\ !! comment
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FooWork {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
userFrame.main(args);
});
}
}
class NewWork extends JPanel {
public NewWork() {
setBackground(Color.red);
}
}
class WorkPan extends JPanel {
JPanel work = new JPanel();
public WorkPan() {
setBackground(Color.LIGHT_GRAY);
setLayout(new BorderLayout(40, 50));
}
void TaskPannel() {
System.out.println("here");
add(new NewWork(), BorderLayout.CENTER);// adds NewWork panel
// !!
revalidate();
repaint();
// !!
}
}
class MenuPan extends JPanel implements ActionListener {
// !! WorkPan work = new WorkPan();
WorkPan work; // !!
JButton view; // !!
// !!
public MenuPan(WorkPan workPan) { // references are key
// !!
this.work = workPan; // set the reference!
// !!
setBackground(Color.white);
setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
setLayout(new FlowLayout(1, 15, 10));
view = new JButton(" Registered Courses ");
view.addActionListener(this);
add(view);
}
#Override
public void actionPerformed(ActionEvent e) {
work.TaskPannel();
}
}
class userFrame extends JFrame {
public void Frame() {
setTitle("TEST CASE");
setSize(900, 670);
// !!
WorkPan workPan = new WorkPan();
MenuPan menuPan = new MenuPan(workPan);
// !!
// !!
// add(new MenuPan(), BorderLayout.NORTH);
// add(new WorkPan(), BorderLayout.CENTER);
add(menuPan, BorderLayout.NORTH);
add(workPan, BorderLayout.CENTER);
// !!
setLocationRelativeTo(this);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
userFrame u = new userFrame();
u.Frame();
}
}
But again, cleaner is to use a CardLayout to help with the swapping:
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class SwapStuff {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
private static void createAndShowGui() {
SwapMainPanel mainPanel = new SwapMainPanel();
JFrame frame = new JFrame("SwapStuff");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
}
class SwapMainPanel extends JPanel {
private CardLayout cardLayout = new CardLayout();
private JPanel cardPanel = new JPanel(cardLayout);
private ButtonPanel buttonPanel = new ButtonPanel(this); // pass the reference
private WorkPanel workPanel = new WorkPanel();
private ViewPanel viewPanel = new ViewPanel();
public SwapMainPanel() {
cardPanel.add(workPanel, workPanel.getClass().getName());
cardPanel.add(viewPanel, viewPanel.getClass().getName());
setLayout(new BorderLayout());
add(buttonPanel, BorderLayout.PAGE_START);
add(cardPanel, BorderLayout.CENTER);
}
// one possible way to swap "cards"
public void nextCard() {
cardLayout.next(cardPanel);
}
}
class ButtonPanel extends JPanel {
private SwapMainPanel mainPanel;
public ButtonPanel(SwapMainPanel mainPanel) {
this.mainPanel = mainPanel; // set the reference!
add(new JButton(new SwapAction("Swap Panels", KeyEvent.VK_S)));
}
private class SwapAction extends AbstractAction {
public SwapAction(String name, int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
mainPanel.nextCard();
}
}
}
class WorkPanel extends JPanel {
public WorkPanel() {
setBorder(BorderFactory.createTitledBorder("Work Panel"));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 400);
}
}
class ViewPanel extends JPanel {
public ViewPanel() {
setBorder(BorderFactory.createTitledBorder("View Panel"));
setBackground(Color.RED);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 400);
}
}
Related
I am new to Java Swing and I am trying to learn how to close one frame without closing the other one using button. For example I have a frame1/window that just have a button called login. Once I click on login button, another window appear frame2. On frame2 I just have a sample JLabel "Hello And Welcome", button called Logout. I want to be able to click on the Logout button on frame2 and frame2 window should close, but frame1 window show still be open. I have try setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE), but it only work if I click on the x icon on the top right of the frame2 window. Does anyone know of a way to close a frame when you click on a button?
public class Frame1 extends JFrame implements ActionListener{
private static JButton login = new JButton("Login");
private static JFrame f = new JFrame("Login");
Frame1(){
f.setSize(1000,750);
f.setLocation(750, 250);
login.setBounds(250, 350, 150, 30);
f.add(login);
f.setLayout(null);
f.setVisible(true);
login.addActionListener(this);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void actionPerformed(ActionEvent e){
if (e.getSource() == login){
Frame2.frame2windown();
}
}
public static void main(String [] args){
Frame1 login1 = new Frame1();
}
}
public class Frame2 extends JFrame implements ActionListener{
private static JButton logout = new JButton("Logout");
private static JLabel jb1 = new JLabel ("Hello And Welcome");
private static JFrame f = new JFrame("Log Out");
Frame2(){
f.setSize(1000,750);
f.setLocation(750, 250);
jb1.setBounds(250, 150, 350, 30);
logout.setBounds(250, 350, 150, 30);
f.add(logout);
f.add(jb1);
f.setLayout(null);
f.setVisible(true);
logout.addActionListener(this);
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public void actionPerformed(ActionEvent a){
if(a.getSource() == logout){
dispose();
WindowEvent closeWindow = new WindowEvent(this, JFrame.DISPOSE_ON_CLOSE);
Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(closeWindow);
}
}
public static void frame2windown(){
Frame2 f2 = new Frame2();
}
}
So, there are a whole bunch of concepts your need to try and learn.
It's generally recommended NOT to extend from top level containers (like JFrame). You're not adding any new functionality too them; they are complicated, compound components; you lock yourself into a single use case (what happens if you want to include the UI in another UI or use a dialog instead of frame?!)
Multiple frames aren't always a good idea and can be confusing to the user. Generally, with login workflows though, I might argue a login dialog is generally a better solution, but you need to understand the use cases to make those determinations.
Swing is a large, rich and diverse API, it has a LOT of inbuilt functionality, which you can use, to make your life easier (although it doesn't always seem this way)
Layout managers are an absolutely required feature and you really need to take the time to learn them, see Laying Out Components Within a Container for more details.
So, a really quick example of using a CardLayout and a basic "observer pattern", which decouples and separates responsibility.
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.EventListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new NavigationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class NavigationPane extends JPanel {
protected enum NavigationTarget {
LOGIN, MAIN;
}
private LoginPane loginPane;
private MainPane mainPane;
private CardLayout cardLayout;
public NavigationPane() {
cardLayout = new CardLayout();
setLayout(cardLayout);
loginPane = new LoginPane();
loginPane.addLoginListener(new LoginPane.LoginListener() {
#Override
public void loginDidFail(LoginPane source) {
JOptionPane.showMessageDialog(NavigationPane.this, "You are not unauthroised", "Error", JOptionPane.ERROR_MESSAGE);
}
#Override
public void loginWasSuccessful(LoginPane source) {
navigateTo(NavigationTarget.MAIN);
}
});
mainPane = new MainPane();
add(loginPane, NavigationTarget.LOGIN.name());
add(mainPane, NavigationTarget.MAIN.name());
navigateTo(NavigationTarget.LOGIN);
}
protected void navigateTo(NavigationTarget target) {
cardLayout.show(this, target.name());
}
}
public static class LoginPane extends JPanel {
public static interface LoginListener extends EventListener {
public void loginDidFail(LoginPane source);
public void loginWasSuccessful(LoginPane source);
}
public LoginPane() {
setBorder(new EmptyBorder(10, 10, 10, 10));
setLayout(new GridBagLayout());
JButton btn = new JButton("Login");
btn.addActionListener(new ActionListener() {
private Random rnd = new Random();
#Override
public void actionPerformed(ActionEvent e) {
// Do some logic here
if (rnd.nextBoolean()) {
fireLoginWasSuccessful();
} else {
fireLoginDidFail();
}
}
});
add(btn);
}
public void addLoginListener(LoginListener listener) {
listenerList.add(LoginListener.class, listener);
}
public void removeLoginListener(LoginListener listener) {
listenerList.remove(LoginListener.class, listener);
}
protected void fireLoginDidFail() {
LoginListener[] listeners = listenerList.getListeners(LoginListener.class);
for (LoginListener listener : listeners) {
listener.loginDidFail(this);
}
}
protected void fireLoginWasSuccessful() {
LoginListener[] listeners = listenerList.getListeners(LoginListener.class);
for (LoginListener listener : listeners) {
listener.loginWasSuccessful(this);
}
}
}
public static class MainPane extends JPanel {
public MainPane() {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(10, 10, 10, 10));
add(new JLabel("Welcome"));
}
}
}
JDialog based login workflow
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
NavigationPane navigationPane = new NavigationPane();
JFrame frame = new JFrame();
frame.add(navigationPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
if (LoginPane.showLoginDialog(navigationPane)) {
navigationPane.didLogin();
} else {
frame.dispose();
}
}
});
}
public static class NavigationPane extends JPanel {
protected enum NavigationTarget {
SPLASH, MAIN;
}
private SplashPane splashPane;
private MainPane mainPane;
private CardLayout cardLayout;
public NavigationPane() {
cardLayout = new CardLayout();
setLayout(cardLayout);
mainPane = new MainPane();
splashPane = new SplashPane();
add(splashPane, NavigationTarget.SPLASH.name());
add(mainPane, NavigationTarget.MAIN.name());
navigateTo(NavigationTarget.SPLASH);
}
protected void navigateTo(NavigationTarget target) {
cardLayout.show(this, target.name());
}
public void didLogin() {
navigateTo(NavigationTarget.MAIN);
}
}
public static class LoginPane extends JPanel {
private Random rnd = new Random();
private boolean isAuthorised = false;
public LoginPane() {
setBorder(new EmptyBorder(10, 10, 10, 10));
setLayout(new GridBagLayout());
add(new JLabel("User name and password fields go here"));
}
protected void authenticate() {
// Authenticate
isAuthorised = rnd.nextBoolean();
if (!isAuthorised) {
JOptionPane.showMessageDialog(this, "You are not authorised", "Error", JOptionPane.ERROR_MESSAGE);
}
}
// So this should return some kind of "session" or something so
// can identify the user, but for now, we'll just use
// a boolean
public boolean isAuthorised() {
return isAuthorised;
}
public static boolean showLoginDialog(Component parent) {
LoginPane loginPane = new LoginPane();
JPanel panel = new JPanel(new BorderLayout());
JPanel buttonPane = new JPanel(new GridBagLayout());
JButton okayButton = new JButton("Login");
JButton cancelButton = new JButton("Cancel");
buttonPane.add(okayButton);
buttonPane.add(cancelButton);
panel.add(loginPane);
panel.add(buttonPane, BorderLayout.SOUTH);
JDialog dialog = new JDialog(SwingUtilities.windowForComponent(parent));
dialog.add(panel);
okayButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
loginPane.authenticate();
if (loginPane.isAuthorised()) {
dialog.dispose();
}
}
});
cancelButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
dialog.setModal(true);
dialog.pack();
dialog.setLocationRelativeTo(parent);
dialog.setVisible(true);
return loginPane.isAuthorised();
}
}
public static class SplashPane extends JPanel {
public SplashPane() {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(10, 10, 10, 10));
add(new JLabel("This is a splash panel, put some nice graphics here"));
}
}
public static class MainPane extends JPanel {
public MainPane() {
setLayout(new GridBagLayout());
setBorder(new EmptyBorder(10, 10, 10, 10));
add(new JLabel("Welcome"));
}
}
}
You duplicated the JFrame, created a JFrame field f inside the JFrame.
Do not use static components like the button.
public class Frame1 extends JFrame implements ActionListener {
private final JButton login = new JButton("Login");
Frame1() {
setTitle("Login");
setSize(1000, 750);
setLocation(750, 250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(null);
login.setBounds(250, 350, 150, 30);
add(login);
login.addActionListener(this);
setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == login) {
Frame2.frame2windown();
}
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
Frame1 login1 = new Frame1();
}
}
}
Use the swing/awt event queue (invokeLater) as on this thread window events are handled and dispatched further.
And Frame2:
public class Frame2 extends JFrame implements ActionListener {
private JButton logout = new JButton("Logout");
private JLabel jb1 = new JLabel("Hello And Welcome");
Frame2() {
setTitle("Logout");
setSize(1000, 750);
setLocation(750, 250);
setLayout(null);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
jb1.setBounds(250, 150, 350, 30);
logout.setBounds(250, 350, 150, 30);
add(logout);
add(jb1);
logout.addActionListener(this);
setVisible(true);
}
public void actionPerformed(ActionEvent a) {
if (a.getSource() == logout) {
setVisible(false); // <--- ALL
}
}
public static void frame2windown() {
Frame2 f2 = new Frame2();
}
}
JFrame.setVisible does it all. Especially setVisible(true) should maybe even done after the constructor is called, so it always is last.
Another remark, dive into layout managers fast. Absolute layouts (null) are a PITA.
I'm getting an AWT-EventQueue-0 Null Pointer Exception in the below code and I can't get to fix it.
I want to have a main frame, from which by pressing a button
I open a second frame, where I have the option to create new players,
which would show up in the main frame.
I passed the references to the constructors, but I still keep getting the error.
I would be very happy for some help, thanks!
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new App();
}
});
}
}
public class App extends JFrame {
private MainPanel mainPanel;
private SecondPanel secondPanel;
public App() {
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(800, 600);
secondPanel = new SecondPanel(mainPanel);
mainPanel = new MainPanel(secondPanel);
add(mainPanel);
}
}
public class MainPanel extends JPanel {
private JTextArea textArea;
private JScrollPane scrollPane;
private JButton options;
public MainPanel(SecondPanel secondPanel) {
textArea = new JTextArea();
textArea.setColumns(20);
textArea.setRows(5);
textArea.setSize(300, 300);
textArea.setVisible(true);
textArea.setEditable(false);
scrollPane = new JScrollPane(textArea);
scrollPane.setSize(new Dimension(400, 400));
options = new JButton("Options");
options.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
secondPanel.setVisible(true);
}
});
add(scrollPane);
add(options);
}
public JTextArea getTextArea() {
return textArea;
}
public void setTextArea(JTextArea textArea) {
this.textArea = textArea;
}
}
public class SecondPanel extends JFrame {
private JButton create, remove;
private JPanel panel;
public SecondPanel(MainPanel mainPanel) {
setVisible(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 400);
panel = new JPanel();
panel.setLayout(new BorderLayout());
create = new JButton("create");
create.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mainPanel.getTextArea().append("New Player Created");
}
});
remove = new JButton("remove");
remove.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
mp.getTextArea().setText("Player removed");
}
});
add(panel);
panel.add(create, BorderLayout.EAST);
panel.add(remove, BorderLayout.WEST);
}
}
Well, it has to be "null", because you don't initialise your MainPanel before you hand it over to the secondPanel.
Instead, make an own method for setting the MainPanel on the secondPanel and to set the secondPanel on the MainPanel.
I see that you need the secondPanel for instance in your constructor to set an ActionListener. Do that in your "setSecondPanel(SecondPanel sPanel)"-Method which, as I mentioned before, you should create.
I want to create a common JPanel template that will be used by all the other panel. The Common JPanel Template would have a common header and footer. Below is the sample code of the common template JPanel.
import javax.swing.*;
public abstract class AbstractPanel extends JPanel {
public AbstractPanel() {
super();
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
init();
addHeader();
addComponentsToScreen();
addFooter();
}
private void addHeader() {
add(new JLabel("Common Header"));
}
private void addFooter() {
add(new JLabel("Common Footer"));
}
protected abstract void init();
protected abstract void addComponentsToScreen();
}
Now I want to create a JPanel using this AbstractPanel with two different layouts based on the input parameter.
import javax.swing.*;
public class MyPanel extends AbstractPanel {
private boolean showDept;
private JTextField jTextEmp;
private JTextField jTextName;
private JTextField jTextDept;
public MyPanel(boolean showDept) {
super();
this.showDept = showDept;
}
protected void init() {
jTextEmp = new JTextField();
jTextName = new JTextField();
jTextDept = new JTextField();
}
protected void addComponentsToScreen() {
add(new JLabel("Employee"));
add(jTextEmp);
add(new JLabel("Name"));
add(jTextName);
if(showDept) {
add(new JLabel("Dept"));
add(jTextDept);
}
}
public static void main(String[] args) {
JFrame window = new JFrame();
window.add(new MyPanel(true));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(200, 500);
window.setVisible(true);
}
}
The problem with the above code is that the showDept is always false for the method addComponentsToScreen as it is called from the superclass constructor. Is there a better way to do this? Any help is appreciated.
Make your super class constructor a parameterised constructor and pass showDept to super class constructor.
Sample Code:
import javax.swing.*;
public abstract class AbstractPanel extends JPanel {
private boolean showDept; // add public getter for it
public AbstractPanel(boolean showDept) {
super();
this.showDept = showDept;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
init();
addHeader();
addComponentsToScreen();
addFooter();
}
private void addHeader() {
add(new JLabel("Common Header"));
}
private void addFooter() {
add(new JLabel("Common Footer"));
}
protected abstract void init();
protected abstract void addComponentsToScreen();
}
MyPanel class:
import javax.swing.*;
public class MyPanel extends AbstractPanel {
private boolean showDept;
private JTextField jTextEmp;
private JTextField jTextName;
private JTextField jTextDept;
public MyPanel(boolean showDept) {
super(showDept);
}
protected void init() {
jTextEmp = new JTextField();
jTextName = new JTextField();
jTextDept = new JTextField();
}
protected void addComponentsToScreen() {
add(new JLabel("Employee"));
add(jTextEmp);
add(new JLabel("Name"));
add(jTextName);
if(getShowDept()) {
add(new JLabel("Dept"));
add(jTextDept);
}
}
public static void main(String[] args) {
JFrame window = new JFrame();
window.add(new MyPanel(true));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(200, 500);
window.setVisible(true);
}
}
Other way around, make your panels totally independent from the each other. as this application basic you want to keep same header and footer on very view you can use following.
class MyDynamicPanel extends JPanel {
public MyDynamicPanel() {
super();
setLayout(new BorderLayout());
addAppHeader();
addAppFooter();
}
private void addAppHeader() {
add(new JLabel("Common Header"),BorderLayout.NORTH);
}
public void addAppCenter(JPanel centerPanel){
add(centerPanel,BorderLayout.CENTER);
}
private void addAppFooter() {
add(new JLabel("Common Footer"),BorderLayout.SOUTH);
}
}
This use border layout to adjust itself in every size of screen or frame.
Now your custom panel.
public class MyPanel extends MyDynamicPanel {
private JTextField jTextEmp;
private JTextField jTextName;
private JTextField jTextDept;
private JPanel centerPanel;
public MyPanel() {
super();
init();
addComponentsToScreen();
}
protected void init() {
centerPanel = new JPanel();
jTextEmp = new JTextField("",20);
jTextName = new JTextField("",20);
jTextDept = new JTextField("",10);
}
protected void addComponentsToScreen() {
centerPanel.add(new JLabel("Name"));
centerPanel.add(jTextEmp);
centerPanel.add(new JLabel("Employee"));
centerPanel.add(jTextName);
centerPanel.add(new JLabel("dept"));
centerPanel.add(jTextDept);
addAppCenter(centerPanel);
}
public static void main(String[] args) {
JFrame window = new JFrame();
window.add(new MyPanel());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(200, 500);
window.setVisible(true);
}
}
This Panel can have its own layout and components
In this code , I have used 3 classes all of them which extend the JPanel class , whose instances are added to a JFrame in the JForm3 class's constructor.
I am wondering if there's a way to display the text present in the text field(instance of JTextField declared in TextPanel class) in the printTextOnConsole() method in the ButtonPanel class.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class JForm3
{
JFrame frame;
ButtonPanel bP;
TextPanel tP;
LabelPanel lP;
public JForm3()
{
frame = new JFrame("Java Window.");
bP = new ButtonPanel();
tP = new TextPanel();
lP = new LabelPanel();
frame.setSize(500,100);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(BorderLayout.CENTER,tP);
frame.getContentPane().add(BorderLayout.EAST,bP);
frame.getContentPane().add(BorderLayout.WEST,lP);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args)
{
new JForm3();
}
}
class ButtonPanel extends JPanel implements ActionListener
{
JButton quitButton;
JButton printButton;
public ButtonPanel()
{
quitButton = new JButton("Quit");
printButton = new JButton("Print");
quitButton.addActionListener(this);
printButton.addActionListener(this);
this.setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
this.add(quitButton);
this.add(printButton);
}
public void actionPerformed(ActionEvent event)
{
if(event.getSource() == quitButton)
System.exit(0);
else
printTextOnConsole();
}
public void printTextOnConsole()
{
}
}
class LabelPanel extends JPanel
{
JLabel label;
public LabelPanel()
{
this.setLayout(new BorderLayout());
label = new JLabel("Enter Some Text :");
this.add(BorderLayout.CENTER,label);
this.setVisible(true);
}
}
class TextPanel extends JPanel
{
JTextField textField;
public TextPanel()
{
this.setLayout(new BorderLayout());
textField = new JTextField("Enter text here");
this.add(BorderLayout.CENTER,textField);
this.requestFocus();
textField.select(0,textField.getText().length());
this.setVisible(true);
}
}
Use an interface to loose couple the text functionality between JPanels.
interface TextRetriever {
String getText();
}
Then pass the instance of the TextRetriever (TextPanel) to ButtonPanel
class ButtonPanel extends JPanel implements ActionListener {
private TextRetriever textRetriever;
public ButtonPanel(TextRetriever textRetriever) {
this.textRetriever = textRetriever
...
}
public void printTextOnConsole() {
String text = textRetriever.getText();
}
}
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