I have a class called UserInterface. In the code public class UserInterface extends JPanel, does "extends JPanel" mean that there is a JPanel within the JFrame (the JFrame is the application window) or does it mean something else?
Also, if it means that there is a JPanel within the JFrame, how can I access the JPanel (for example, set its background colour)?
extends in Java means is-a. So your class is a JPanel; it's inheritance; a fundamental part of OOP.
Since your class is a JPanel, if you want to set it's background color somewhere inside the class you'd just do setBackground(yourColor) from outside would be ui.setBackground(yourColor) assuming of course that you named the instance ui.
JFrames are not the same as JPanels if that's what you were getting at.
Related
I started not so long ago learning Java through tutorials and videos, and after understanding a few things (how buttons, layouts, audio, and a few other things work) one of my goal now is to create a little interactive game.
I wrote a pretty big part of the game in the Main Class and it was working good, but it got messy after a while.
So I decided to try another time from the beginning using different classes for every part of the game to make the code look more clear and understandable.
But I have a problem from the very beginning and after a few hours of searching tutorials, answers on forums and not finding a precise answer, I think it's the best if you will see exactly my problem (which is very simple!)
-So I just constructed the JFrame in a class (I use the main Class only to launch the frame, and it works fine) :
import javax.swing.*;
import java.awt.*;
public class principalFrame {
public principalFrame(){
JFrame mainFrame = new JFrame();
mainFrame.setVisible(true);
mainFrame.setSize(1200,750);
mainFrame.getContentPane().setBackground(Color.BLACK);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setResizable(false);
}
}
and I created a JPanel in another class :
import javax.swing.*;
import java.awt.*;
public class mainMenu{
public mainMenu(){
JPanel menuPanel = new JPanel();
menuPanel.setSize(300,300);
menuPanel.setBackground(Color.BLUE);
}
}
And my goal is to add the JPanel inside the JFrame. And... I don't understand how to do it.
I tried to add the menuPanel class as an object in the mainFrame class so I could add the JPanel but it did'nt work. Then tried a bunch of other solutions from what I read on older questions but nothing really helped me.
PS : I know that I didn't add any layout manager or any other things in the code here because I want to keep the code very simple for the question.
So if you want to make a separate class for mainMenu, you should make it extend JPanel. This way, your mainFrame class can instantiate it.
Here is what I would tell you about the lessons I learned in building things in swing:
You (almost) never need a separate class to create a JFrame. If you create a class that extends JPanel, it is easy enough to create a JFrame in a static method (like main) to put your JPanel in. That being said, if you also want to use the JLayeredPane or want to add menus on a JMenuBar, there might be a case of subclassing JFrame. The advantage of not subclassing JFrame is that it makes it easier to stick your JPanel into a JFrame, a JDialog (via JOptionPane) or a JWindow.
Unless you have a Component that you think could be useful in other applications, you should build your entire GUI in one class, and also use that class as the Controller. What is an example of a Component that could be used in other applications? Back in the day, I made a "ColorButton" swing class, for color picking. This component has a self-contained model, has its own controller and an API to get the picked color. (https://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/ui/ex/) which makes it reuseable. But normally, the elements of the GUI you are building aren't really reuseable outside of what you are doing in that class.
With that said, to the code you posted above:
Your mainMenu JPanel isn't accessible outside the class, so that is probably a problem. As I said in the paragraph above, if you're not sure that the Component you are creating could be used in another place, it is better to put the entire view and model building in the same class as the controller
You were close. You have to be able to get the JPanel from the MainMenu class.
The JFrame methods must be called in a specific order. This is the order I use for my Swing applications.
Class names start with an upper case character.
Here's one way you could code your MainMenu class.
public class PrincipalFrame {
public PrincipalFrame() {
JFrame mainFrame = new JFrame();
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.add(new MainMenu().getMenuPanel(), BorderLayout.CENTER);
mainFrame.setSize(1200, 750);
mainFrame.setResizable(false);
mainFrame.setVisible(true);
}
}
public class MainMenu {
private final JPanel menuPanel;
public MainMenu() {
this.menuPanel = new JPanel();
this.menuPanel.setPreferredSize(300, 300);
this.menuPanel.setBackground(Color.BLUE);
}
public JPanel getMenuPanel() {
return menuPanel;
}
}
Say I have a JFrame called childJframe.
If I create a new childJFrame from two different JFrames. How can I get which particular JFrame created the childJFrame.
Thus:
public class myPage1 extends javax.swing.JFrame{
// on a Button clicked
childJFrame cjf = new childJFrame();
cjf.setVisible(true);
}
And the Second class is
public class myPage2 extends javax.swing.JFrame{
// on a Button clicked
childJFrame cjf = new childJFrame();
cjf.setVisible(true);
}
How can I find out if cjf is an instance of myPage1 or myPage2?
The Window class, which JFrame descends from, has a getOwner() method that will return the "owner" Window for any child windows.
But having said that, child windows should be JDialogs, not JFrames as your application should have one and only one JFrame, and I believe that JFrames don't have owners, so that this method may return null. If you need to change "views" within the JFrame, use a CardLayout, and if you need to display child windows, use dialog windows such as JDialogs and JOptionPanes. Please read: The Use of Multiple JFrames, Good/Bad Practice?, for more on this.
But having said this, I do have to wonder if your question may in fact be an XY Problem where you ask "how do I fix this code" when the real solution is to use a different (read -- more "object oriented") approach entirely.
If your child windows must really be JFrame instances (I suppose ChildJFrame extends JFrame), I think the simplest solution consists in keeping track of the parent JFrame in the ChildJFrame instance. Since ChildJFrame is a custom class of yours, this is easy:
Add a JFrame (or Frame or Window) attribute to your ChildJFrame class;
Add to ChildJFrame a constructor that takes a parameter that will be assigned to the above attribute;
When you create a ChildJFrame instance from one of your JFrame-derived classes, just add this as a parameter.
Then you have everything you need to interact with the parent JFrame.
I have a class "GUI" that extends JPanel. I have another class "Buttons" that extends JFrame. I'm trying to have the JFrame class call a method "clearScreen()" in the JPanel class when the when a JButton "clearB" is pushed on the JFrame.
The only way I could make this work was by building the object for the JPanel class "GUI" right in the actionlistener for the JButton:
clearB.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent event){
GUI g = new GUI();
g.clearScreen();
}
}
);
But then when I called the method clearScreen(), which looks like this:
public void clearScreen(){
xs.clear();
ys.clear();
count = 0;
repaint();
}
NOTHING HAPPENED. I'm guessing it's because the repaint() method wasn't working for some reason unknown to me.
Someone PLEASE show me an easier, working way of doing what I'm trying to accomplish here.
Thanks! :D
The reason that your ActionListener isn't working is because the GUI object that you create in there is a new GUI object, one that is completely unrelated to the GUI object that is displayed, and so calling the clearScreen() method on the non-displayed GUI instance will have no effect on the displayed GUI instance.
The solution is for your Buttons class to hold a valid reference to the visualized GUI object and call methods on this reference. The reference can be passed via a setter method or constructor parameter.
i.e.,
public class Buttons {
private GUI gui;
public Buttons (GUI gui) {
this.gui = gui;
}
// in some ActionListener code...
gui.someMethod();
}
A couple of comments:
It is unusual that you should have to have a class that extends JFrame. Myself, I try to avoid doing this unless necessary, but rather usually create my JFrames from the JFrame class itself, and only when needed.
I'm a little surprised that your main window class doesn't already have a GUI variable, since it likely displays the GUI instance.
I have a main class which extends JFrame, and its content is contained in other classes which extend JPanel.
Now, in those other classes, I want to use several panels to group the content in a good order.
Is it possible to use many panels( by creating several JPanel objects in that class) in this class that extends JPanel?
JPanel extends JComponent, which extends Container, so JPanel is a container, so it contain other Component.
So, yes, you can do this and in fact, depending on the context and requirements, is actually a good idea.
You could take a look at this example and this example
mKorbel makes a valid point. It is generally not recommended to extend from top level containers like JFrame, instead, use something like JPanel as you primary application interface (adding other containers and components to it as you see fit) and adding this frame to an instance of JFrame which you create
I have a MainWindow class that extends JFrame and is the only frame in my application. I have several JPanels to change its content though. I would like to pass the MainWindow around so I won't have to make a global copy of it.
Here is the problem. I have a fake JMenuBar in MainWindow that I use to go around and look for screens. In their JMenuItem listeners, I cannot pass MainWindow as this to the JPanels.
Is there a way I can do that, like maybe marking the class final or do I have to create a new MainWindow each time I have to pass in one. It doesn't carry around any data so its not crucial and the performance isn't a major concern for a small final project like this but I want to know if there is a better way?
Are you unable to pass this because it would reference the listener? If so, you should be able to use MainWindow.this.
Or create a reference to this outside the listener and pass that as the parameter.
Create the MainWindow class as the Outer class and extend this to JFrame which u already did, . Now in the MainWindow class, create as many inner classes as you want and let the handle the ActionListener method in different way..
eg:
MainWindow extends JFrame {
MainWindow(){
}
class panel1 extends JPanel implements ActionListener{
}
class panel2 extends JPanel implements ActionListener{
}
}
You can also implement Singleton Pattern, so that makes sure there is only one instance of MainWidow.
Try any of this approaches:
Make MainWindow singleton.
Mark as final a variable in the method when you create the listener.
Use MainWindow.this
For your case use the singleton approach, with that you can access freely from any place of your project.