Button in CardLayout not working - java

So I'm using cardLayout in one of my programs and I'm trying to make it so that when you click a button the next panel loads. I have a panelHolder class where the cardlayout is held and every time the button on the panel is pressed, it would call a method in the panelHolder class that depending on the button sets a certain boolean variable to true and calls repaint (where the panels are shown). For some reason my button isn't working and I can't seem to find out why. Can someone help me?
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.util.Arrays;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
import javax.swing.*;
public class SheetReader101 extends JFrame {
public SheetReader101(){
super("SheetReader101");
setSize(2000,1000);
setLocation(0,0);
setResizable(true);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
PanelHolder pg2 = new PanelHolder();
setContentPane(pg2);
setVisible(true);
}
public static void main(String[]args){
SheetReader101 z1 = new SheetReader101();
}
}
class PanelHolder extends JPanel { // HERE
CardLayout clayout = new CardLayout();
PianoGameContent x;
tutorial y;
boolean [] paneldecide;
PanelHolder() {
super();
y = new tutorial();
x = new PianoGameContent();
setLayout(clayout);
this.add("Tutorial", y);
this.add("FreePlay Mode", x);
paneldecide = new boolean[15];
}
public static void main(String[]args){
PanelHolder z1 = new PanelHolder();
z1.run();
}
public void run(){
layoutShower(0);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
}
public void layoutShower (int decide){
{
PianoGameContent y2 = new PianoGameContent();
PanelHolder.this.add("Piano", y2);
System.out.println("intro slide run");
if(decide == 1){
PanelHolder.this.add("Piano", y2);
System.out.println("testing11");
clayout.show(PanelHolder.this,"Piano");
}
}
}
}

I "suspect" that the core problem has to do with the original code you posted, where you're making a new instance of PanelHolder in your child view's ActionListener and then are attempting to switch views, this new instance has no relationship to the instance that is on the screen.
There are a few ways you can manage CardLayout, my preferred way is to use some kind of "navigation" controller which defines how navigation works, for example, you could have "next" and "previous" or "back", or you could define the actual views that can be displayed, ie showMenuView, showTutorialView etc, depending on how much control you want to give your sub views.
The following is a simple example which demonstrates the basic idea, it uses a enum to define the available views (as it has more meaning than 0, 1... and I don't need to remember the actual names of the views, the IDE can provide auto correct for that ;))
I create and add each view up front when I create the PanelHolder, I also pass each view an instance of the NavigationController, so they can interact with it
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
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.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class JavaApplication1013 {
public static void main(String[] args) {
new JavaApplication1013();
}
public JavaApplication1013() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new PanelHolder());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum View {
MENU,
TUTORIAL,
FREEPLAY;
}
public interface NavigationController {
public void showView(View view);
}
public class PanelHolder extends JPanel implements NavigationController {
private CardLayout cardLayout;
public PanelHolder() {
cardLayout = new CardLayout();
setLayout(cardLayout);
add(new MenuView(this), View.MENU.name());
add(new TutorialView(this), View.TUTORIAL.name());
add(new FreePlayView(this), View.FREEPLAY.name());
}
#Override
public void showView(View view) {
cardLayout.show(this, view.name());
}
}
public abstract class ViewPane extends JPanel {
private NavigationController controller;
public ViewPane(NavigationController controller) {
this.controller = controller;
}
public NavigationController getController() {
return controller;
}
protected void showView(View view) {
controller.showView(view);
}
}
public class MenuView extends ViewPane {
public MenuView(NavigationController controller) {
super(controller);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
JButton tut = new JButton("Tutorial");
JButton freePlay = new JButton("Free Play");
add(tut, gbc);
add(freePlay, gbc);
tut.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
showView(View.TUTORIAL);
}
});
freePlay.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
showView(View.FREEPLAY);
}
});
}
}
public class TutorialView extends ViewPane {
public TutorialView(NavigationController controller) {
super(controller);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JButton menu = new JButton("Menu");
add(new JLabel("Tutorial"), gbc);
add(menu, gbc);
menu.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
showView(View.MENU);
}
});
}
}
public class FreePlayView extends ViewPane {
public FreePlayView(NavigationController controller) {
super(controller);
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JButton menu = new JButton("Menu");
add(new JLabel("Free Play"), gbc);
add(menu, gbc);
menu.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
showView(View.MENU);
}
});
}
}
}
Take a closer look at How to Use CardLayout for more details

