jpanel as inner class - java

I need to write a simple tennis game.
To move between different windows(panel with main menu, panel with game, panel with settings) I decided to use inner classes extends JPanel and replace it when some events like start new game occurs.
but the problem is - it doesn't see my inner class. I mean I add it to JFrame
mainframe.add(new MainMenuPanel());
but there is nothing on the screen when I run program. What's the problem?
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MainFrame{
JFrame mainframe;
public static void main(String[] args){
new MainFrame();
}
public MainFrame() {
mainframe = new JFrame();
mainframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainframe.setSize(300, 400);
mainframe.setTitle("X-Tennis v0.1");
mainframe.add(new MainMenuPanel());
mainframe.getContentPane().setLayout(new GridLayout());
mainframe.getContentPane().setBackground(Color.WHITE);
mainframe.setVisible(true);
}
public class MainMenuPanel extends JPanel {
JPanel mainmenupanel;
JLabel label1;
JButton btnNewGame,btnJoinGame;
ImageIcon iconNewGame,iconJoinGame;
public MainMenuPanel(){
mainmenupanel = new JPanel();
label1 = new JLabel("X-TENNIS");
label1.setFont(new Font("Comic Sans MS",Font.ITALIC,20));
label1.setForeground(Color.BLUE);
btnNewGame = new JButton("New Game", iconNewGame);
btnNewGame.setFocusPainted(false);
btnNewGame.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e){
JOptionPane.showMessageDialog(mainframe, "New game");
//delete current panel and add another to mainframe
}
}
);
btnNewGame.setPreferredSize(new Dimension(140,30));
btnJoinGame = new JButton("Join game",iconJoinGame);
mainmenupanel.add(label1);
mainmenupanel.add(btnNewGame);
}
}
}

There is no need for mainmenupanel within the MainMenuPanel class as MainMenuPanel is a JPanel itself
Simple add all the components in MainMenuPanel directly to itself

You create a new JPanel, mainmenupanel, inside MainMenuPanel but never add that to the container itself. You could do
add(mainmenupanel);
If you intend for this JPanel to occupy the full area of the parent, then you can simply add your components directly to your instance of MainMenuPanel as indicated by #Mad

First you should add your component to the ContentPane. In Swing, all the non-menu components displayed by the JFrame should be in the ContentPane.
mainframe.getContentPane().add(new MainMenuPanel());
Edit: I was wrong about the content pane, see #MadProgrammer comment.
Then you have to add the JPanel that you create in MainMenuPanel to the MainMenuPanel instance itself.
add(mainmenupanel);
But you should probably get rid of that intermediary container itself and add your labels to the MainMenuPanel instance itself:
add(label1);
add(btnNewGame);

mainmenupanel.add(label1);
mainmenupanel.add(btnNewGame);
try this :
super.add(label1);
super.add(btnNewGame);

Related

Why is my JPanel not showing up when called into JFrame?

Initially, I created my buttons and my JPanel in my GUI but I want to take them out of my GUI and create a different class for them since I have to add on to them.
Here is the following code that's giving me an issue.
The issue being that my JPanel isn't showing up. I extended the VButtons class to JPanel assuming that adding the JPanel to JFrame would work but no luck.
Any suggestions?
public static void vGui() {
JFrame frame = new JFrame();
B b;
b = new B();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(b, BorderLayout.WEST);
frame.setVisible(true);
}
public static class B extends JPanel {
B() {
JPanel Panel1 = new JPanel();
JRadioButton 1st button = new JRadioButton("1st button");
JRadioButton 2nd button = new JRadioButton("2nd button");
Panel1.add(1st button);
Panel1.add(2nd button);
Panel1.setLayout(new GridLayout(9,1))
}
}
VButtons extends JPanel <-- This itself is a JPanel
JPanel Panel1 <-- But you are adding everything inside Panel1
And panel1 is just created and left unused.
So, remove Panel1.
Just call add method, because you are inside a subclass of JPanel.
You can call this.add(...) if that is clearer to read.
You need to use the vertex from the left intersection to compile the right for layout of the entire grid. The vertices won't intersect if you use 9,1. I like how you you used removeVertex but it is unnecessary.

Place JButton in defined position

