Java Swing change panel when a button is pressed from different class - java

I am writing a program in Java with Java Swing. I have a class, which is a custom JPanel (my class extends JPanel), which is a log in page. The panel contains a button called "Enter".
When I create my main JFrame, I add the Log in Panel in it. When the button "Enter" is pressed I want to remove the Log In panel and proceed to the next panel.
So how can I make my frame understand when the button "Enter" from the Log In panel is pressed (they are in different classes), so that it proceeds to the next page?

To be able to switch beetween JPanels enclose them in CardLayout:
JPanel cards;
final static String BUTTONPANEL = "Card with JButtons";
final static String TEXTPANEL = "Card with JTextField";
//Where the components controlled by the CardLayout are initialized:
//Create the "cards".
JPanel card1 = new JPanel();
...
JPanel card2 = new JPanel();
...
//Create the panel that contains the "cards".
cards = new JPanel(new CardLayout());
cards.add(card1, BUTTONPANEL);
cards.add(card2, TEXTPANEL);
You should add ActonListener to the "Enter" button:
JButton enterButton = ...
enterButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
CardLayout cl = (CardLayout)// your reference to the CardLayout here eg. yourJFrame.getContentPane().getLayout();
cl.show(cards, "The name of panel to show, you gave it with the add operation on cardLayout eg. BUTTONPANEL OR TEXTPANEL");
}
});

Related

How to add container to a frame?