Related

How can I open a JInternalFrame inside a panel (inside parent) from another child JInternalFrame?

I have 3 frames, Main (as the parent) and 2 JInternalFrames (F1 and F2 as children). When a button (inside parent) is pressed, I make an instance of F1 and send it as a parameter to ShowIntrlFrame() so F1 can be displayed inside frmContainter. My question here is, how can I open F2 from F1 and display it on frmContrainer (which is in the Main frame)?
public class Main extends javax.swing.JFrame{
public Main(){
}
private void btnOpenFrmActionPerformed(java.awt.event.ActionEvent evt) {
F1 f1 = new F1();
frmContainer(f1);
}
}
public void ShowIntrlFrame(JInternalFrame f){
f.setSize(1100, 620);
f.setLocation(0, 0);
f.setVisible(true);
frmContainer.removeAll();
frmContainer.add(f, BorderLayout.CENTER);
frmContainer.revalidate();
frmContainer.repaint();
}
What I would do is follow a delegation pattern via dependency injection.
This is, I would "delegate" the functionality need to generate and show the window to some other class and then "inject" that into the workflow as required
I'd start with a concept of a "window manager"...
public interface WindowManager {
enum Window {
FIRST, SECOND;
}
public void openWindow(Window window);
}
At the moment, this is pretty basic and just opens a specified window. The nice thing about this, is we don't care if it's a JInternalFrame or JFrame which gets generated, that's not the callers responsibility.
Next, we make a implementation which supports JDesktopPane
public class DesktopWindowManage implements WindowManager {
private JDesktopPane desktopPane;
private int initialX = 0;
private int initialY = 0;
public DesktopWindowManage(JDesktopPane desktopPane) {
this.desktopPane = desktopPane;
}
public JDesktopPane getDesktopPane() {
return desktopPane;
}
#Override
public void openWindow(Window window) {
JInternalFrame frame = new JInternalFrame(window.name(), true, true, true, true);
frame.setContentPane(makeContentFor(window));
frame.pack();
frame.setLocation(initialX, initialY);
frame.setVisible(true);
try {
frame.setSelected(true);
} catch (PropertyVetoException ex) {
}
desktopPane.add(frame);
frame.toFront();
initialX += 20;
initialY += 20;
}
protected JPanel makeContentFor(Window window) {
switch (window) {
case FIRST: return new FirstPane(this);
case SECOND: return new SecondPane();
}
return null;
}
}
Now, important to note, this class is acting as kind of factory, in that it's generating the content view and JInternalFrame. I'd probably consider making a "content factory" which could be injected into this which would then create the content based on the desired destination, but that's probably getting a little more complicated then is required right now.
Now, before you ask, the actual content is based on JPanel, for example...
public class FirstPane extends JPanel {
public FirstPane(WindowManager windowManager) {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
add(new JLabel("I am first"), gbc);
JButton showSecond = new JButton("Show second");
showSecond.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.SECOND);
}
});
add(showSecond, gbc);
}
}
public class SecondPane extends JPanel {
public SecondPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
add(new JLabel("I am second"));
}
}
Why? Because it's a JPanel can be added to any container and, generally, we don't care if it's a JInternalFrame or JFrame.
And finally, some kind of "starting point"....
public class MainPane extends JPanel {
private WindowManager windowManager;
private JDesktopPane desktopPane;
public MainPane() {
setLayout(new BorderLayout());
JButton open = new JButton("Open");
desktopPane = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
windowManager = new DesktopWindowManage(desktopPane);
add(open, BorderLayout.NORTH);
add(desktopPane);
open.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.FIRST);
}
});
}
}
Runnable example...
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyVetoException;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.add(new MainPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface WindowManager {
enum Window {
FIRST, SECOND;
}
public void openWindow(Window window);
}
public class DesktopWindowManage implements WindowManager {
private JDesktopPane desktopPane;
private int initialX = 0;
private int initialY = 0;
public DesktopWindowManage(JDesktopPane desktopPane) {
this.desktopPane = desktopPane;
}
public JDesktopPane getDesktopPane() {
return desktopPane;
}
#Override
public void openWindow(Window window) {
JInternalFrame frame = new JInternalFrame(window.name(), true, true, true, true);
frame.setContentPane(makeContentFor(window));
frame.pack();
frame.setLocation(initialX, initialY);
frame.setVisible(true);
try {
frame.setSelected(true);
} catch (PropertyVetoException ex) {
}
desktopPane.add(frame);
frame.toFront();
initialX += 20;
initialY += 20;
}
protected JPanel makeContentFor(Window window) {
switch (window) {
case FIRST: return new FirstPane(this);
case SECOND: return new SecondPane();
}
return null;
}
}
public class MainPane extends JPanel {
private WindowManager windowManager;
private JDesktopPane desktopPane;
public MainPane() {
setLayout(new BorderLayout());
JButton open = new JButton("Open");
desktopPane = new JDesktopPane() {
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
};
windowManager = new DesktopWindowManage(desktopPane);
add(open, BorderLayout.NORTH);
add(desktopPane);
open.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.FIRST);
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class FirstPane extends JPanel {
public FirstPane(WindowManager windowManager) {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = gbc.REMAINDER;
add(new JLabel("I am first"), gbc);
JButton showSecond = new JButton("Show second");
showSecond.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
windowManager.openWindow(WindowManager.Window.SECOND);
}
});
add(showSecond, gbc);
}
}
public class SecondPane extends JPanel {
public SecondPane() {
setBorder(new EmptyBorder(32, 32, 32, 32));
setLayout(new GridBagLayout());
add(new JLabel("I am second"));
}
}
}
But wait, there's more...
Currently, if you tap "Open" or "Show second" multiple times, you get a bunch of new windows. This may or may not be desirable, but could be easily fixed via the WindowManager, in fact, you could create different WindowManagers based on your needs, for example...
public class DesktopWindowManage implements WindowManager {
private JDesktopPane desktopPane;
private int initialX = 0;
private int initialY = 0;
private Map<Window, JInternalFrame> windowCache = new HashMap<>();
public DesktopWindowManage(JDesktopPane desktopPane) {
this.desktopPane = desktopPane;
}
public JDesktopPane getDesktopPane() {
return desktopPane;
}
#Override
public void openWindow(Window window) {
JInternalFrame frame = windowCache.get(window);
if (frame == null) {
frame = new JInternalFrame(window.name(), true, true, true, true);
frame.setContentPane(makeContentFor(window));
windowCache.put(window, frame);
frame.pack();
frame.setLocation(initialX, initialY);
frame.setVisible(true);
desktopPane.add(frame);
initialX += 20;
initialY += 20;
}
try {
frame.setSelected(true);
} catch (PropertyVetoException ex) {
}
frame.toFront();
}
protected JPanel makeContentFor(Window window) {
switch (window) {
case FIRST:
return new FirstPane(this);
case SECOND:
return new SecondPane();
}
return null;
}
}