I have a problem, i searched on many topics how to place a JButton on a JPanel with a defined position. The most current answer i found is that, i should display layout of JFrame and set it to null, so here is my code. But the thing is that when i'm setting layout to null nothing works anymore.
package loto;
import javax.swing.JFrame;
import javax.swing.JButton;
public class Accueil extends JFrame{
public Accueil(){
this.setTitle("Accueil du loto");
this.setSize(1920,1080);
this.setLocationRelativeTo(null);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fond pan = new fond();
JButton suivant = new JButton("Commencer le Loto");
pan.setLayout(null);
pan.add(suivant);
suivant.setBounds(1800, 400, 40, 300);
this.setContentPane(pan);
while (true) {
this.repaint();
}
}
}
When you are new to Swing, you have to go by step by step UI,
Ensure the JPanel is added to your JFrame... fond pan = new fond(); Is it a JPanel subclass? you dont need to do this way you can
create JPanel jp = new JPanel();
add this JPanel component to JFrame by calling this.add(jp) in your constructor.
three important properties for every Swing display is a) setVisible b)setLayout c)setContentPane d) add
You have added JButton to Jpanel but you have not added Jpanel to JFrame.
add properties this.add(pan), this.setLayout(new FlowLayout()) in your constructor.
remove the while loop from your constructor.
Using null-Layout, you have to set a size and a location for your JButton like this:
suivant.setSize(120,20);
suivant.setLocation(x,y);

How to display one Jframe at a time? [duplicate]

