Dynamic JPanels error - java

I hava CardLayout and want to have changing panels on it. For that I wrote my JFrame Class:
public class GUI_NewList extends javax.swing.JFrame {
CardLayout layout = new CardLayout();
public GUI_NewList() {
initComponents();
this.setLayout(layout);
JPanel paChoose = new Choose();
layout.addLayoutComponent(paChoose, "1");
layout.show(paChoose, "1");
}
The class Choose:
public class Choose extends JPanel {
public Choose() {
setLayout(new GridLayout(3, 1));
JButton btnPractice = new JButton("Practice");
add(btnPractice);
JButton btnNewList = new JButton("Create a new List");
add(btnNewList);
JButton btnEditList = new JButton("Edit a List");
add(btnEditList);
}
}
If I run this I get an error:
Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: wrong parent for CardLayout
Could you please tell me what I have done wrong?

Here is an MCVE that fixes the problem. See code comments for details of the problem(s).
import java.awt.*;
import javax.swing.*;
public class GUI_NewList extends JFrame {
CardLayout layout = new CardLayout();
public GUI_NewList() {
this.setLayout(layout);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
JPanel paChoose = new Choose();
// this only adds it to the layout, not the container.
layout.addLayoutComponent(paChoose, "1");
// this adds it to the container (the content pane)
add(paChoose);
// the container of interest is the content pane.
layout.show(this.getContentPane(), "1");
pack();
setVisible(true);
}
public static void main(String[] args) {
Runnable r = () -> {
new GUI_NewList();
};
SwingUtilities.invokeLater(r);
}
}
class Choose extends JPanel {
public Choose() {
setLayout(new GridLayout(3, 1));
JButton btnPractice = new JButton("Practice");
add(btnPractice);
JButton btnNewList = new JButton("Create a new List");
add(btnNewList);
JButton btnEditList = new JButton("Edit a List");
add(btnEditList);
}
}
Note: There is no good case here for extending either JFrame or JPanel.

Related

Using ActionListener with JMenuBar and CardLayout

I'm testing out a basic java swing GUI setup with a navigation bar and a cardlayout. I'm trying to get the items in the JMenuBar to change what card is shown on the page. I've successfully created the navigation bar and the three cards. I've also added an actionlistener to detect when an item in the JMenuBar is pressed and then eventually change the card. Currently, when trying to retrieve the layout in the actionlistener i receive the error, Cannot Invoke "java.swing.JPanel.getLayout()" because "this.cards" is null. Code is pasted below. Thanks
import java.awt.event.*;
import javax.swing.*;
public class testgui extends JFrame implements Runnable, ActionListener {
JPanel cards; //a panel that uses CardLayout
final static String BUTTONPANEL = "Card 1";
final static String TEXTPANEL = "Card 2";
final static String CARD3 = "Card 3";
JMenu cardList;
JMenuItem card1, card2, card3;
public testgui(String title) {
super(title);
}
private JPanel card1(){
JPanel card1 = new JPanel();
card1.add(new JButton("Button 1"));
card1.add(new JButton("Button 2"));
card1.add(new JButton("Button 3"));
return card1;
}
private JPanel card2(){
JPanel card2 = new JPanel();
card2.add(new JTextField("TextField", 20));
return card2;
}
private JPanel card3(){
JPanel card3 = new JPanel();
JLabel label = new JLabel("Card 3");
card3.add(label);
return card3;
}
private JMenuBar navbar(){
JMenuBar navbar = new JMenuBar();
card1 = new JMenuItem("Card 1");
card2 = new JMenuItem("Card 2");
card3 = new JMenuItem("Card 3");
card1.addActionListener(this);
card2.addActionListener(this);
card3.addActionListener(this);
cardList = new JMenu("Cards");
cardList.add(card1);
cardList.add(card2);
cardList.add(card3);
navbar.add(cardList);
return navbar;
}
public void addComponentToPane(Container pane) {
//Cards are created using separate methods
//Create the panel that contains the "cards".
cards = new JPanel(new CardLayout());
cards.add(card1(), BUTTONPANEL);
cards.add(card2(), TEXTPANEL);
cards.add(card3(), CARD3);
setVisible(true);
//Everything is added to a pane.
// pane.add(comboBoxPane, BorderLayout.PAGE_START);
pane.add(cards, BorderLayout.CENTER);
}
public void actionPerformed(ActionEvent e){
CardLayout layout = (CardLayout) cards.getLayout();
//Why is the above line giving me the error saying that this.cards is null?
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("CardLayoutDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Create the navbar
//Create and set up the content pane.
testgui demo = new testgui("hello");
demo.addComponentToPane(frame.getContentPane());
//Display the window.
frame.setJMenuBar(navbar());
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new testgui("test gui"));
}
public void run() {
setSize(700, 500);
setDefaultCloseOperation(EXIT_ON_CLOSE);
createAndShowGUI();
}
}
You're problem is here:
testgui demo = new testgui("hello");
demo.addComponentToPane(frame.getContentPane());
You're creating one too many JFrame/GUI unnecessarily, setting the JPanel on one and displaying the other (the one with the still null JPanel). The solution is to not do this, to change the above lines to:
// testgui demo = new testgui("hello");
this.addComponentToPane(frame.getContentPane());
or more simply:
addComponentToPane(frame.getContentPane());

Unable to put buttons on frame?

I'm using currently Intellij to create a GUI with 3 buttons on the top of the main frame. I'm fairly new to GUI's and still learning as I go. When I try to run the code I get an error telling me that I cannot have the main method as static but if I remove the static I get an error saying I need it to be static. Is there a way to easily avoid this?
package CA3;
import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent;
public class Main extends JFrame{
public static void main(String[] args) {
// Attach window listener
addWindowListener(new WindowCloser()); // Just in-case it's needed
// Adding first customer panel
JPanel pCustomerL = new JPanel();
pCustomerL.setBounds(0,0,750,750);
pCustomerL.setBackground(Color.BLUE);
// Adding second customer panel
JPanel pCustomerR = new JPanel();
pCustomerR.setBounds(750,0,750,750);
pCustomerR.setBackground(Color.BLACK);
// Adding first invoice panel
JPanel pInvoiceL = new JPanel();
pInvoiceL.setBounds(0,0,750,750);
pInvoiceL.setBackground(Color.BLUE);
// Adding second product panel
JPanel pInvoiceR = new JPanel();
pInvoiceR.setBounds(750,0,750,750);
pInvoiceR.setBackground(Color.BLACK);
// Button Listener
ButtonListener listener = new ButtonListener();
// Adding "Customer" Button
JButton b = new JButton("Customer");
b.addActionListener(listener);
add(b);
b.setBounds(1300,10,150,35);
// Adding "Product" Button
b = new JButton("Product");
b.addActionListener(listener);
add(b);
b.setBounds(1150,10,150,35);
// Adding "Invoice" Button
b = new JButton("Invoice");
b.addActionListener(listener);
add(b);
b.setBounds(1000,10,150,35);
// Adding first product panel
JPanel pProductL = new JPanel();
pProductL.setBounds(0,0,750,750);
//pProductL.setBackground(Color.BLUE);
// Adding second product panel
JPanel pProductR = new JPanel();
pProductR.setBounds(750,0,750,750);
//pProductR.setBackground(Color.BLACK);
// Frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
frame.setSize(1500,750);
frame.setVisible(true);
// Add panels
frame.add(pCustomerL);
frame.add(pCustomerR);
frame.add(pProductL);
frame.add(pProductR);
frame.add(pInvoiceL);
frame.add(pInvoiceR);
// Customer Panel Settings
pCustomerL.setVisible(true);
pCustomerR.setVisible(true);
// Product Settings
pProductL.setVisible(false);
pProductR.setVisible(false);
// Invoice settings
pInvoiceL.setVisible(false);
pInvoiceR.setVisible(false);
}
// Listener for buttons
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent evt) {
String buttonLabel = evt.getActionCommand();
}
}
// Listener for window
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent evt) { System.exit(0);}
}
}
You have to move your code inside the main to another method not-static or you can put it on a Constructor. The errors are because you are using normal methods like addWindowsListener which inherits from JFrame. And you also have to remove:
JFrame frame = new JFrame();
That's not necessary because your class already inherits from JFrame so your code must be like this:
public class Main extends JFrame
{
public Main(){
// Attach window listener
addWindowListener(new WindowCloser()); // Just in-case it's needed
// Adding first customer panel
JPanel pCustomerL = new JPanel();
pCustomerL.setBounds(0,0,750,750);
pCustomerL.setBackground(Color.BLUE);
// Adding second customer panel
JPanel pCustomerR = new JPanel();
pCustomerR.setBounds(750,0,750,750);
pCustomerR.setBackground(Color.BLACK);
// Adding first invoice panel
JPanel pInvoiceL = new JPanel();
pInvoiceL.setBounds(0,0,750,750);
pInvoiceL.setBackground(Color.BLUE);
// Adding second product panel
JPanel pInvoiceR = new JPanel();
pInvoiceR.setBounds(750,0,750,750);
pInvoiceR.setBackground(Color.BLACK);
// Button Listener
ButtonListener listener = new ButtonListener();
// Adding "Customer" Button
JButton b = new JButton("Customer");
b.addActionListener(listener);
add(b);
b.setBounds(1300,10,150,35);
// Adding "Product" Button
b = new JButton("Product");
b.addActionListener(listener);
add(b);
b.setBounds(1150,10,150,35);
// Adding "Invoice" Button
b = new JButton("Invoice");
b.addActionListener(listener);
add(b);
b.setBounds(1000,10,150,35);
// Adding first product panel
JPanel pProductL = new JPanel();
pProductL.setBounds(0,0,750,750);
//pProductL.setBackground(Color.BLUE);
// Adding second product panel
JPanel pProductR = new JPanel();
pProductR.setBounds(750,0,750,750);
//pProductR.setBackground(Color.BLACK);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLayout(null);
this.setSize(1500,750);
this.add(pCustomerL);
this.add(pCustomerR);
this.add(pProductL);
this.add(pProductR);
this.add(pInvoiceL);
this.add(pInvoiceR);
// Customer Panel Settings
pCustomerL.setVisible(true);
pCustomerR.setVisible(true);
// Product Settings
pProductL.setVisible(false);
pProductR.setVisible(false);
// Invoice settings
pInvoiceL.setVisible(false);
pInvoiceR.setVisible(false);
this.setVisible(true);
}
// Listener for buttons
class ButtonListener implements ActionListener {
public void actionPerformed(ActionEvent evt) {
String buttonLabel = evt.getActionCommand();
}
}
// Listener for window
class WindowCloser extends WindowAdapter {
public void windowClosing(WindowEvent evt) { System.exit(0);}
}
public static void main(String[] args) {
new Main();
}
}

