I have 2 panels in my frame, 1 is for buttons (I want to use radioButton, but for now it is easier using buttons) and the other one is for the card layout panel. My plan is to shuffle the chad when I press specific button. Like the move button will show me the move panel card. Move panel card has x0 label and text field, Line panel card has x0 and x1 both label and text field.
There are 2 classes, 1 is for the buttonpanel = Buttons
the other one is for the cards = PanelMiddle
Here's my code:
public class PanelMiddle{
JPanel controlPanel = new JPanel();
CardLayout cl = new CardLayout();
JPanel movePanel = new JPanel();
JPanel linePanel = new JPanel();
JLabel x0Label = new JLabel("x0");
JTextField x0TextField = new JTextField(3);
JLabel x1Label = new JLabel("x1");
JTextField x1TextField = new JTextField(3);
public PanelMiddle(){
controlPanel.setLayout(cl);
//move panel
movePanel.setLayout(new GridLayout (1,2));
movePanel.add(x0Label);
movePanel.add(x0TextField);
controlPanel.add(movePanel,"Move"); //add the keyword Move to show the move card
//line panel
linePanel.setLayout(new GridLayout (2,2));
//linePanel.add(x0Label);
linePanel.add(x1Label);
//linePanel.add(x0TextField);
linePanel.add(x1TextField);
controlPanel.add(linePanel,"Line"); // add the keyword Line to show the line card
}
}
In the other class I have:
public class Buttons extends PanelMiddle{
JPanel buttonPanel = new JPanel();
JButton moveB = new JButton ("Move");
JButton lineB = new JButton ("Line");
public Buttons(){
buttonPanel.setLayout(new GridLayout (2,1));
buttonPanel.add(moveB);
buttonPanel.add(lineB);
action();
}
public void action(){
moveB.addActionListener((e) -> {
cl.show(controlPanel,"Move");
});
lineB.addActionListener((e) -> { cl.show(controlPanel,"Line");});
}
}
The result that I got is weird. It doesn't show fully my panel. But when I tried commenting all the line panel, it works. Does someone have a fix here?
NB: Im sorry I dont know how to edit the text here so its a little bit messy.
edit 1 : as guleryuz says, I commented out the x0Label and x0TextField from the line panel
in swing component hierarchy a component can only be added to one container, you are adding x0Label and x0TextField two both panels. so when you add x0Labe two second panel (linePanel) it will be removed from movePanel (same case for x0TextField) so movePanel becomes empty.
more details here
Related
I just have a small problem with my code; I'm currently using a cardlayout wherein I currently have 3 buttons. 1(on the initial panel) adds JLabels to the initial panel,another(also on the initial panel) switches to the second panel which just contains the 3rd button that returns to the initial panel. My problem is that clicking the buttons for swapping between panels also triggers the first button which creates JLabels.
Here is part of my code:
actionListener al = new actionListener();
actionListener al2 = new actionListener();
actionListener al3 = new actionListener();
adddeck.addActionListener(al);//creates JLabels on panel1
addcardbutton.addActionListener(al2);//goes to panel2
goback.addActionListener(al3)//returns to panel1
Then the actionlistener part:
public class actionListener implements ActionListener{
public void actionPerformed(ActionEvent event) {
JButton src = (JButton) event.getSource();
if(event.getSource()==adddeck)
decklist.add(new Deck(newdeck.getText()));
//panel for label/buttons
JPanel deckpanel;
deckpanel= new JPanel();
deckpanel.setLayout(new GridLayout(1,2));
//label with new deck name
JLabel decklabel;
decklabel = new JLabel(newdeck.getText());
deckpanel.add(decklabel);
deckpanel.revalidate();
//label with # of cards
JLabel cardamt;
cardamt = new JLabel(i +"cards");
deckpanel.add(cardamt);
deckpanel.revalidate();
//add panel
initial.add(deckpanel);
initial.revalidate();
if(event.getSource()==addcardbutton)
cardLayout.show(contentPanel,"adding");
if(event.getSource()==goback)
cardLayout.show(contentPanel,"initial");
You have not used curly braces ({) for the if statements. When an if statement does not have curly braces, only the line just after if is included in the if block.
For example your code
if(event.getSource()==adddeck)
decklist.add(new Deck(newdeck.getText()));
//panel for label/buttons
JPanel deckpanel;
deckpanel= new JPanel();
deckpanel.setLayout(new GridLayout(1,2));
//label with new deck name
JLabel decklabel;
decklabel = new JLabel(newdeck.getText());
deckpanel.add(decklabel);
deckpanel.revalidate();
is equivalent to:
if(event.getSource()==adddeck) {
decklist.add(new Deck(newdeck.getText()));
}
//panel for label/buttons
JPanel deckpanel;
deckpanel= new JPanel();
deckpanel.setLayout(new GridLayout(1,2));
//label with new deck name
JLabel decklabel;
decklabel = new JLabel(newdeck.getText());
deckpanel.add(decklabel);
deckpanel.revalidate();
So, the code starts from line //panel for label/buttons is always executed regardless of the button you click.
I have two JPanels that sit on top of one another. The 'top' panel holds many widgets (JButtons, JTextFields, etc.). One of the buttons will initiate an action to display a number of images.
These images are displayed on the other JPanel. So, when this button is clicked, I want to hide the control panel and display the images panel. Sounds pretty simple.
Here is the code (I've omitted a lot of stuff that I don't think is relevant). In the constructor, if I switch which panel is visible when the app launches, it looks fine either way. When I click the button, I should go from my dark gray control panel to my blue images panel. Except that what happens is my dark gray control panel becomes an empty white panel. Any ideas?
public GUI() {
JFrame frame = new JFrame();
...
JPanel imagesPanel = new ImagesPanel();
imagesPanel.setBackground(Color.BLUE);
imagesPanel.setVisible(false);
frame.getContentPane().add(imagesPanel, BorderLayout.CENTER);
// make a JPanel to hold all of the buttons and text fields
JPanel imagesPanel = new ImagesPanel();
controlPanel.setBackground(Color.DARK_GRAY);
controlPanel.setVisible(true);
frame.getContentPane().add(controlPanel, BorderLayout.CENTER);
...
JButton btnDisplayImages = new JButton("Display Images");
btnDisplayImages.setPreferredSize(standardButtonSize);
btnDisplayImages.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
imagesPanel.setVisible(true);
controlPanel.setVisible(false);
frame.repaint();
frame.setVisible(true);
}
});
// button added to control panel
...
}
Use CardLayout. (docs.oracle.com/javase/tutorial/uiswing/layout/card.html)
final String IMAGES_PANEL = "Images Panel";
final String CONTROL_PANEL = "Control Panel";
CardLayout cardLayout;
JPanel cards;
//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".
cardLayout = new CardLayout();
cards = new JPanel(cardLayout);
cards.add(card1, IMAGES_PANEL);
cards.add(card2, CONTROL_PANEL);
...
//Show images panel
cardLayout.show(cards,IMAGES_PANEL);
...
//Show control panel
cardLayout.show(cards, CONTROL_PANEL);
I've got a new requirement to change my display.
Currently I have a row of 3 radio buttons sitting above a Panel with a card layout. The buttons CONTROL which card of the Card Layout Panel is displayed. But this, it seems, wastes valuable screen real estate.
The row of buttons can easily be transformed to a column of buttons using a GridLayout(4,1) on the panel that owns them and their title label. This panel could then theoretically be placed in the upper left corner of the each of the cards displayed in the card layout panel, and the top row of each card could be moved up to the right of the button panel, allowing more space for what has to come below.
But what shall be the containment model for this? In this variant, the button panel must appear on each card. Who owns it? Logically it needs to be owned by the parent panel on which all this sits, but it won't display on the cards, which will cover it over - unless I could
add the button panel to each card at the moment of its display, which would probably be messy and maybe cause flicker.
make the top left corner of each card be transparent, allowing it to show the upper left button panel owned by its parent. But how would I do that?
Other solutions?
Maybe
Have two card layout panels controlled by the radio buttons. The upper right one that contains all but the the button panel and the lower component that sits below both.
It sounds like you could use a JLayeredPane as the parent component of both, the panel containing the radio buttons and the card panel.
JLayeredPane allows its child components to overlap, each child belonging to a layer.
To specify the layer, you can pass an Integer constant into the JLayeredPane's add(Component, Object) method as the constraint argument. The integer constants are defined in the JLayeredPane class itself. You can use JLayeredPane.DEFAULT_LAYER for the card panel and JLayeredPane.PALETTE_LAYER for the radio button panel.
Having set the layer, you'll still have to position the two panels correctly in x,y space. I would recommend just overriding the JLayeredPane's doLayout() method with something like this (haven't tested):
public void doLayout()
{
cardPanel.setBounds( new Rectangle( getSize() ));
radioButtonPanel.setBounds( new Rectangle( radtioButtonPanel.getPreferredSize() ));
}
You may be able to use OverlayLayout to display the control panel in the top-left of your card panel.
I would forget the transparency idea. Just put the options as a list to the left of (or right of, or over/under) the card panel. I would definitely NOT put the panel of controls on the CardPanel itself. It should be outside.
The list of selections could be radios, buttons, or in this example, a JList of items that can grow w/o messing up the layout. For example:
/*
* CardLayoutDemo.java
*/
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
#SuppressWarnings("unchecked")
public class CardLayoutDemo implements Runnable
{
final static String CARD1 = "Gray Panel";
final static String CARD2 = "Blue Panel";
final static String CARD3 = "Green Panel";
JPanel cards;
CardLayout cl;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new CardLayoutDemo());
}
public void run()
{
final JList jList = new JList(new String[]{CARD1, CARD2, CARD3});
jList.setPrototypeCellValue("XXXXXXXXXXXX");
jList.setVisibleRowCount(5);
jList.setSelectedIndex(0);
jList.addListSelectionListener(new ListSelectionListener()
{
#Override
public void valueChanged(ListSelectionEvent e)
{
String name = jList.getSelectedValue().toString();
cl.show(cards, name);
}
});
JScrollPane scroll = new JScrollPane(jList);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
Dimension dim = new Dimension(300, 300);
JPanel card1 = new JPanel();
card1.setBackground(Color.GRAY);
card1.setPreferredSize(dim);
JPanel card2 = new JPanel();
card2.setBackground(Color.BLUE);
card2.setPreferredSize(dim);
JPanel card3 = new JPanel();
card3.setBackground(Color.GREEN);
card3.setPreferredSize(dim);
cl = new CardLayout();
cards = new JPanel(cl);
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(scroll, BorderLayout.WEST);
f.add(cards, BorderLayout.CENTER);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
If you wanted a label for the selections, just make a "selection panel" that contains the JLabel and the JScrollPane (or use your grid of buttons panel), and put it in Borderlayout.WEST (instead of the adding the JScrollPane directly).
Also, look into JTabbedPane as an alternative.
I have a border layout and I want to add a grid layout to the center section. However, I can't declare a grid and then add my center border. How can I do this?
public Liability_Calculator(String s)
{
super(s);
setSize(325,200);
c = getContentPane();
c.setLayout(new BorderLayout());
//the top label
total = new JLabel("Total monthly liabilities ", JLabel.CENTER);
c.add(total, BorderLayout.NORTH);
//the grid
GridLayout grid = new GridLayout(2,2);
text_field1 = new JTextField(7);
//I GET AN ERROR HERE!!!!!!!
grid.add(text_field1);
//AND ERROR HERE!!!!!!!!!!!!!
c.add(grid, BorderLayout.CENTER);
setVisible(true);
}
You're trying to add a component to a layout, and that simply cannot be done. Instead use a JPanel, give it a GridLayout, and then add the component to the JPanel (acting as the "container" here).
In general, you will want to nest JPanels with each using the best layout for the GUI, here the inner JPanel using GridLayout and the outer one using BorderLayout. Then you simply add the inner JPanel to the outer one (here your contentPane) in the BorderLayout.CENTER position.
Providing code visualization derived from Hovercraft's answer:
Display class:
public class Display extends JFrame {
JPanel gridHolder = new JPanel(); // panel to store the grid
private GridLayout buttonsGrid; // space containing a buttons
private JButton myButtons[]; // grid is to be filled with these buttons
private BorderLayout mainGUILayout; // main gui layout
private Container mainGuiContainer;
public Display() {
mainGUILayout = new BorderLayout(5,5); // Border layout option
mainGuiContainer = getContentPane(); // getting content pane
mainGuiContainer.setLayout(mainFrameLayout); // setting main layout
buttonsGrid = new GridLayout(4, 1, 5, 5); // 4 buttons one over the other
myButtons = new JButton[4]; // player's hand represented with buttons
gridHolder.setLayout(buttonsGrid);
for (int x = 0; x < 4; x++) {
myButtons[x] = new JButton (" ");
gridHolder.add(myButtons[x]); }
add(gridHolder, BorderLayout.WEST);
setVisible(true); } }
MainGUILaunch class:
public class MainGUILaunch {
public static void main (String args[]) {
Display myApplication = new Display();
myApplication.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myApplication.setSize(1024, 1024);
myApplication.setVisible(true); // displaying application }
} // End of MainGUILaunch
I have a log in GUI that when i click a button, it gets text from the username and password, and if it is correct, it moves on to a new panel. i have the panel called optionPanel and i want the button to go to it specifically. all of the panels are set up as cards, so i can switch between them smoothly. I know how to make the button move to the next panel/card in the sequence, but i don't know how to make it go to the panel/card called optionPanel.
EDIT:
I dont know if im being very clear, but in my head, this makes perfect sense. please tell me how i can be more clear so i can get an answer.
THANKS
I think what you want is:
// Create the panels
JPanel loginPanel = new JPanel();
JPanel someOtherPanel1 = new JPanel();
JPanel someOtherPanel2 = new JPanel();
JPanel optionPanel = new JPanel();
JPanel someOtherPanel3 = new JPanel();
// Add them to a card layout
JPanel cards = new JPanel(new CardLayout());
cards.add(loginPanel, "loginPanel");
cards.add(someOtherPanel1, "someOtherPanel1");
cards.add(someOtherPanel2, "someOtherPanel2");
cards.add(optionPanel, "optionPanel");
cards.add(someOtherPanel3, "someOtherPanel3");
...
// Switch to the optionPanel
cards.getLayout().show(cards, "optionPanel");
don't you just need
cardLayout.show(cards, "optionPanel");
or am i missing something completely non-obvious?