I'm trying to make a little game that will first show the player a simple login screen where they can enter their name (I will need it later to store their game state info), let them pick a difficulty level etc, and will only show the main game screen once the player has clicked the play button. I'd also like to allow the player to navigate to a (hopefully for them rather large) trophy collection, likewise in what will appear to them to be a new screen.
So far I have a main game window with a grid layout and a game in it that works (Yay for me!). Now I want to add the above functionality.
How do I go about doing this? I don't think I want to go the multiple JFrame route as I only want one icon visible in the taskbar at a time (or would setting their visibility to false effect the icon too?) Do I instead make and destroy layouts or panels or something like that?
What are my options? How can I control what content is being displayed? Especially given my newbie skills?
A simple modal dialog such as a JDialog should work well here. The main GUI which will likely be a JFrame can be invisible when the dialog is called, and then set to visible (assuming that the log-on was successful) once the dialog completes. If the dialog is modal, you'll know exactly when the user has closed the dialog as the code will continue right after the line where you call setVisible(true) on the dialog. Note that the GUI held by a JDialog can be every bit as complex and rich as that held by a JFrame.
Another option is to use one GUI/JFrame but swap views (JPanels) in the main GUI via a CardLayout. This could work quite well and is easy to implement. Check out the CardLayout tutorial for more.
Oh, and welcome to stackoverflow.com!
Here is an example of a Login Dialog as #HovercraftFullOfEels suggested.
Username: stackoverflow Password: stackoverflow
import java.awt.*;
import java.awt.event.*;
import java.util.Arrays;
import javax.swing.*;
public class TestFrame extends JFrame {
private PassWordDialog passDialog;
public TestFrame() {
passDialog = new PassWordDialog(this, true);
passDialog.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new TestFrame();
frame.getContentPane().setBackground(Color.BLACK);
frame.setTitle("Logged In");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
});
}
}
class PassWordDialog extends JDialog {
private final JLabel jlblUsername = new JLabel("Username");
private final JLabel jlblPassword = new JLabel("Password");
private final JTextField jtfUsername = new JTextField(15);
private final JPasswordField jpfPassword = new JPasswordField();
private final JButton jbtOk = new JButton("Login");
private final JButton jbtCancel = new JButton("Cancel");
private final JLabel jlblStatus = new JLabel(" ");
public PassWordDialog() {
this(null, true);
}
public PassWordDialog(final JFrame parent, boolean modal) {
super(parent, modal);
JPanel p3 = new JPanel(new GridLayout(2, 1));
p3.add(jlblUsername);
p3.add(jlblPassword);
JPanel p4 = new JPanel(new GridLayout(2, 1));
p4.add(jtfUsername);
p4.add(jpfPassword);
JPanel p1 = new JPanel();
p1.add(p3);
p1.add(p4);
JPanel p2 = new JPanel();
p2.add(jbtOk);
p2.add(jbtCancel);
JPanel p5 = new JPanel(new BorderLayout());
p5.add(p2, BorderLayout.CENTER);
p5.add(jlblStatus, BorderLayout.NORTH);
jlblStatus.setForeground(Color.RED);
jlblStatus.setHorizontalAlignment(SwingConstants.CENTER);
setLayout(new BorderLayout());
add(p1, BorderLayout.CENTER);
add(p5, BorderLayout.SOUTH);
pack();
setLocationRelativeTo(null);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
jbtOk.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if (Arrays.equals("stackoverflow".toCharArray(), jpfPassword.getPassword())
&& "stackoverflow".equals(jtfUsername.getText())) {
parent.setVisible(true);
setVisible(false);
} else {
jlblStatus.setText("Invalid username or password");
}
}
});
jbtCancel.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setVisible(false);
parent.dispose();
System.exit(0);
}
});
}
}
I suggest you insert the following code:
JFrame f = new JFrame();
JTextField text = new JTextField(15); //the 15 sets the size of the text field
JPanel p = new JPanel();
JButton b = new JButton("Login");
f.add(p); //so you can add more stuff to the JFrame
f.setSize(250,150);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Insert that when you want to add the stuff in. Next we will add all the stuff to the JPanel:
p.add(text);
p.add(b);
Now we add the ActionListeners to make the JButtons to work:
b.addActionListener(this);
public void actionPerforemed(ActionEvent e)
{
//Get the text of the JTextField
String TEXT = text.getText();
}
Don't forget to import the following if you haven't already:
import java.awt.event*;
import java.awt.*; //Just in case we need it
import java.x.swing.*;
I hope everything i said makes sense, because sometimes i don't (especially when I'm talking coding/Java) All the importing (if you didn't know) goes at the top of your code.
Instead of adding the game directly to JFrame, you can add your content to JPanel (let's call it GamePanel) and add this panel to the frame. Do the same thing for login screen: add all content to JPanel (LoginPanel) and add it to frame. When your game will start, you should do the following:
Add LoginPanel to frame
Get user input and load it's details
Add GamePanel and destroy LoginPanel (since it will be quite fast to re-create new one, so you don't need to keep it memory).

Problems with BorderLayout() in Java

I've tried a lot of different ways, but I will explain two and what was happening (no error messages or anything, just not showing up like they should or just not showing up at all):
First, I created a JPanel called layout and set it as a BorderLayout. Here is a snippet of how I made it look:
JPanel layout = new JPanel();
layout.setLayout(new BorderLayout());
colorChoice = new JLabel("Choose your color: ");
layout.add(colorChoice, BorderLayout.NORTH);
colorBox = new JComboBox(fireworkColors);
colorBox.addActionListener(this);
layout.add(colorBox, BorderLayout.NORTH);
In this scenario what happens is they don't show up at all. It just continues on with whatever else I added.
So then I just tried setLayout(new BorderLayout()); Here is a snippet of that code:
setLayout(new BorderLayout());
colorChoice = new JLabel("Choose your color: ");
add(colorChoice, BorderLayout.NORTH);
colorBox = new JComboBox(fireworkColors);
colorBox.addActionListener(this);
add(colorBox, BorderLayout.NORTH);
In this scenario they are added, however, the width takes up the entire width of the frame and the textfield (not shown in the snippet) takes up basically everything else.
Here is what I have tried:
setPreferredSize() & setSize()
Is there something else that I am missing? Thank you.
I also should note that this is a separate class and there is no main in this class. I only say this because I've extended JPanel instead of JFrame. I've seen some people extend JFrame and use JFrame, but I haven't tried it yet.
You created a JPanel, but didn't add it to any container. It won't be visible until it is added to something (a JFrame, or another panel that is in a frame somewhere up the hierarhcy)
You added two components to the same position in the BorderLayout. The last one added is the one that will occupy that position.
Update:
You do not need to extend JFrame. I never do, instead I always extend JPanel. This makes my custom components more flexible: they can be added in another panel, or they can be added to a frame.
So, to demonstrate the problem I will make an entire, small, program:
public class BadGui
{
public static void main(String[] argv)
{
final JFrame frame = new JFrame("Hello World");
final JPanel panel = new JPanel();
panel.add(new JLabel("Hello"), BorderLayout.NORTH);
panel.add(new JLabel("World"), BorderLayout.SOUTH);
frame.setVisible(true);
}
}
In this program I created a panel, but did not add it to anything so it never becomes visible.
In the next program I will fix it by adding the panel to the frame.
public class FixedGui
{
public static void main(String[] argv)
{
final JFrame frame = new JFrame("Hello World");
final JPanel panel = new JPanel();
panel.add(new JLabel("Hello"), BorderLayout.NORTH);
panel.add(new JLabel("World"), BorderLayout.SOUTH);
frame.getContentPane().add(panel);
frame.setVisible(true);
}
}
Note that in both of these, when I added something to the panel, I chose different layout parameters (one label I put in 'North' and the other in 'South').
Here is an example of a JPanel with a BorderLayout that adds a JPanel with a button and label to the "North"
public class Frames extends JFrame
{
public Frames()
{
JPanel homePanel = new JPanel(new BorderLayout());
JPanel northContainerPanel = new JPanel(new FlowLayout());
JButton yourBtn = new JButton("I Do Nothing");
JLabel yourLabel = new JLabel("I Say Stuff");
homePanel.add(northContainerPanel, BorderLayout.NORTH);
northContainerPanel.add(yourBtn);
northContainerPanel.add(yourLabel);
add(homePanel);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setLocationRelativeTo(null);
setExtendedState(JFrame.MAXIMIZED_BOTH);
setTitle("Cool Stuff");
pack();
setVisible(true);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(Frames::new);
}
}
The below suggestion is assuming that your extending JFrame.
Testing
First of all, without seeing everything, theres always a numerous amount of things you can try.
First off, after you load everything, try adding this in (Again, assuming your extending JFrame:
revalidate();
repaint();
I add this into my own Swing projects all the time, as it refreshes and checks to see that everything is on the frame.
If that doesn't work, make sure that all your JComponent's are added to your JPanel, and ONLY your JPanel is on your JFrame. Your JFrame cannot sort everything out; the JPanel does that.
JPanel window = new JPanel();
JButton button = new JButton("Press me");
add(window);
window.add(button); // Notice how it's the JPanel that holds my components.
One thing though, you still add your JMenu's and what-not through your JFrame, not your JPanel.

is it possible to point to a particular JPanel

I have this program in which I'm using CardLayout. I have different panels with different attributes. I have a button called "Enter" that I decided to reuse on every panel, however each panel performs a different operation when the button is clicked. Is there a way to say, when button is clicked but I am at a specific panel, then do this. How can I point directly to a panel?
First thing you must consider is: You can't add one button to many panels, every panel should have it's own component(s).
If you add one button to many panels say :
JButton b = new JButton("Button");
//....
pan1.add(b);
pan2.add(b);
pan3.add(b);
In such case, the button will be added to the last panel means pan3, the other won't show the button.
Second, I would like to mention a #trashgod's good example from comments, and also in case confusing, look at this example:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class CardLayoutDemo extends JFrame implements ActionListener {
private CardLayout cardLayout;
private JButton pan1,pan2;
private JPanel mainPanel;
public CardLayoutDemo(){
cardLayout = new CardLayout();
mainPanel = new JPanel(cardLayout);
JPanel p1 = new JPanel();
JPanel p2 = new JPanel();
pan1 = new JButton("To Second Panel");
pan2= new JButton ("To First Panel");
pan1.addActionListener(this);
pan2.addActionListener(this);
p1.setBackground(Color.green);
p2.setBackground(Color.BLUE.brighter());
p1.add(pan1);
p2.add(pan2);
mainPanel.add(p1,"1");
mainPanel.add(p2,"2");
cardLayout.show(mainPanel, "1");
add(mainPanel);
setDefaultCloseOperation(3);
setLocationRelativeTo(null);
setVisible(true);
pack();
}
#Override
public void actionPerformed(ActionEvent ev){
if(ev.getSource()==pan1)
cardLayout.show(mainPanel, "2");
else if(ev.getSource()==pan2)
cardLayout.show(mainPanel, "1");
}
public static void main(String...args){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new CardLayoutDemo().setVisible(true);
}
});
}
}
You can let the panel assign an ActionListener to the button each time the card is created. That way the constructor for a specific panel can determine what the functionality of the button will be.

Categories