Different classes for different JPanels - java

I am a Beginner in Java. I have looked all over the place for an answer to my question, but could not find any, or they were to complex for me at this stage of my Java knowledge.
What Planning to do is to create a program on the way of my learning, it will be quite a bit of code and would like to keep things organized.
I have a class where I want to store the mainPanel, where then I would like to add other JPanels which are stored in other classes (on button click (not with a cardLayout)).
My code is probably full of errors, I hope you can help me.
Here is my main class:
import javax.swing.JFrame;
public class TestTool {
public static void main(String[] args){
Test1 frame = new Test1();
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Then I have another class where I want to store the mainPanel and load other panels from different classes:
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test1 extends JFrame {
public Test1(){
testPanel();
}
public void testPanel(){
setTitle("Test Tool");
TestPanel1 te = new TestPanel1();
JPanel mainPanel = new JPanel();
mainPanel.add(te.pan());
}
}
On the next class I have a different panel which I am then trying to load into the mainPanel:
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class TestPanel1 {
private JPanel panel1;
public TestPanel1(){
JPanel panel1 = new JPanel();
JLabel label1 = new JLabel("panel 1");
panel1.add(label1);
JButton button1 = new JButton("button 1");
panel1.add(button1);
}
public JPanel pan(){
return panel1;
}
}
Is there anyway I can do it like this? or am I doing it completely wrong?
Thank you

I would suggest making the TestPanel class extend the JPanel class and in your constructor call the superconstructor and then do what you need.

Related

Is it possible to create a panel with a class on the left and right side?

I have been practicing my code with Java Swing and have gotten decent on controlling where to place some items, such as labels and or buttons, but I was wondering if you can do the same with classes? I have just a simple class with enough code to put a button in it and that's it, that I am trying to create an instance of the class and then control for to put on the left and right side but when I do, all it does is create two separate windows with the button in the middle and that's it. Am I doing something wrong, or can you not do classes the same way?
The code:
import java.awt.Color;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class Fun extends JFrame
{
private final int WIDTH = 500;
private final int HEIGHT = 400;
public Fun()
{
setTitle("Fun Management");
setSize(WIDTH, HEIGHT);
BuildPanel west = new BuildPanel(); /// BuildPanel is the name of the class that has just a button in it.
BuildPanel east = new BuildPanel(); ///
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(west, BorderLayout.WEST); /// I am doing the same thing with the instances as I would with buttons or labesl
add(east, BorderLayout.EAST);
setVisible(true);
}
public static void main(String[] args)
{
new Fun();
}
}
I took your code and created the following GUI.
Oracle has a rad tutorial, Creating a GUI With Swing, that will show you how to create Swing GUIs. Skip the Netbeans section.
Always start your Swing application with a call to the SwingUtilities invokeLater method. This method ensures that your Swing components are created and executed on the Event Dispatch Thread.
Use Swing components. Don't extend a Swing component unless you want to override one or more of the component methods.
The JFrame methods must be called in a specific order. This is the order I recommend for most Swing applications. Use the JFrame pack method and let the components size the JFrame.
I created a BuildPanel class to build a JPanel. There are good reasons to do this, but be careful. You have to manage each instance of the class you create. As an example, what if you want the text of the two buttons to be different? What if you want to assign two different ActionListener classes, one to each button?
Here's the complete runnable code. I made the BuildPanel class an inner class so I can post the code as one block.
import java.awt.BorderLayout;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class TwoPanelExample implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new TwoPanelExample());
}
#Override
public void run() {
JFrame frame = new JFrame("Fun Management");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BuildPanel west = new BuildPanel();
BuildPanel east = new BuildPanel();
frame.add(west.getPanel(), BorderLayout.WEST);
frame.add(east.getPanel(), BorderLayout.EAST);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public class BuildPanel {
private final JPanel panel;
public BuildPanel() {
this.panel = createMainPanel();
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(5, 30, 5, 30));
JButton button = new JButton("Click Me");
panel.add(button);
return panel;
}
public JPanel getPanel() {
return panel;
}
}
}

Can't dispose of jframe window?

