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
Related
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
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.
No matter what I do, I can't get the JFrame to show anything. Its just blank. I added the buttons starter and tutorialer to the JPanel game and added that JPanel to the the JPanel cards which I set to a cardLayout.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class layouter extends JFrame {
public static void main (String[]args){
layouter x = new layouter();
}
public layouter(){
setSize(600,600);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
Pan p = new Pan();
setContentPane(p);
setVisible(true);
}
}
class Pan extends JPanel{
JButton starter;
JButton tutorialer;
JPanel start;
JPanel tutorial;
JPanel game;
JPanel cards;
CardLayout cl;
Pan(){
starter = new JButton("start");
tutorialer = new JButton("tutorial");
start = new JPanel();
tutorial = new JPanel();
game = new JPanel();
cards = new JPanel( new CardLayout());
cl= (CardLayout)(cards.getLayout());
game.setLayout(null);
starter.setBounds(150,150,100,50);
tutorialer.setBounds(150,200,100,50);
game.add(starter);
game.add(tutorialer);
cards.add(game,"game");
add(cards);
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
cl.show(cards,"game");
System.out.println("hello");
}
}
game.setLayout(null); <-- This is going to cause you issues as anything your add to this container will no longer be automatically laid out. Components by default have a size and position of 0x0
Make use of an appropriate layout manager. See Laying Out Components Within a Container for more details.
If you add any more containers to games, you may need to "show" the default view you want to been shown first
cl.show(cards, "game");
Trying to change the look of a JOptionPane while its open, depending on which radiobutton the user clicks. What am I doing wrong? It works perfect if I for example add a button and move a JLabel from side to side of the window.
import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import static javax.swing.JOptionPane.*;
public class ChangePanel extends JFrame{
private JButton click = new JButton("CLICK ME!");
ChangePanel(){
add(click, BorderLayout.SOUTH);
click.addActionListener(new ButtonListen());
setVisible(true);
setSize(300,100);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public class ButtonListen implements ActionListener{
public void actionPerformed(ActionEvent e){
PopUpPanel pop = new PopUpPanel();
showConfirmDialog(ChangePanel.this, pop, "Changeable", OK_CANCEL_OPTION);
}
}
//Send this as Parameter to the ConfirmDialog
public class PopUpPanel extends JPanel implements ActionListener{
JRadioButton jewelry = new JRadioButton("Jewelry");
JRadioButton shares = new JRadioButton("Shares");
JRadioButton machine = new JRadioButton("Machine");
PopUpPanel(){
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
ButtonGroup bg = new ButtonGroup();
JPanel north = new JPanel();
bg.add(jewelry);
jewelry.addActionListener(this);
bg.add(shares);
shares.addActionListener(this);
bg.add(machine);
machine.addActionListener(this);
north.add(jewelry);
north.add(shares);
north.add(machine);
add(north);
}
//Listener for RadioButtons
public void actionPerformed(ActionEvent e){
JTextField info1Txt = new JTextField(12);
JTextField info2Txt = new JTextField(12);
JTextField info3Txt = new JTextField(3);;
JRadioButton b = (JRadioButton)e.getSource();
if(b.getText().equals("Jewelry")){
//Dummy test text
System.out.println("Jewelry");
JPanel info1 = new JPanel();
info1.add(new JLabel("info1:"));
info1.add(info1Txt);
add(info1);
JPanel info2 = new JPanel();
info2.add(new JLabel("info2:"));
info2.add(info2Txt);
add(info2);
JPanel info3 = new JPanel();
info3.add(new JLabel("info3:"));
info3.add(info3Txt);
add(info3);
validate();
repaint();
}else if(b.getText().equals("Shares")){
//Dummy test text
System.out.println("Shares");
}else
//Dummy test text
System.out.println("Machine");
}
}
public static void main(String[] args){
new ChangePanel();
}
}
As you are working with BoxLayout, you should provide size hints to the PopUpPanel panel, which you haven't given.
When a BoxLayout lays out components from top to bottom, it tries to size each component at the component's preferred height. If the vertical space of the layout does not match the sum of the preferred heights, then BoxLayout tries to resize the components to fill the space. The components either grow or shrink to fill the space, with BoxLayout honoring the minimum and maximum sizes of each of the components.
check out the official tutorial page discussion: BoxLayout Feature
Call revalidate() and repaint() on the container after removing or adding components to it. So if you change the following lines:
validate();
repaint();
to:
revalidate();
repaint();
The content should appear. Though, it will not fit the original size of the JOptionPane. You can override PopUpPanel.getPreferredSize() to return desired size so that JOptionPane is packed properly, ie:
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
You can also use JDialog instead of JOptionPane.
Also, consider using CardLayout instead of swapping components manually. Check How to Use CardLayout for examples.
Why not just use setPreferredSize(new Dimension(300, 300)) in PopUpPanel constructor? Works fine for me. Good eye on revalidate and repaint.
We are working on a project where we encountered a problem with including more than two Panels on the same JFrame .What we want is one Panel above the other.
Can the community help give an example of ho to implement this or refer me to a good tutorial or guide related to our Java Swing needs?
Assuming you want two panels added to a single frame:
Set a layout for your parent JFrame and add the two panels. Something like the following
JFrame frame = new JFrame();
//frame.setLayout(); - Set any layout here, default will be the form layout
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
frame.add(panel1);
frame.add(panel2);
Assuming you want to add one panel over the other
JFrame frame = new JFrame();
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
frame.add(panel1);
panel1.add(panel2);
There is no limit on the number of panels to be added on the JFrame. You should understand that they all are containers when seen on a higher level.
if you want each of the frames/panels the same size, use the GridLayout, with a grid of 1(column) and 2(rows)
Frame myFrame;
GridLayout myLayout = new GridLayout(2,1);
myFrame.setLayout(myLayout);
Panel p1;
Panel p2;
myFrame.add(p1);
myFrame.add(p2);
if the panels are different size use the BorderLayout.... set the upper frame to "North" and the lower one to "South" or "Center"
Frame myFrame;
myFrame.setLayout(new BorderLayout() );
Panel p1;
Panel p2;
myFrame.add(p1, BorderLayout.NORTH);
myFrame.add(p2, BorderLayout.CENTER);
//you can also use card Layout, that enables you to add multiple card-panels on Main panel.
CardLayout cl;
JPanel main,one,two,three;
JButton button1,button2;
cl = new CardLayout();
main.setLayout(cl);
main.add(one,"1");
main.add(two,"2");
main.add(three,"3");
cl.show(main,"1");
public void actionPerformed(ActionEvent e){
if(e.getSource() == button1)
cl.show(main,"2");
else if(e.getSource() == button2)
cl.show(main,"3");
}