Why launching does it random?

When i run this program sometimes shows me all buttons, but sometimes only 2 or 3 or 4 or 5 or even just 1.. why is that??
I really do not get it. There should always be 6 buttons, but it doesnt show them. Is there any logical reason?
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class testnet
{
public static void main (String[] args)
{
JFrame frame = new JFrame("Knjigarna");
frame.setVisible(true);
frame.setSize(800,200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
frame.add(panel);
JButton button1 = new JButton("Prikazi vse");
panel.add(button1);
button1.addActionListener (new Action1());
JButton button2 = new JButton("Prikazi knjigo");
panel.add(button2);
button2.addActionListener (new Action2());
JButton button3 = new JButton("Dodaj knjigo");
panel.add(button3);
button3.addActionListener (new Action3());
JButton button4 = new JButton("Brisi knjigo");
panel.add(button4);
button4.addActionListener (new Action4());
JButton button5 = new JButton("Uredi knjigo");
panel.add(button5);
button5.addActionListener (new Action5());
JButton button6 = new JButton("Izhod");
panel.add(button6);
button6.addActionListener (new Action6());
}
static class Action1 implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
JFrame frame2 = new JFrame("Pikaz vseh knjig");
frame2.setVisible(true);
frame2.setSize(500,800);
JLabel label = new JLabel("Seznam vseh knjig:");
JPanel panel = new JPanel();
JTextField text1=new JTextField("Naslov: ");
JTextField text2=new JTextField("Avtor: ");
frame2.add(panel);
panel.add(label);
panel.add(text1);
panel.add(text2);
}
}
static class Action2 implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
JFrame frame3 = new JFrame("Prikaz knjige");
frame3.setVisible(true);
frame3.setSize(600,300);
JLabel label = new JLabel("Vpisi naslov knjige:");
JPanel panel = new JPanel();
frame3.add(panel);
panel.add(label);
}
}
static class Action3 implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
JFrame frame4 = new JFrame("Dodajanje knjige");
frame4.setVisible(true);
frame4.setSize(600,300);
JLabel label = new JLabel("Vpisi podtke o knjigi");
JPanel panel = new JPanel();
frame4.add(panel);
panel.add(label);
}
}
static class Action4 implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
JFrame frame5 = new JFrame("Brisanje knjige");
frame5.setVisible(true);
frame5.setSize(600,300);
JLabel label = new JLabel("Vpisi naslov knjige, ki jo zelis brisati");
JPanel panel = new JPanel();
frame5.add(panel);
panel.add(label);
}
}
static class Action5 implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
JFrame frame6 = new JFrame("Urejanje knjige");
frame6.setVisible(true);
frame6.setSize(600,300);
JLabel label = new JLabel("Vpisi naslov knjige, ki jo zelis urejati");
JPanel panel = new JPanel();
frame6.add(panel);
panel.add(label);
}
}
static class Action6 implements ActionListener
{
public void actionPerformed (ActionEvent e)
{
System.exit(0);
}
}
}
try something with layout. JFrame and or remove managed by inside with a content pane. content pane default layout is BorderLayout. so you need to try border layout stuff.
or you can try this code in you main method
frame.setLayout(new FlowLayout());
this will add component by one by one.
for more about layout you can get in here
This is just a fix and not really an explanation of why the problem is occurring.
Call frame.revalidate() after adding all the buttons.
From the Java Docs,
public Component add(Component comp)
This method
changes layout-related information, and therefore, invalidates the
component hierarchy. If the container has already been displayed, the
hierarchy must be validated thereafter in order to display the added
component.