how to make JButton show a list of JButtons with just few items

Hey Guys my problem is when I place the mouse on a JButton in my JFrame, I want it to show a list of JButtons on its left.
I don't known how to do that really I feel like I'm blocked and I cant make any progress in my project.
I'd would be grateful if you could help me and thanks in advance.
Can you create the list of buttons in a JPanel, add it to your JFrame and then call myPanel.setVisible(false). When you click your button then call myPanel.setVisible(true)?
As for ensuring that myPanel is positioned correctly you will want to use a Layout Manager
Or is there a more complex behaviour you want?
A basic option would be to use a MouseListener and a CardLayout. The MouseListener would be used to determine when the mouse cursor enters/exists a given component and the CardLayout would be used to display the appropriate sub component for each "menu" element.
I have to say, JButton would be me last choice for the "menu" item, in most cases, a JLabel would be preferred or even perhaps using a JMenu, which can can have sub menus, which can be displayed automatically might be a better choice, or even a JComboBox....
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class ShowStuff {
public static void main(String[] args) {
new ShowStuff();
}
public ShowStuff() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
MenuPane menu = new MenuPane();
menu.addMenu("Fruit", new FruitPane());
menu.addMenu("Meat", new MeatPane());
menu.addMenu("Dairy", new DairyPane());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(menu);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class MenuPane extends JPanel {
private JPanel subMenu;
private JPanel menu;
private CardLayout cardLayout;
private MouseListener mouseHandler;
public MenuPane() {
setLayout(new BorderLayout());
cardLayout = new CardLayout();
subMenu = new JPanel(cardLayout);
menu = new JPanel(new GridBagLayout());
add(subMenu);
add(menu, BorderLayout.WEST);
subMenu.add(new JPanel(), "BLANK");
mouseHandler = new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent e) {
if (e.getSource() instanceof JButton) {
JButton btn = (JButton) e.getSource();
cardLayout.show(subMenu, btn.getText());
}
}
#Override
public void mouseExited(MouseEvent e) {
cardLayout.show(subMenu, "BLANK");
}
};
}
public void addMenu(String name, JPanel subMenuPane) {
JButton button = new JButton(name);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
menu.add(button, gbc);
subMenu.add(subMenuPane, name);
button.addMouseListener(mouseHandler);
}
}
public abstract class ButtonPane extends JPanel {
private int gridy = 0;
public ButtonPane() {
setLayout(new GridBagLayout());
}
protected void addButton(String name) {
JButton btn = new JButton(name);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = gridy++;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(btn, gbc);
}
}
public class FruitPane extends ButtonPane {
public FruitPane() {
addButton("Banana");
addButton("Grapes");
addButton("Apples");
addButton("Tomatoes");
}
}
public class MeatPane extends ButtonPane {
public MeatPane() {
addButton("Lamb");
addButton("Beef");
addButton("Pork");
addButton("Mince");
}
}
public class DairyPane extends ButtonPane {
public DairyPane() {
addButton("Milk");
addButton("Cream");
addButton("Cheese");
addButton("Yoghurt");
}
}
}

