I have this piece of code:
public class GUI extends JFrame {
private PlaneUI planeui;
public GUI(PlaneUI planeui) {
this.planeui = planeui;
}
//We have put the code that creates the GUI inside a method
public GUI() {
start();
planeui.display();
} ...
This is just a test and I need the method "planeui.display" to work when the program starts, together with the method "start();" which already works.
public final class PlaneUI extends JFrame {
public void display() {
//Creates a new JPanel object
JPanel panelStart = new JPanel();
getContentPane().add(panelStart);
//Changing the default layout from Flowlayout to absolute
panelStart.setLayout(null);
setTitle("Reservationer"); //Sets the window title
setSize(236, 256); //Sets the default size of the window
setLocationRelativeTo(null); //Start location of the window (centered)
setDefaultCloseOperation(EXIT_ON_CLOSE); //Exits the window
}
}
I have imported the needed libraries and I feel like the problem lies in an object that isn't created correctly since I get a nullpointerexception. I tried running this planeUI class in the main method and it worked correctly. I just can't get it to work this way..
In function PlaneUI.display() add one last line setVisible(true) because your adding everything but not displaying anything
you have to add this into your display() method:
setVisible(true);
Otherwise, all you are doing is setting all the aspects of the JFrame and adding the JPanel to it. You have to make it visible afterwards.
Related
How would I go about closing a JFrame based on an ActionEvent from a button click within a JPanel?
I have a total of three classes:
Application: contains the main method and runs the program by creating a FrameStartUp object.
FrameStartUp: extends the JFrame class and displays the contents within StartUpPanel.
StartUpPanel: extends the JPanel class and has all the components and ActionEvents.
Within the StartUpPanel class, I have a button with an ActionEventListener waiting for the button to be clicked.
When the button is clicked I want the application to shut down completely. I know of a method called .dispose() for the JFrame class, but I can't use it because creating an object of FrameStartUp would just run another GUI (run by the constructor).
As I am new to programming and swing, I do not know any other way to fix this, other than getting rid of the StartUpPanel and just creating a JPanel within the FrameStartUp class.
Are there any methods provided by Swing that can access the current JFrame that the panel is on, so the program can close when the ActionEvent is triggered?
I know of a method called .dispose() for the JFrame class
This will work if you explicitly set setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Are there any methods provided by Swing that can access the current JFrame that the panel is on
Yes... SwingUtilities provides one called getWindowAncestor().
button.addActionListener(e -> {
SwingUtilities.getWindowAncestor((Component)e.getSource()).dispose();
});
... or more commonly, you can chose to reference a final variable to achieve the same effect...
final JFrame swingStuff = this; // or expose via a getter/setter
button.addActionListener(e -> {
swingStuff.dispose();
});
... however the final variable placement and setter/getter would need a small reproducible code example.
And finally, as others have mentioned, System.exit(0) works quite fantastically well too, so as long as it doesn't break the lifecycle of any of your other components.
My test class:
import javax.swing.*;
import java.awt.*;
public class SwingStuff extends JFrame {
// Our main JFrame
public SwingStuff() {
super();
// The button
JButton button = new JButton("Close");
button.addActionListener(e -> {
SwingUtilities.getWindowAncestor((Component)e.getSource()).dispose();
});
// The JPanel and nested components
JPanel startupPanel = new JPanel();
startupPanel.add(button);
add(startupPanel);
pack();
// Make sure the app exits when closed
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
// Just our entry point
public static void main(String ... args) {
SwingUtilities.invokeLater(() -> {
new SwingStuff().setVisible(true);
});
}
}
I am trying to implement mouse listener however I can not seem to get it to work. My code doesnt have any errors, but when I click on the frame I I can not get a message to print out. I have tried extending the class HandleClassOne to viewOne, but that also wouldn't work. Any thoughts?
The main class creates a frame and then creates an instance of viewOne on the frame.
public class main{
protected static JFrame window;
public static void main(String args[]){
window = new JFrame();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(400,400);
window.setVisible(true);
new viewOne(window);
}
}
The viewOne class adds a panel and a label to a frame. It also adds a mouse listener to the panel.
public class viewOne {
private static JPanel panel1;
private static JLabel label1;
public viewOne(JFrame frame) {
panel1 = new JPanel();
label1 = new JLabel("View One");
panel1.add(label1);
frame.add(panel1);
panel1.setBackground(Color.red);
frame.validate();
}
public static void mouseAdd() {
HandleClassOne handle = new HandleClassOne();
panel1.addMouseListener(handle);
panel1.addMouseMotionListener(handle);
}
public static void main(String[] args) {
mouseAdd();
}
}
The HandleClassOne class should print out a message when the panel created in viewOne is clicked.
public class HandleClassOne extends main implements MouseListener, MouseMotionListener {
public void mouseClicked(MouseEvent e) {
System.out.println("mouse clicked");
}
}
While you have defined the function mouseAdd(...) I don't see you calling it.
Try (within the constructor)
public viewOne(JFrame frame) {
...
mouseAdd();
...
}
naturally, you'll need to do this after the panel1 is set.
Note that there are other issues, too
You don't invoke presenting the JFrame properly within your main function in your main class. Look up a basic tutorial on Java Swing, where it talks about the event dispatch thread and the requirements to not present within your program's main thread of execution.
You have an additional main function in your viewOne class, which is not how these things are wired up.
You added the mouseAdd() method (which is responsible for registering the mouse listener) inside the main method of viewOne class.
Please keep in mind that main method only gets called whenever you are running it as entry point class for your application. Here you have main class to act as an entry point.
You kept main method in viewOne class as well and it will get called only when you are running it as an individual piece (not along with main class).
To fix the issue here, keep your mouseAdd() method call inside viewOne() constructor as constructor gets called every time whenever object is getting created.
public viewOne(JFrame frame) {
panel1 = new JPanel();
label1 = new JLabel("View One");
panel1.add(label1);
frame.add(panel1);
panel1.setBackground(Color.red);
mouseAdd();
frame.validate();
}
I have this code sample. And I needed to change the background color of the JFrame when run the application.
But when I call the create a object of the class and call it with it's reference variable, the JFrame isn't showing up (I think it is stucked or something) I cannot even see the java icon in my taskbar.
Here's my code (Only the constructor of the class)
package lockme;
import java.awt.Color;
import javax.swing.JFrame;
public class MainWindow extends javax.swing.JFrame {
public MainWindow() {
initComponents();
MainWindow m=new MainWindow();
m.setSize(1368, 768);
m.getContentPane().setBackground(new Color(10, 20, 30));
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
MainWindow m=new MainWindow();
m.getContentPane().setBackground(new Color(100, 40, 20));//This is not working
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainWindow().setVisible(true);
}
});
}
}
`
But it shows the JFrame when I alter the code above like this:
package lockme;
import java.awt.Color;
import javax.swing.JFrame;
public class MainWindow extends javax.swing.JFrame {
public MainWindow() {
initComponents();
//MainWindow m=new MainWindow();
this.setSize(1368, 768);
this.getContentPane().setBackground(new Color(10, 20, 30));
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
//MainWindow m=new MainWindow();
this.getContentPane().setBackground(new Color(100, 40, 20));//This isworking
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MainWindow().setVisible(true);
}
});
}
}
Can anyone please tell me what's wrong here?
That's because you get stuck in an infinite loop by creating a new object of MainWindow inside the constructor of MainWindow, essentially trying to create an infinite amount of new Frames.
Since you're already inside the constructor of MainWindow you don't need to instantiate MainWindow again.
Your 2nd code shows the JFrame because this is the actual way it needs to be done.
In your 1st code, MainWindow() itself is a constructor whereas you are again calling another instance of MainWindow inside the same constructor which is completely wrong.
And guess what, you are calling the MainWindow again and again in its own constructor as it will work as infinite loop. That's why you stuck up there.
A constructor in Java is a block of code similar to a method that’s
called when an instance of an object is created.
But you need not to create the instance of the object inside the own constructor of any class.
Edit:
There are several mistakes in your 1st code snippet. Let me clear those for you:
MainWindow m=new MainWindow(); inside the constructor MainWindow(). It is totally illegal as I have mentioned earlier that it turns into an infinite loop.
So, the correct way of doing this is mentioned in your 2nd code snippet.
this.getContentPane().setBackground(new Color(10, 20, 30));
N.B.: By declaring above line inside constructor means it will show that during runtime.
Inside jButton2ActionPerformed(java.awt.event.ActionEvent evt) method, you are calling another object of MainWindow. This will run the code well but will not work as you wanted. Look here you are creating another object of that class. But may be you didn't want this. Now let me clear this by example:
Assume, at first in the constructor you have mentioned RED color in the setBackground() method. And then created another object of MainWindow inside jButton2ActionPerformed() and provided color BLUE as setBackground() . Now you run the program. The program initially runs well showing you the RED background colored Frame. But when you click on the button, guess what will happen. That red colored JFrame will remain as it is and as you are creating another instance of that class on button action, then after clicking on the button another new JFrame will appear having the color BLUE. And after you click the button for infinite no. of time, an infinite no. of new JFrame will be created. May be nobody wants that in any program unless any special case.
I want to find out if a JPanel is on the screen or not. It doesn't mean that isVisible() method could be used for this situation. I mean I want to find out whether a component that has been initiated before, presently is one of components on my main panel or not.
Edit and more explanation: I have several panels initiated before in my program and use them on my form as needed. I want to know for example jpanel1 in now on any of panels that now are present on my form.
Example:
public class GUI extends JFrame() {
private JPanel1, jPanel2;
public static void main(String[] args) {
GUI gui = new GUI();
jPanel1 = new JPanel();
jPanel2 = new JPanel();
gui.setContentpane(jPanel1);
gui.setVisible(true);
}
}
now jPanel1 is visible on screen bu jPanel2 is not visible.
How can I find out this?
After investigation I find out this method represents that the component is displayed on screen or not:
isDisplayable()
in my Example:
jPanel1.isDisplayable() // returns true
jPanel2.isDisplayable() // returns false
as Simple as this!
jPanel1.isVisible()==true
jPanel1.isVisible()==false
for panel
jPanel1.isShowing() also works
If you're looking for children of a main panel, you could call getComponents() on the main panel to return an array of its Components, then iterate through them to check if any of them are the Panel you are looking for. You may need to call this recursively if the panel is not a direct child of the main panel.
Write your own panel class that extends JPanel. Add a new method to this class named isOnTheScreen() which return a boolean indicating whether the panel is added to the window or not.
public class MyPanel extends JPanel
{
boolean isAdded = false;
public boolean isOnTheScreen()
{
return isAdded;
}
public void setOnTheScreen(boolean isAdded)
{
this.isAdded = isAdded;
}
}
After creating your own panel objects, use the methods above to learn whether a panel is added to main panel/frame or not. Suppose you have added a panel to a frame:
JFrame frame = new JFrame()
MyPanel panel = new MyPanel();
frame.getContentPane().add(panel);
panel.setOnTheScreen(true);
As soon as you add it to the main screen, in this case a frame, call setOnTheScreen(true)
And similarly call setOnTheScreen(false) when you remove the panel.
After this design you can determine whether a panel is added to the main window or not by just invoking isOnTheScreen() anywhere else in your code. I hope this design helps you.
I have a button in a JFrame, if pressed, it takes us to another frame.
I used this code:
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
SecondForm secondform = new SecondForm();
secondform.setVisible(true);
setVisible(false);
dispose();
}
So the new frame opens and everything is ok. Then i placed another button -in the second frame- in order to go back to the previous frame. I used this code:
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
MainForm Mform = new MainForm();
Mform.setVisible(true);
setVisible(false);
dispose();
}
The thing is, i don't think this is the right way to do this. What i want is to:
hide the first frame
show the new second one
dispose the second one
show again the first
Is there a way to do that using the first MainForm instance and not creating a new one every time i want to go back.
I monitored my program and every time i go back and forth the frames and as i suspected, the ram being used by it keeps increasing.
Thanks in advance.
EDIT : I have a login system and when the user put the correct credentials a new ManiForm instance is created.
MainForm Mform = new MainForm();
Mform.setVisible(true);
That is the instance i want to use. Ii there a way to make MForm visible again from the secondform?
First of all thanks for the help!
I agree that it is easier not to use more than one JFrames, but can you please tell me which is the better way to do what i asked in the first post?
The answer Robin gave me is very nice but i don't know what to put as an argument there*:
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
* new SecondForm().setVisible(true);
}
});
It's from the auto-generated code from NetBeans.
I tried
new SecondForm(super).setVisible(true);
but i still get compile errors. Apparently i must put super.something() but i don't know what. I tried many but no luck.
you shouldn't use more then one frame.
You should have NOTHING in JFrame except defaultExitOperation, size, preferedsize and visible true.
Instead place all buttons and fields into a JPanel and add/remove the JPanel from the JFrame.
If you want another Window open use JDialog.
btw: you can have your MainFrame setVisible false and open a JDialog with your MainFrame as parent. Only if someone writes down the right user + password you make the MainFrame visible.
For swing applications, the standard is to use a STATIC MAIN FRAME, in other words, make your main frame (mframe) static and add methods to pop-up new frames, dialogs, optionPanes, etc. You can even control the visibility of the main frame throw static calls. That's the way you implement a UNIQUE FRAME for your application, even tho you instance other frames for navigation, all child frames can refer to the main frame without the need of passing it as parameter to constructors or creating new instances of it.
The Main Class
`/* to start the application */
public class Main{
public static MainFrame MFRAME;
public static void main(String[] args){
/*use this for thread safe*/
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Main.MFRAME = new MainFrame(/*init parms to constructor*/);
}
});
}
}
`
The Main Frame
`/* to create the main frame */
public class MainFrame extends JFrame{
public MainFrame(/*your constructor parms*/){
/* constructor implementation */
}
public void openOtherFrame(/*your parms*/){
OtherFrame oFrm = new OtherFrame(/*your parms*/);
}
/* other methods implementation */
}
`
The child frame
`/* to open child frames controling the visibility of the main frame*/
public class OtherFrame extends JFrame{
public OtherFrame(/*your constructor parms*/){
/* hide main frame and show this one*/
Main.MFRAME.setVisible(false);
this.setVilible(true);
/* do something else */
/* show main frame and dispose this one*/
Main.MFRAME.setVisible(true);
this.dispose();
}
/* other methods implementation */
}
`
If you pass your MainForm to the SecondForm class (for example using a constructor parameter) the SecondForm instance can make the original MainForm instance visible again instead of creating a new one.
For example
public class SecondForm extends JFrame{
private final MainForm mainForm;
public SecondForm( MainForm form ){
mainForm = form;
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
mainForm.setVisible(true);
setVisible(false);
dispose();
}
}
and in your MainForm class
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
SecondForm secondform = new SecondForm( this );
secondform.setVisible(true);
setVisible(false);
dispose();
}