How to tidy up code into class files and methods

I am still learning Java and I am currently creating a program in Swing. I have been confused regarding when and when I should use methods and class files. I have created an application that has two cards, card 1: homeJPanel and card 2: guestFixturesJPanel and I want these to switch between each other on button click - which i have done to an extent. However, my code looks extremely messy and is hard to look at as all JPanels are in one method. I was wondering if there was any way I could put guestFixturesJPanel into a separate method or class file and still be able to call the card on button click. Is this possible? Also, does anyone know of any good tutorials that explain methods and class files well as I have been confused and this may be the solution to my problem.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
public class Main
{
protected static final Component c1 = null;
private JButton viewFixturesButton, loginButton, guestBackButton;
private JLabel testTextJLabel, testTextJLabel2;
JPanel container = new JPanel();
CardLayout cardLayout = new CardLayout();
public Main()
{
final JFrame window = new JFrame ("Main Game");
final CardLayout c1 = new CardLayout();
final JPanel container = new JPanel(c1);
JPanel homeJPanel = new JPanel(new BorderLayout());
container.add(homeJPanel);
JPanel centerJPanel = new JPanel(new BorderLayout());
testTextJLabel = new JLabel("TEST");
centerJPanel.add(testTextJLabel);
JPanel southPanel = new JPanel(new FlowLayout());
viewFixturesButton = new JButton("View Fixtures");
loginButton = new JButton("Login");
southPanel.add(viewFixturesButton);
southPanel.add(loginButton);
homeJPanel.add(centerJPanel, BorderLayout.CENTER);
homeJPanel.add(southPanel, BorderLayout.SOUTH);
centerJPanel.setBackground(Color.BLUE);
southPanel.setBackground(Color.GREEN);
JPanel guestFixturesJPanel = new JPanel(new BorderLayout());
container.add(guestFixturesJPanel);
JPanel guestCenterJPanel = new JPanel(new BorderLayout());
JPanel guestSouthPanel = new JPanel(new FlowLayout());
guestBackButton = new JButton("Back");
guestSouthPanel.add(guestBackButton);
guestFixturesJPanel.add(guestCenterJPanel, BorderLayout.CENTER);
guestFixturesJPanel.add(guestSouthPanel, BorderLayout.SOUTH);
guestCenterJPanel.setBackground(Color.BLUE);
guestSouthPanel.setBackground(Color.GREEN);
viewFixturesButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
c1.show(container, "2");
}
});
container.add(homeJPanel, "1");
container.add(guestFixturesJPanel, "2");
c1.show(container, "1");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(container);
window.setSize(600, 500);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Main();
}
});
}
}
You could extract the guestFixturesPanel to a class of its own like this:
public class GuestFixturesPanel extends JPanel {
public GuestFixturesPanel() {
this.setLayout(new BorderLayout());
JPanel guestCenterJPanel = new JPanel(new BorderLayout());
JPanel guestSouthPanel = new JPanel(new FlowLayout());
JButton guestBackButton = new JButton("Back");
guestSouthPanel.add(guestBackButton);
add(guestCenterJPanel, BorderLayout.CENTER);
add(guestSouthPanel, BorderLayout.SOUTH);
guestCenterJPanel.setBackground(Color.BLUE);
guestSouthPanel.setBackground(Color.GREEN);
}
}
Then in your Main class you could instantiate a GuestFixturesPanel and add it to your container. This would preserve the functionality you have now, and extract the code out of your Main class.
GuestFixturesPanel guestFixturesPanel = new GuestFixturesPanel();
container.add(guestFixturesPanel, "2");
Not sure if that addresses the question you had, but I hope this helps.