Singleton with CardLayout won't show card when another class calls Singleton.instance.show()

public class MainWindow extends JPanel {
public static MainWindow instance = new MainWindow();
private CardLayout cards = new CardLayout();
public MainWindow() {
setLayout(cards);
add(new FirstPage(), Pages.FIRST.toString());
add(new SecondPage(), Pages.SECOND.toString());
add(new ThirdPage(), Pages.THIRD.toString());
}
public void showPage(Pages page) {
cards.show(this, page.toString());
}
}
the showPage(page); method works fine if I call it in the constructor of MainWindow. But when I try to call MainWindow.instance.showPage(Pages.SECOND); from an ActionListener in FirstPage nothing happens. I've checked that the showPage(page) method works correctly. I've checked that the ActionEvent is fired and enters the correct if/else clause. What am I doing wrong, why isn't my second page showing?
public class FirstPage extends JPanel {
private JButton showSecond = new JButton("Show Second");
private JButton showThird = new JButton("Show Third");
public FirstPage() {
insertButton(showSecond);
insertButton(showThird);
}
private void insertButton(JButton button) {
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == showSecond) {
MainWindow.instance.showPage(Pages.SECOND);
} else {
MainWindow.instance.showPage(Pages.THIRD);
}
}
});
this.add(button);
}
}
It would suggest a reference issue. public static MainWindow instance = new MainWindow(); looks suspicious, as you would have had to create an instance of MainWindow first for it to be initialise which suggests you now have two instances of MainWindow, one on the screen and one that is not
Using static in this way is a bad idea, as it leads to issues like this. Instead you should pass a reference of the controller to the page. The controller would define the actions that each page could perform (and if done right, would be defined as an interface)
Alternatively, you could separate the navigation from the pages into a separate mechanism, this means the pages don't care and can simply displayed in any order you want or reused else where
Example #1 - Controller based pages
This examples defines a simple controller which the pages can call in order to effect the navigation of the pages
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CardLayoutExample {
public static void main(String[] args) {
new CardLayoutExample();
}
public CardLayoutExample() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new Wizard());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public interface NavigationController {
public void nextPage();
public void previousPage();
public void lastPage();
public void firstPage();
}
public interface Page {
public NavigationController getNavigationController();
public JComponent getView();
public String getName();
}
public class Wizard extends JPanel implements NavigationController {
private List<Page> pages;
private Page currentPage;
private CardLayout cardLayout;
public Wizard() {
cardLayout = new CardLayout();
pages = new ArrayList<>(25);
setLayout(cardLayout);
pages.add(new FirstPage("Page01", this));
pages.add(new SecondPage("Page02", this));
pages.add(new ThirdPage("Page03", this));
for (Page page : pages) {
add(page.getView(), page.getName());
}
firstPage();
}
#Override
public void nextPage() {
int index = pages.indexOf(currentPage);
index++;
if (index < pages.size()) {
cardLayout.next(this);
currentPage = pages.get(index);
}
}
#Override
public void previousPage() {
int index = pages.indexOf(currentPage);
index--;
if (index >= 0) {
cardLayout.previous(this);
currentPage = pages.get(index);
}
}
#Override
public void lastPage() {
Page page = pages.get(pages.size() - 1);
showPage(page);
}
#Override
public void firstPage() {
Page page = pages.get(0);
showPage(page);
}
protected void showPage(Page page) {
cardLayout.show(this, page.getName());
currentPage = page;
}
}
public abstract class AbstractPage extends JPanel implements Page, ActionListener {
private NavigationController navigationController;
private JPanel buttons;
private String name;
public AbstractPage(String name, NavigationController navigationController) {
this.name = name;
this.navigationController = navigationController;
setLayout(new BorderLayout());
buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
add(buttons, BorderLayout.SOUTH);
}
protected void insertButton(JButton button) {
button.addActionListener(this);
buttons.add(button);
}
#Override
public NavigationController getNavigationController() {
return navigationController;
}
#Override
public JComponent getView() {
return this;
}
#Override
public String getName() {
return super.getName();
}
}
public class FirstPage extends AbstractPage implements Page {
private JButton next = new JButton("Next >");
public FirstPage(String name, NavigationController controller) {
super(name, controller);
JLabel label = new JLabel("First page");
label.setHorizontalAlignment(JLabel.CENTER);
add(label);
insertButton(next);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == next) {
getNavigationController().nextPage();
}
}
}
public class SecondPage extends AbstractPage implements Page {
private JButton next = new JButton("Next >");
private JButton previous = new JButton("< Previous");
public SecondPage(String name, NavigationController controller) {
super(name, controller);
JLabel label = new JLabel("Second page");
label.setHorizontalAlignment(JLabel.CENTER);
add(label);
insertButton(previous);
insertButton(next);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == next) {
getNavigationController().nextPage();
} else if (e.getSource() == previous) {
getNavigationController().previousPage();
}
}
}
public class ThirdPage extends AbstractPage implements Page {
private JButton previous = new JButton("< Previous");
public ThirdPage(String name, NavigationController controller) {
super(name, controller);
JLabel label = new JLabel("Third page");
label.setHorizontalAlignment(JLabel.CENTER);
add(label);
insertButton(previous);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == previous) {
getNavigationController().previousPage();
}
}
}
}
Example #2 - central controller example
This example separates the controller from the pages, so that the buttons are not part of the pages themselves. This frees up the pages/views to be anything you need them to be
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class CardLayoutExample2 {
public static void main(String[] args) {
new CardLayoutExample2();
}
public CardLayoutExample2() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new WizardPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class WizardPane extends JPanel {
private List<String> pages;
private String currentPage;
private JButton first;
private JButton previous;
private JButton next;
private JButton last;
private CardLayout cardLayout;
private JPanel contentPane;
public WizardPane() {
setLayout(new BorderLayout());
cardLayout = new CardLayout();
pages = new ArrayList<>(3);
contentPane = new JPanel(cardLayout);
contentPane.setBorder(new EmptyBorder(4, 4, 4, 4));
pages.add("Page01");
pages.add("Page02");
pages.add("Page03");
contentPane.add(new FirstPage(), "Page01");
contentPane.add(new SecondPage(), "Page02");
contentPane.add(new ThirdPage(), "Page03");
JPanel actionsPane = new JPanel(new GridBagLayout());
actionsPane.setBorder(new EmptyBorder(4, 4, 4, 4));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
actionsPane.add((first = new JButton("<< First")), gbc);
gbc.gridx++;
gbc.weightx = 1;
gbc.anchor = GridBagConstraints.WEST;
actionsPane.add((previous = new JButton("< Previous")), gbc);
gbc.gridx++;
gbc.anchor = GridBagConstraints.EAST;
actionsPane.add((next = new JButton("Next >")), gbc);
gbc.gridx++;
gbc.weightx = 0;
actionsPane.add((last = new JButton("Last >>")), gbc);
add(contentPane);
add(actionsPane, BorderLayout.SOUTH);
NavigationHandler handler = new NavigationHandler();
first.addActionListener(handler);
previous.addActionListener(handler);
next.addActionListener(handler);
last.addActionListener(handler);
gotoFirstPage();
}
protected void gotoFirstPage() {
currentPage = pages.get(0);
cardLayout.show(contentPane, currentPage);
}
protected void gotoPreviousPage() {
int index = pages.indexOf(currentPage);
index--;
if (index >= 0) {
currentPage = pages.get(index);
cardLayout.show(contentPane, currentPage);
}
}
protected void gotoNextPage() {
int index = pages.indexOf(currentPage);
index++;
if (index < pages.size()) {
currentPage = pages.get(index);
cardLayout.show(contentPane, currentPage);
}
}
protected void gotoLastPage() {
currentPage = pages.get(pages.size() - 1);
cardLayout.show(contentPane, currentPage);
}
protected class NavigationHandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == first) {
gotoFirstPage();
} else if (e.getSource() == previous) {
gotoPreviousPage();
} else if (e.getSource() == next) {
gotoNextPage();
} else if (e.getSource() == last) {
gotoLastPage();
}
}
}
}
public class FirstPage extends JPanel {
public FirstPage() {
setLayout(new BorderLayout());
JLabel label = new JLabel("Page One");
label.setHorizontalAlignment(JLabel.CENTER);
add(label);
}
}
public class SecondPage extends JPanel {
public SecondPage() {
setLayout(new BorderLayout());
JLabel label = new JLabel("Page Two");
label.setHorizontalAlignment(JLabel.CENTER);
add(label);
}
}
public class ThirdPage extends JPanel {
public ThirdPage() {
setLayout(new BorderLayout());
JLabel label = new JLabel("Page Three");
label.setHorizontalAlignment(JLabel.CENTER);
add(label);
}
}
}
Example #3 - Model based
Or you could use a model based approach (which is probably more preferable), which defines the order in which components are displayed. For example