I am trying to make a minesweeper that has a different space for a smiley icon that we can click and the buttons which we have to click to play.
public final class testFrame extends JFrame implements MouseListener, ActionListener {
private JFrame screen = null;
private JPanel composite = new JPanel();
public testFrame() {
screen = new JFrame();
screen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
screen.setVisible(true);
screen.setResizable(true);
composite.setLayout(new BorderLayout());
//this button is not showing also
JButton button = new JButton("Text goes here");
composite.add(button);
Container cp = screen.getContentPane(); // JFrame's content-pane
cp.setLayout(new GridLayout(5, 5, 2, 2)); // in 10x10 GridLayout
//codes to add buttons
}
So here I am trying to add the container cp to the screen. But it opened
two screen
Sorry if this seems like minor things but I am really new to this java GUI so please help me.
EDIT:
I removed the extends JFrame and used the screen instead. It kinda works but I can't seem to put the container cp to a panel. The requirement is that I have to use container cp. So I cannot change. Thank you
public final class TestFrame implements MouseListener, ActionListener {
private JFrame screen = null;
private JPanel composite = new JPanel();
private JPanel topPanel = new JPanel();
public TestFrame() {
screen = new JFrame("TestFrame");
screen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
screen.setVisible(true);
topPanel.setLayout(new BorderLayout());
//composite.setLayout(new BorderLayout());
//button in topPanel
JButton button = new JButton("Text goes here");
topPanel.add(button, BorderLayout.PAGE_START);
//Content Pane
Container cp = screen.getContentPane();// JFrame's content-pane
cp.setLayout(new GridLayout(5, 5, 2, 2)); // in 10x10 GridLayout
//composite.add(cp, BorderLayout.CENTER);
screen.add(topPanel);
// screen.add(composite);
}
Now it looks like
this
There are a few things.
You are extending JFrame as well as using it as an attribute of the same class so you can ether use this instead of screen or you remove the extends JFrame as it is redundant and not needed
To answer your question. A JFrame contains a Panel called ContentPane this pane is were you add you panels to (you already did the layout thing right). So the solution is:
cp.add(composite);
You've got too many JFrames, the testFrame class which extends JFrame (and which should be re-named TestFrame to comply with Java naming conventions) and the screen variable. Use only one.
You can and should nest JPanels to achieve your desired result. For instance if you want a grid as well as some control buttons, create a JPanel, give it a BorderLayout, put your grid JPanel in the BorderLayout.CENTER postion and a JPanel with control JButtons in a different position, say BorderLayout.PAGE_START

How to make a JPanel display over another JPanel when moved?

I have created a card game which allows the users to move the cards, which are JPanels, on top of each other. However, I noticed that if I attempt to move a card to another cards exact location (ie on top of it), that card will not always be displayed on top of that card.
For example, lets say we have 5 cards, which where built in order.
If move card1 to card2's location, then card1 will appear on top of card2. However, if I tried to move card5 to card3's location, then card5 will appear underneath card3.
How can can I make is so that the last card that I move will be the one on top?
However, I noticed that if I attempt to move a card to another cards exact location (ie on top of it), that card will not always be displayed on top of that card.
This sounds related to the Z-Ordering of components. Basically the default behaviour for Swing is that the last component added to a panel is painted first.
So you need to change the Z-Order when you add the card on the panel. You are probably using code like:
panel.add( card );
The easy solution is to use:
panel.add(0, card);
Or, when you handle the mousePressed() event when you click on the card your would use:
Component child = event.getComponent();
Component parent = child.getParent();
parent.setComponentZOrder(child, 0);
You may also want to look at the Overlap Layout which explains Z-Ordering a little more and provides a layout manager that can allow you to stack cards.
For this purpose card layout is your friend.
How to use card layout https://docs.oracle.com/javase/tutorial/uiswing/layout/card.html
Example uses:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CardLayoutDemo implements ItemListener {
JPanel cards; //a panel that uses CardLayout
final static String BUTTONPANEL = "Card with JButtons";
final static String TEXTPANEL = "Card with JTextField";
public void addComponentToPane(Container pane) {
//Put the JComboBox in a JPanel to get a nicer look.
JPanel comboBoxPane = new JPanel(); //use FlowLayout
String comboBoxItems[] = { BUTTONPANEL, TEXTPANEL };
JComboBox cb = new JComboBox(comboBoxItems);
cb.setEditable(false);
cb.addItemListener(this);
comboBoxPane.add(cb);
//Create the "cards".
JPanel card1 = new JPanel();
card1.add(new JButton("Button 1"));
card1.add(new JButton("Button 2"));
card1.add(new JButton("Button 3"));
JPanel card2 = new JPanel();
card2.add(new JTextField("TextField", 20));
//Create the panel that contains the "cards".
cards = new JPanel(new CardLayout());
cards.add(card1, BUTTONPANEL);
cards.add(card2, TEXTPANEL);
pane.add(comboBoxPane, BorderLayout.PAGE_START);
pane.add(cards, BorderLayout.CENTER);
}
public void itemStateChanged(ItemEvent evt) {
CardLayout cl = (CardLayout)(cards.getLayout());
cl.show(cards, (String)evt.getItem());
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("CardLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create and set up the content pane.
CardLayoutDemo demo = new CardLayoutDemo();
demo.addComponentToPane(frame.getContentPane());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
You can easily modify it to you fulfill your goal.

The function of JPanel

I am working with Swing, trying to learn how to use it. I am doing an excercise in my book where I am supposed to make buttons (JButtons) like the ones a dvd-player has. I am adding no funcionality to the buttons at this point. The program worked just fine when I first ran it. Then I thought that I would expand it by making a second panel (JPanel) with the same buttons. When I run my code however, I just get one set of buttons (not two areas with two sets of buttons).
Have I misunderstood the concept of Panels? I have understood a Panel to be an area (a container) in my frame where I can display different output, and that I can have several panels i one frame.
Here is my code:
import javax.swing.*;
public class Oppgave91 extends JFrame
{
public Oppgave91()
{
super ("We make buttons");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JButton play = new JButton("Play");
JButton stopeject = new JButton("Stop/Eject");
JButton rewind = new JButton("Rewind");
JButton fastforward = new JButton("FastForward");
JButton pause = new JButton("Pause");
JPanel panel = new JPanel();
panel.add(play);
panel.add(stopeject);
panel.add(rewind);
panel.add(fastforward);
panel.add(pause);
JPanel panel2 = new JPanel();
panel2.add(play);
panel2.add(stopeject);
panel2.add(rewind);
panel2.add(fastforward);
panel2.add(pause);
add(panel);
add(panel2);
setVisible(true);
}
public static void main(String[] args)
{
Oppgave91 showbuttons = new Oppgave91();
showbuttons.pack();
}
}
A component can have only 1 parent. See the last line of my code snippet for how it should be done
JPanel panel = new JPanel();
panel.add(play);
panel.add(stopeject);
panel.add(rewind);
panel.add(fastforward);
panel.add(pause);
//right now panel is the parent component of play, stop, eject
JPanel panel2 = new JPanel();
panel2.add(play); //play is now owned by panel2, not panel
panel2.add(stopeject); //stopeject is now owned by panel2, not panel
panel2.add(new JButton("Rewind")); // this is how you should do this

Can't shift focus to unshown CardLayout JPanel

Why can't I shift focus to an unshown JPanel card in a CardLayout?
I'm implementing a CardLayout-based interface that needs to be keyboard navigation friendly. When a user finishes tabbing through all the fields on one card, the user needs to be able to tab to the next card.
I've already implemented a FocusTraversalPolicy that produces the right Component at each point in the process, and a FocusAdapter to pop up any cards newly tabbed to, but something is eating the messages and preventing focus change.
I can uncleanly pass the CardLayout to the FocusTraversalPolicy to change the card— though any of its functions are called several times in Swing's many threads and leads to strange behavior. Besides, that way's just dirty.
I do not want to use key bindings b/c that would require reimplementing all of the focus work Java already does for me, and is also really unclean.
Basically: Java dislikes shifting focus to unshown cards in CardLayouts— how can I override this?
I want to keep the program compartmentalized, as it runs in distinct steps.
This does not prevent you from creating a long scrolling form?
You can still create individual panels the way you are doing now. Then instead of adding these panels to a CardLayout where you need to swap panels, you can add the panels to a panel using a BoxLayout (or GridBagLayout).
This would even give more flexibility since each panel can be of a different size without impacting the size of every individual panel.
However, forms do not currently scroll automatically in a JScrollPane, so you may want to check out Scrolling a Form for a class this will do this for you.
It sounds like you have a wizard-like UI. If so, add a "Next" button as the last field on each card.
The action of the Next button would be to flip to the next card as set focus to the first entry field.
The last entry field on each card would transfer focus to the Next button, who could then be "pressed" with a strike of the spacebar when it receives focus (which is the default behavior of a JButton), keeping it keyboard-friendly.
This would alleviate the need for special KeyBindings or FocusTraversalPolicies.
EDIT:
Try this, using FocusListeners for the JTextFields. Tab thorugh the fields and the cards will flip to the next one automatically once you tab out of the last field. You could use ActionListeners instead if you wish:
EDIT 2: Added hack for panels that only have 1 field.
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
public class CardLayoutDemo2 implements Runnable
{
final static String CARD1 = "One";
final static String CARD2 = "Two";
final static String CARD3 = "Three";
JPanel cards;
CardLayout cardLayout;
JTextField tf1, tf2, tf3, tf4, tf5;
JButton dummy;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new CardLayoutDemo2());
}
public void run()
{
tf1 = new JTextField(10);
tf2 = new JTextField(10);
tf2.addFocusListener(new CardFlipper(CARD2));
tf3 = new JTextField(10);
tf4 = new JTextField(10);
tf4.addFocusListener(new CardFlipper(CARD3));
tf5 = new JTextField(10);
tf5.addFocusListener(new CardFlipper(CARD1));
dummy = new JButton()
{
#Override
public Dimension getPreferredSize()
{
return new Dimension(0,0);
}
};
dummy.addFocusListener(new FocusAdapter()
{
#Override
public void focusGained(FocusEvent e)
{
dummy.transferFocus();
}
});
JPanel card1 = new JPanel();
card1.add(new JLabel("One"));
card1.add(tf1);
card1.add(new JLabel("Two"));
card1.add(tf2);
JPanel card2 = new JPanel();
card2.add(new JLabel("Three"));
card2.add(tf3);
card2.add(new JLabel("Four"));
card2.add(tf4);
JPanel card3 = new JPanel();
card3.add(dummy);
card3.add(new JLabel("Five"));
card3.add(tf5);
cardLayout = new CardLayout();
cards = new JPanel(cardLayout);
cards.add(card1, CARD1);
cards.add(card2, CARD2);
cards.add(card3, CARD3);
JFrame f = new JFrame("CardLayout Demo");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(cards, BorderLayout.CENTER);
f.setSize(180, 200);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private class CardFlipper extends FocusAdapter
{
private String nextCard;
CardFlipper(String cardName)
{
this.nextCard = cardName;
}
#Override
public void focusLost(FocusEvent e)
{
cardLayout.show(cards, nextCard);
}
}
}

Switching Panels in Swing

I have a Swing application using Card Layout which basically changes the displayed panel depending on what the user selects from a drop-down menu.
One of my panels has a form. I would need for when the submit buton is pressed for all the inputs to be collected and the Panel to be switched to another one. (This second panel is defined in a separate class) I would also need for all the input to be somehow passed to a method in the new panel.
Any suggestions?
Dario
If you look at the <--s in the following code, each should solve each different question you have in your post. I figured you should know how to make a submit button, so I didn't include that. (Note: this is not running code, just suggestions);
public class MainPanel entends JPanel {
CardLayout layout = new CardLayout(); <-- card layout
JPanel panel = new JPanel(layout); <-- set layout to main panel
NewPanel newPanel = new NewPanel(); <-- you new panel
JPanel p1 = new JPanel(); <-- random panel
JTextField text = new JTextField() <-- text field in form
JButton button = new JButton();
JComboBox cbox = new JComboBox(new String[] {"newPanel", "p1"}); <-- hold panel names
public MainPanel(){
panel.add(newPanel, "newPanel"); <-- name associated with panel
panel.add(p1, "p1");
...
cbox.addAItemListener(new ItemListener(){
public void itemStateChnaged(ItemEvent e){
layout.show(panel, (string).getItem()); <-- show Panel from combobox
}
});
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
String txt = text.getText();
newPanel.printText(txt); <-- Using method from other class
}
});
}
}
public class NewPanel extends JPanel {
public void printText(String text){ <-- method from other class
System.out.println(text);
}
}

Categories

Resources