Simple Adding a JLabel to JPanel

I have simple problem as I am not much familiar with Java GUI. I am trying to make visible the JLable on the below code as I find it hard to understand the concept. But still label is not visible but the frame do open on run time.
public class Sample extends JPanel {
public void Sample() {
JPanel p = new JPanel();
JLabel lab1 = new JLabel("User Name", JLabel.LEFT);
p.setLayout(new FlowLayout());
p.add(lab1 = new JLabel("add JLabel"));
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new Sample());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
You are forgot to add panel p to sample. Either use add(p) at the end or just remove panel p cause your sample class is extending JPanel.
Option 1:
JPanel p = new JPanel();
JLabel lab1 = new JLabel("User Name", JLabel.LEFT);
p.setLayout(new FlowLayout());
p.add(lab1 = new JLabel("add JLabel"));
add(p);
option 2:
JLabel lab1 = new JLabel("User Name", JLabel.LEFT);
setLayout(new FlowLayout());
add(lab1 = new JLabel("add JLabel"));
Also why are you overriding initialization of JLabel? In your code JLable will always hold value "add JLabel". If you want to see "User Name" then use this add(lab1); instead of add(lab1 = new JLabel("add JLabel"));.
May be you just require this:
JLabel lab1 = new JLabel("User Name", JLabel.LEFT);
setLayout(new FlowLayout());
add(lab1);
Also constructor can not have return type so remove void from your constructor.
The constructor that you are using is not a proper constructor .. A java constructor does not have a return type and the void is extra. When in the main method you are calling new Sample() it is not actually calling your method but the default constructor that exists by default.
Try like this ..
public Sample() {
JPanel p = new JPanel();
JLabel lab1 = new JLabel("User Name", JLabel.LEFT);
p.setLayout(new FlowLayout());
p.add(lab1 = new JLabel("add JLabel"));
}
also you need to do what #Harry Joy suggested to add the add(p); statement otherwise the panel is still not added.
Note the comments.
import java.awt.*;
import javax.swing.*;
public class Sample extends JPanel {
public Sample() {
// set the layout in the constructor
super(new FlowLayout(FlowLayout.LEADING));
// best not to set size OR preferred size!
setPreferredSize( new Dimension(200,200) );
JLabel lab1 = new JLabel("User Name");
add(lab1);
}
public static void main(String[] args) {
// construct the GUI on the EDT
SwingUtilities.invokeLater( new Runnable() {
public void run() {
JFrame frame = new JFrame("User Details");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new Sample());
// important!
frame.pack();
frame.setVisible(true);
}
});
}
}
Note also, that it is generally not considered a good idea to extend a component unless adding custom functionality. That would mean (for example) defining new methods for the Sample panel (Which might better be labelled a UserDetails or UserDetailsContainer if I guess correctly where you are going with that code..). Or it might be a Login component..
Sample is the Jpanel.
Sample extends JPanel means you inherit from JPanel.
just drop JPanel p and all your "p."s
#SuppressWarnings("serial")
public class MyGui extends JFrame{
private MyContentPane myContentPane = new MyContentPane();
public MyGui(){
super("title");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setContentPane(myContentPane);
this.createMenu();
this.pack();
this.setVisible(true);
}
private void createMenu(){
JMenuBar myMenuBar = new JMenuBar();
JMenu xMenu = new JMenu("x");
JMenu x = new JMenu("x");
JMenuItem xItem = new JMenuItem("letter");
JMenuItem exitItem = new JMenuItem("exit");
xItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
myContentPane.xPanel();
}
});
xItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent arg0) {
myContentPane.setxPanel();
}
});
exitItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
});
displayMenu.add(letterItem);
displayMenu.add(colorItem);
fileMenu.add(exitItem);
myMenuBar.add(displayMenu);
myMenuBar.add(fileMenu);
this.setJMenuBar(myMenuBar);
}
}

Categories