JPanel in JApplet

I need to have one JPanel opened on start. I have a button on that one to open to another JPanel which contains a button to bring me back. How do i write action listeners for those buttons. I have searched extensively. Do I need a JFrame? All examples seem to have it.
Regardless of which approach you might take, the basic idea is the same. You need to know where to go based on where you are...
To this end, this simple example uses a simple navigation interface to provide movement control for the panels and a List to maintain the order of the components.
You could just as simply use a queue of some kind, pushing the next panel onto it and popping the last panel of it as you switched views.
This is a quick and simple example of CardLayout
import java.awt.CardLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class SwitchPanel extends JApplet{
private String currentView;
private List<String> viewNames;
#Override
public void init() {
final CardLayout cardLayout = new CardLayout();
setLayout(cardLayout);
Navigator navi = new Navigator() {
#Override
public void next() {
int index = viewNames.indexOf(currentView);
if (index > -1) {
index++;
if (index < viewNames.size()) {
currentView = viewNames.get(index);
cardLayout.show(getContentPane(), currentView);
}
}
}
#Override
public void previous() {
int index = viewNames.indexOf(currentView);
if (index > -1) {
index--;
if (index >= 0) {
currentView = viewNames.get(index);
cardLayout.show(getContentPane(), currentView);
}
}
}
};
MainPane mainPane = new MainPane(navi);
LastPane lastPane = new LastPane(navi);
viewNames = new ArrayList<>(2);
viewNames.add("main");
viewNames.add("last");
add(mainPane, "main");
add(lastPane, "last");
currentView = "main";
cardLayout.show(getContentPane(), "main");
}
public interface Navigator {
public void next();
public void previous();
}
public class MainPane extends JPanel {
private Navigator navigator;
public MainPane(Navigator navi) {
this.navigator = navi;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JButton btn = new JButton("Next >");
add(new JLabel("Main"), gbc);
add(btn, gbc);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
navigator.next();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class LastPane extends JPanel {
private Navigator navigator;
public LastPane(Navigator navi) {
this.navigator = navi;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JButton btn = new JButton("< Previous");
add(new JLabel("Last"), gbc);
add(btn, gbc);
btn.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
navigator.previous();
}
});
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
}

Multiple JFrames, or JDialogs

From a variety of resources (this website, a book, a friend) I have managed to make a JFrame(JFrame1) that responds to a button. It makes another JFrame (JFrame2), and changes the JFrame.setVisible() to false.
What I'm trying to do is make it so that when a declared Back button is pressed, it closes JFrame2 and sets JFrame1 visibility to true. That's all fine, but when I do JFrame2.setVisiblity(false), JFrame2 is still visible. I've tried dispose(); but that doesn't work either.
I'm also wondering, since I've read on stackoverflow, that creating multiple JFrames is bad programming. So should I use JDialogs instead?
I am trying to display a bunch of information, and allow you to interact with the GUI to navigate around the information. The information would be arranged by alphabetical order.
Also, I'm not sure how to post code on here, so if you need to see what I currently have, just tell me how to post code :D
You are better of using a single frame, using something like JPanels to hold you UI components. This way you can simply switch it the panels as you need, possibly with something like CardLyout
By moving your UI to panels, you are also decoupling your code, giving your more flexibility and reuse potential.
Updated with basic example
This basically uses a simple model to change out different views. You could use a different style of model that listens to changes to the views and then makes choices on there behalf (which would generally be my preferred method), it depends on what you want to do...
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class CardLayoutDemo {
public static void main(String[] args) {
new CardLayoutDemo();
}
public CardLayoutDemo() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new MasterPane());
frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GameModel {
private JPanel view;
private JPanel lastView;
private JPanel currentView;
private WelcomePane welcomePane;
private GamePane gamePane;
private SettingsPane settingsPane;
public GameModel(JPanel view) {
this.view = view;
welcomePane = new WelcomePane(this);
gamePane = new GamePane(this);
settingsPane = new SettingsPane(this);
}
public void welcome() {
lastView = currentView;
view.removeAll();
view.add(welcomePane);
view.revalidate();
view.repaint();
currentView = welcomePane;
}
public void newGame() {
lastView = currentView;
view.removeAll();
view.add(gamePane);
view.revalidate();
view.repaint();
currentView = gamePane;
}
public void settings() {
lastView = currentView;
view.removeAll();
view.add(settingsPane);
view.revalidate();
view.repaint();
currentView = settingsPane;
}
public void back() {
if (lastView != null) {
view.removeAll();
view.add(lastView);
view.revalidate();
view.repaint();
currentView = lastView;
lastView = null;
}
}
}
public class MasterPane extends JPanel {
public MasterPane() {
setLayout(new BorderLayout());
GameModel model = new GameModel(this);
model.welcome();
}
}
public class WelcomePane extends JPanel {
private GameModel model;
public WelcomePane(GameModel gameModel) {
this.model = gameModel;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
JButton btnStart = new JButton("New Game");
JButton btnSettings = new JButton("Settings");
add(new JLabel("Welcome"), gbc);
add(btnStart, gbc);
add(btnSettings, gbc);
btnSettings.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
model.settings();
}
});
btnStart.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
model.newGame();
}
});
}
}
public class SettingsPane extends JPanel {
private GameModel model;
public SettingsPane(GameModel gameModel) {
this.model = gameModel;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
add(new JLabel("Go ahead, make some changes..."), gbc);
JButton back = new JButton("Back");
back.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
model.back();
}
});
add(back, gbc);
}
}
public class GamePane extends JPanel {
private GameModel model;
public GamePane(GameModel model) {
this.model = model;
setLayout(new GridBagLayout());
add(new JLabel("All your base are belong to us"));
}
}
}

Categories