I'm trying to dispose of the difficulty window after any one of the difficulty button's are clicked but it won't happen. I've tried .dispose and frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); but i can't get it. Is it just placement or more?
import java.awt.FlowLayout;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.GridLayout;
public class Game extends JFrame{
public static JFrame frame = new JFrame();
private JLabel lab;
public static void main(String[] args) {
Game difficulty = new Game();
difficulty.setSize(350,105);
difficulty.setTitle("Difficulty.");
difficulty.setVisible(true);
difficulty.setLocationRelativeTo(null);
/**Game sudoku = new Game();
sudoku.setSize(900, 900);
sudoku.setVisible(false);*/
}
public Game(){
setLayout(new FlowLayout());
lab = new JLabel("Please select your difficulty.");
add(lab);
JButton easy;
easy = new JButton("Easy");
add(easy);
easy.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
//Execute when button is pressed
System.out.println("You clicked the button");
JFrame.dispose();
}
});
JButton medium;
medium = new JButton("Medium");
add(medium);
JButton hard;
hard = new JButton("Hard");
add(hard);
JButton evil;
evil = new JButton("Evil!");
add(evil);
}
}
First of all you're extending JFrame and creating an object of JFrame, if I'm not wrong, this shouldn't be done.
public class Game extends JFrame{
public static JFrame frame = new JFrame();
And as #Salah said, JFrame is not static, so it should be:
public JFrame frame = new JFrame();
To solve your problem, you're disposing a new JFrame (yes, you have 3 JFrames in one class, instead of 1, which is what you want), with: JFrame.dispose(); if you already created an object or you're extending JFrame, you can:
this.dispose(); //For the extended JFrame
or
frame.dispose(); //For the object you created
dispose() method is not a static, so it'll not work by calling it directly from JFrame class
JFrame.dispose();
try to do :
dispose();
Or to dispose the frame object you have created
frame.dispose();
Read more about JFrame
I had the same problem:
this.dispose();
solved my problem.
Try setting the jFrame to invisible before disposing it:
public void disposeJFrame(JFrame frame){
frame.setVisible(false);
frame.dispose();
}
If you're wanting to close the whole program, you can use System.exit(0);
Instead JFrame.dispose();, use frame.dispose() or JFrame.this.dispose();

I'm attempting to create a small GUI application, but the contents of the JFrame are not showing on screen. How can I fix my code?

As of late I've been developing a (very) small GUI application in Java. I'm extremely new to Swing and Java in general, but up until now I have been able to get everything to work the way I want it to. However, after cleaning up my code, when I run the program nothing but the border of the window appears. What am I doing wrong and how can I fix my code? Thanks ahead of time!
For the sake of saving space I've made Pastebin links to all of my classes (besides Main).
Main Class
package me.n3rdfall.ezserver.main;
public class Main {
public static GUI g = new GUI();
public static void main(String[] args) {
g.showWindow(800, 500);
}
}
GUI Class
http://pastebin.com/gDMipdp1
ButtonListener Class
http://pastebin.com/4XXm70AD
EDIT: It appears that calling removeAll() directly on 'frame' actually removed essential things other than what I had added. By calling removeAll() on getContentPane(), the issue was resolved.
Quick hack: Remove the removeAll() functions.
public void homePage() {
// frame.removeAll();
// mainpanel.removeAll();
// topbar.removeAll();
I'm not sure what you're trying to achieve, but that will at least show some items. If I were you I would rebuild this GUI by extending JFrame. It will make your code a little easier to read.
I also think what you are trying to achieve with the buttons is to switch layouts, you can do this in an easier way by using CardLayout
Example (has nothing to do with your code, but to demonstrate):
import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Example extends JFrame implements ActionListener {
private JButton leftButton;
private JButton rightButton;
private CardLayout cardLayout = new CardLayout();
JPanel cards = new JPanel(cardLayout);
final static String LEFTPANEL = "LEFTPANEL";
final static String RIGHTPANEL = "RIGHTPANEL";
JPanel card1;
JPanel card2;
public Example() {
JPanel topPanel = new JPanel();
addButtons(topPanel);
add(topPanel, BorderLayout.NORTH);
add(cards, BorderLayout.CENTER);
//Initiates the card panels
initCards();
setTitle("My Window");
setSize(300, 300);
setLocationRelativeTo(null);
setVisible(true);
}
private void initCards() {
card1 = new JPanel();
card2 = new JPanel();
card1.setBackground(Color.black);
card2.setBackground(Color.red);
cards.add(card1, LEFTPANEL);
cards.add(card2, RIGHTPANEL);
}
private void addButtons(Container con) {
leftButton = new JButton("Left Button");
leftButton.addActionListener(this);
rightButton = new JButton("Right Button");
rightButton.addActionListener(this);
con.add(leftButton, BorderLayout.WEST);
con.add(rightButton, BorderLayout.EAST);
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource().equals(leftButton)) {
//Change cardlayout
cardLayout.show(cards, LEFTPANEL);
} else if(e.getSource().equals(rightButton)) {
//Change cardlayout
cardLayout.show(cards, RIGHTPANEL);
}
}
public static void main(String[] args) {
new Example();
}
}

JTextField is blanking out my JPanels

I am attempting to learn more about creating more dynamic GUI's. I am hoping to add different panels with different content and as you press buttons on one main panel, it changes the adjacent panels. I have added two panels and some buttons and when I test the program, it displays correctly. The problem is when I add a JTextField (or JTextArea) the panels are blank and there are no buttons. The strange thing is I haven't added the JTextField to either panel. I have only created a global variable. If I comment it out, the program runs correctly. Am I missing something very simple?
Here is the gameWindow class that has the JTextField
package rpgcreator;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
class gameWindow extends JPanel {
JPanel startWindowPanel;
JPanel settingsPanel;
JPanel characterPanel;
JPanel scenarioPanel;
JPanel mapPanel;
JButton CharacterButton = new JButton("Create your character");
JButton StoryButton = new JButton("Choose your Story line");
JButton MapButton = new JButton("Choose your World");
//JTextField nameField = new JTextField(15); //comment or uncomment to see issue
public gameWindow() {
setLayout(new GridLayout(0,2,5,0));
startWindowPanel = new JPanel(new FlowLayout());
settingsPanel = new JPanel(new GridLayout(2,1));
startWindowPanel.setBackground(Color.blue);
settingsPanel.setBackground(Color.black);
startWindowPanel.add(MapButton);
startWindowPanel.add(StoryButton);
startWindowPanel.add(CharacterButton);
add(startWindowPanel);
add(settingsPanel);
}
}
Here is main
package rpgcreator;
import javax.swing.JFrame;
public class RPGCreator extends JFrame{
private static void mainWindow(){
RPGCreator mainwindow = new RPGCreator();
mainwindow.setSize(1200, 800);
mainwindow.setResizable(false);
mainwindow.setLocationRelativeTo(null);
mainwindow.setTitle("RPG Creator");
mainwindow.setVisible(true);
mainwindow.add(new gameWindow());
mainwindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
// TODO code application logic here
mainWindow();
}
}
setVisible should go at the end. You're currently setting visible to true, and then adding a panel.
mainwindow.setVisible(true);
mainwindow.add(new gameWindow());
Put setVisible at the end after setDeaultCLoseOperation
I'm not entirely sure why it does it, maybe someone else can explain.
What I do know, is I usually call pack() which seems to make your problem go away.
private static void mainWindow(){
final RPGCreator mainwindow = new RPGCreator();
mainwindow.setMinimumSize(new Dimension(1200, 800));
mainwindow.setResizable(false);
mainwindow.setTitle("RPG Creator");
mainwindow.setVisible(true);
mainwindow.add(new gameWindow());
mainwindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainwindow.pack(); //This usually goes after you've added all of your components
mainwindow.setLocationRelativeTo(null);
}
Some notes:
I had to change to mainwindow.setMinimumSize(new Dimension(1200, 800)); to avoid the frame looking squashed. Although I would usually let the layout manager deal with the sizes of things.
Call setLocationRelativeTo(null) after you call pack() so that it has the desired effect. Again not sure why, but I've learnt that through some hardship.

CardLayout, in JFrame or JPanel?

I have to make a game for school and I've been having some trouble with switching JPanels with a click on the JButton. I want to use a CardLayout, but I'm new to Java which makes it very hard. My goal is to have all my Panels in different classes, like class 'Panel 1', class 'Panel 2' etc. (instead of creating my JPanels in my main (JFrame) class, so my code is easier to read. Is it possible to put your CardLayout container in the class which contains my JFrame? And also, where do I put that darn ActionPerformed? Here is my code, hope you guys can help me!
MAIN (JFrame) CLASS
package invers;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class InversMain extends JFrame implements ActionListener
{
public CardLayout cardlayout;
public Container contentPane = this.getContentPane();
public InversMain()
{
JFrame frame = new JFrame();
frame.setLayout(cardlayout);
frame.setSize(1366,768);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Invers");
frame.setResizable(true);
frame.setVisible(true);
contentPane.setPreferredSize(new Dimension(600, 400));
contentPane.add(new InversMainPaneel(), "Panel 1");
contentPane.add(new InstellingenPaneel(), "Panel 2");
settingsButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
cardlayout.show(contentPane, "Panel 1");
}
});}
public static void main ( String [] args)
{
new InversMain();
}
}
Note that the settingsButton is my button from the PANEL 1 class. Because it isn't created in my main class, it gives an error. I want to refer to my settingsButton from PANEL 1 class, from within my main class. Is this possible?
PANEL 1, PANEL CONTAINING MY BUTTONS, THIS IS MY MAIN MENU PAGE
package invers;
import java.awt.Color;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JPanel;
public class InversMainPaneel extends JPanel
{
private JButton nieuwSpelKnop = new JButton("Nieuw spel");
private JButton laadSpelKnop = new JButton("Laad Spel");
private JButton settingsButton = new JButton("Settings");
private JButton handleidingKnop = new JButton("Handleiding");
public InversMainPaneel()
{
this.setLayout(null);
nieuwSpelKnop.setSize(300,40);
nieuwSpelKnop.setFont(new Font("Arial", Font.BOLD, 25));
nieuwSpelKnop.setLocation(520,250);
nieuwSpelKnop.setVisible(true);
laadSpelKnop.setSize(300,40);
laadSpelKnop.setFont(new Font("Arial", Font.BOLD, 25));
laadSpelKnop.setLocation(520,350);
laadSpelKnop.setVisible(true);
settingsButton.setSize(300,40);
settingsButton.setFont(new Font("Arial", Font.BOLD, 25));
settingsButton.setLocation(520,450);
settingsButton.setVisible(true);
handleidingKnop.setSize(300,40);
handleidingKnop.setFont(new Font("Arial", Font.BOLD, 25));
handleidingKnop.setLocation(520,550);
handleidingKnop.setVisible(true);
this.add(nieuwSpelKnop);
this.add(laadSpelKnop);
this.add(settingsButton);
this.add(handleidingKnop);
this.setBackground(new Color(178,143,79));
}
}
}
PANEL 2, FOR TESTING IF THE CARDLAYOUT WORKED
package invers;
import java.awt.Color;
import javax.swing.JPanel;
public class InstellingenPaneel extends JPanel
{
public InstellingenPaneel()
{
this.setBackground(new Color(178,143,79));
}
}
Have you tried setting the JFrame contentpane using the setContentPane method?
Because I can see you declaring JFrame and a contentpane object, but not setting it, or setting it with your panels.
Note that the settingsButton is my button from the PANEL 1 class. Because it isn't created in my main class, it gives an error.
I'm guessing that the error you're getting is telling you that cardlayout is referenced in an inner class and thus must be made final. To fix this problem, simply insert the final keyword on your creation of cardlayout.
Second - yes, it is perfectly acceptable (and in line with best practices) to define your panel types in separate classes and then create instances of those classes to place in your JFrame.
Third, it appears that you have "that darned actionPerformed" in the right place (i.e. as a method in your ActionListener inner-class), but you should add the #Override annotation to it. Do you know what I mean by that?
Finally, if you want to refer to the settingsButton from another class, you have several options. I would recommend declaring settingsButton as an instance variable of your JFrame class, and passing a reference to the JFrame to the constructor of the InversMainPanel class:
public InversMainPanel(InversMain im) {
...
im.settingsButton. //do something with the settings button.
having created an InversMainPanel from the InversMain class like this:
InversMainPanel imp = new InversMainPanel(this)
with this referring to the InversMain instance from which the call is being made.
Let me know if I can explain any of this further.
PS: Check out this tutorial on Java naming conventions

Categories