Communictating between classes using Jpanel, repaint() method - java

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.

Related

Basic JPanel/JFrame class problem in Java

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;
}
}

Swing: Visual interface connect to second frame

I have 2 frames. I want from the first frame to open the second. I tried this, but it leads to an exception.
class aboutaction implements ActionListener {
public void actionPerformed(ActionEvent e) {
frame.dispose();
aboutInfo about = new aboutInfo();
about.frame.setVisible(true);
}
}
about.addActionListener(new aboutaction());
This is the full program: https://github.com/Zhelyazkov97/Fuel-calculator.git.
You're basic problem is a NullPointerException create from a misunderstanding of how Swing works and a bad design.
Basically, you define your class as...
public class aboutInfo extends JFrame {
private JPanel contentPane;
javax.swing.JFrame frame;
Now, here the confusion starts, you basically have two frames, but you only ever add components to the instance of aboutInfo.
The basic answer here is, get rid of frame, it's just confusing the issue. In fact, you shouldn't be extending from JFrame in the first place, you should really use something like JPanel and simply add instances of the class to instances of JFrame or JDialog or what ever container you want

Transitions between JPanel?

First of all... I'd like to say that I am not interested in using the card layout for this... Unless it's necessary (which means that not using the card layout would be result in unnecessary workarounds and complex code). This is for learning purposes after all and I will look into the card layout very soon enough anyway...
Okay so my question is pretty basic GUI layout I guess. My code is not working and this whole layouting confuses me quite a lot...
I'm having trouble how to make the transition between JPanels like this:
I have one window. I press a button, the old window is replaced by another window. I press a button and that window will be replaced by another window.
I'd like to add that I am skipping a lot of irrelevant code in my example below...
I start off with a JFrame:
public class StartWindow extends JFrame{
public StartWindow(){
//Add JButton & ActionListener
//When the button is pressed:
add(new NextWindow());
}
public static void main(String [] args){
new StartWindow();
}
}
then I have several JPanels...
public class NextWindow extends JPanel{
public NextWindow(){
//Add a JButton & ActionListener
//When the button is pressed:
add(new NextWindow2());
remove(this);
//This does not work. Nothing happens.
}
}
public class NextWindow2 extends JPanel{ // Stuff and so on}
So, I'd like to know a proper way to handle this situation!
You are adding a panel to itself. You need to remove the panel from the JFrame, add the new one to it, and call revalidate() on the JFrame.

Mouselistener wont apply to panel

So I created a handling class that implements the MouseListener (this one works). As the program runs some resources are being loaded and it creates the panel to be used for the MouseListener etc... Then when everything is done it's suppose to enter() the panel and add the MouseListener. enter() below:
#Override
public void enter() {
gh = new Game_handler(gr); //gh works fine and implements mouselistener
this.addMouseListener(gh); //gr is nothing but a chunk of data
this.requestFocus();
}
Now for some reason the MouseListener doesn't listen! I 've done some system prints and I know the panel is created then the MouseListener class and then it's added to the panel. But for some reason it just wont do anything!

java pass object from JFrame to JPanel

I am developing a standalone application, in Java using NetBeans, that gets and sends data via Serial Port. I am using a great API for Serial communication called java simple serial connector http://code.google.com/p/java-simple-serial-connector/
Please download the following NetBeans project that I created:
http://netload.in/dateiN9xmwRtn19.htm
Even if you do not have netbeans you can still view the code.
The above is a small example project that I made to explain what I wish to accomplish. The example contains a JFrame that contains the main method. This JFrame contains 2 panels: a Panel with navigation buttons, and a Panel that displays Panel 1 and Panel 2 using CardLayout.
In the JFrame I have a method that gets port names list using the getPortNames() method of the jssc API. My question is, how do I pass these port names String values from JFrame to my Panel 1, without using the following since it will not work:
MyJFrame myjframe = new MyJFrame();
myjframe.getPortNames();
Hovercraft Full Of Eels
Once again thank you very much for your explanation, it is worth gold. I now realize that my problem is NetBeans rather than Java. I am not familiar with it enough but I would still prefer to use it due to the size and complexity of my project. I have uploaded 2 more screenshots below, that show how I tried to pass the "this" reference of the JFrame object to my JPanel object in NetBeans. As you can see in the MyJFrame.java screenshot, NetBeans has underlined "this" reference as an error. Would you please be able to help me with this problem? Also, in the first sentence of your explanation you mention that the serial port methods should be in a separate class, not in JFrame, since they are non-GUI methods. I fully agree with you and I would prefer to do it that way since it is the correct object-oriented approach. But doing it that way, I am once again facing the same problem in NetBeans. How do I now pass the object reference from SerialPorts.java class to JFrame, JPanel etc in a way so that I am not creating a new SerialPorts object all the time, remember I need the connection to stay open all the time (ex. without using SerialPorts sp = new SerialPorts();). Thank you so so so much for your help.
Adding "this" in code customizer for Panel 1
MyJFrame.java - editor underlines reference "this" as error
I wonder if you should have the port names held by a non-GUI model class and obtained from it rather than from the "JFrame", but regardless your question is a specific example of a more of a general question: how do you pass information from one GUI object to another, and that can be generalized further to: how do you pass information from one object to another.
The simple answer is to have one object call a method on the other, which is what you've tried, and which is what should work, but the problem with your attempt is that you're calling it on the wrong object. You have a JFrame object that has already been constructed, that is visible, and that holds the information you need, and that is the object which you should be calling your method on, not a new JFrame object. Sure the new object is built from the same class, but understand that it is a completely different object from the one that's displayed which is the one you want.
So now your problem boils down to this -- how do I get a reference to the visualized JFrame into another object? There are many ways to do this, but the easiest way to do this is to probably pass a reference from one class to the other via a constructor or method parameter.
...
So for instance, say you've got a class called FooFrame that extends JFrame, and it holds a FooPanel object that extends JPanel, and suppose you want the FooPanel object to call the someMethod() method of FooFrame:
public class FooFrame extends JFrame {
public String someMethod() {
return myTextField .getText();
}
}
You could have FooPanel create a new FooFrame object and call this method as you're trying to do:
class FooPanel extends JPanel {
public void otherMethod() {
FooFrame fooFrame = new FooFrame();
fooFrame.someMethod();
}
}
But then you run into the same problem you're running into above. The FooFrame object created here is not the one being displayed, and so the contents of the JTextField will be empty and not very helpful. The solution I'm suggesting is that you pass a reference from the original JFrame into the JPanel via a constructor parameter like so:
class FooPanel extends JPanel {
private FooFrame fooFrame;
// constructor accepts a reference to a FooFrame object
public FooPanel(FooFrame fooFrame) {
this.fooFrame = fooFrame; // and sets its field with it
}
public void otherMethod() {
// no longer needed!
// FooFrame fooFrame = new FooFrame();
// now method is called on the right object!
fooFrame.someMethod();
}
}
Then you can create your FooPanel object in FooFrame and pass the FooFrame object (this) into it.
public class FooFrame extends JFrame {
private JTextField myTextField = new JTextField(10);
private FooPanel fooPanel;
public FooFrame() {
// the current FooFrame object is this!
fooPanel = new FooPanel(this);
add(fooPanel);
}
public String someMethod() {
return myTextField .getText();
}
}

Categories

Resources