Execute actions in main() after closing JFrame - java

I am sorry, for I believe that this question has been asked already, but none of the answers have actually helped me out.
I have a class with gui, it contains a JFrame with several textfields and buttons. Here's the main() I'm trying to get working:
Gui interface1 = new Gui();
interface1.setSize(200,200);
interface1.setVisible(true);
//hold main execution
//wait for the pressed button in gui
//close the jframe
//proceed with main()
call_some_functions();
I have tried setting default close operation to HIDE_ON_CLOSE but that doesn't seem to be what I want. I'm using a framework and I need main() to be alive for quite a long time.
Basically, I need jframe to hold the main() for the time of user input and updating parameters, then close itself without terminating the process and continue with main() as if nothing has happened.
Thanks in advance for any help.

Uses a JDialog instead of JFrame and make the JDialog modal, using JDialog#setModal to true
See How to use dialogs for more information

Use :
frame.setDefaultCloseOperation(frame.HIDE_ON_CLOSE);
EG:
import javax.swing.JFrame;
import javax.swing.JTextField;
public class TestFrame {
public static void main(String aa[])
{JFrame frame =new JFrame();
JTextField field=new JTextField("hello buddy..nuthin happnd");
frame.setDefaultCloseOperation(frame.HIDE_ON_CLOSE);
frame.add(field);
frame.pack();
frame.setVisible(true);
}
UPDATE AS PER YOUR NEEDS:
import javax.swing.JFrame;
import javax.swing.JTextField;
public class TestFrame {
public static void main(String aa[])
{
JFrame frame =new JFrame();
JTextField field=new JTextField("hello buddy..nuthin happnd");
frame.setDefaultCloseOperation(frame.HIDE_ON_CLOSE);
frame.add(field);
frame.pack();
frame.setVisible(true);
frame. addComponentListener(new java.awt.event.ComponentAdapter() {
public void componentHidden(java.awt.event.ComponentEvent evt) {
formComponentHidden(evt);
}
});
}
private static void formComponentHidden(java.awt.event.ComponentEvent evt) {
somefunction();
}
public static void somefunction()
{
System.out.println("hii!! i am hidden!!");
}
}

Related

How to update Swing Components in Real Time

I am programming a multiplication app for very large integers, I need to update every sigle step of the multiplication in a Swing component ( I created a JPane extended class with a JTextArea in it, then add it to the JFrame inside a ScrollPane). The issue is that this Swing component only updates once the multiplication algorithm is done. I tried using a Thread that would call repaint method of the Pane every 10 ms, but it did not work. The next is a sample of the problem.
This is the main Frame class:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Frame extends JFrame implements ActionListener{
private Console console;
private JButton calculate;
private Calculator calculator;
public Frame(){
console=new Console();
calculate=new JButton("Calculate");
calculate.addActionListener(this);
calculate.setActionCommand("");
calculator=new Calculator(this);
this.setLayout(new BorderLayout());
this.add(console,BorderLayout.CENTER);
this.add(calculate, BorderLayout.NORTH);
this.setTitle("Frame");
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(new Dimension(500,500));
this.setLocationRelativeTo(null);
}
public void writeOnConsole(String txt){
console.write(txt);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if(e.getActionCommand().equals("")){
console.clear();
calculator.calculate();
}
}
public static void main(String[] args) {
new Frame();
}
}
This is the Console Class
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.TitledBorder;
public class Console extends JPanel{
private JTextArea area;
public Console(){
this.setBorder(new TitledBorder("Console:"));
area=new JTextArea();
this.setLayout(new BorderLayout());
JScrollPane scroll=new JScrollPane(area);
this.add(scroll,BorderLayout.CENTER);
}
public void clear(){
area.setText("");
}
public void write(String txt){
area.append(txt+"\n");
}
}
Finally, this is the Calculator class (the one responsible for calling the writing)
public class Calculator {
private Frame parent;
public Calculator(Frame f){
parent=f;
}
public void calculate(){
for (int i = 0; i <= 1000000; i++) {
parent.writeOnConsole("Iteration "+i);
}
}
}
Note that if you run the program, the GUI will freeze until the Calculator class is done with the loop.
if you have a layout like a BorderLayout and you want to update it inside the JFrame do as bellow
JFrame frame = new JFrame();
BorderLayout layout = new BorderLayout();
layout.layoutContainer(frame.getContentPane());// use the frame as the border layout container
else you can use JFrame pack() method. The pack method packs the components within the window based on the component’s preferred sizes. it's not for updating but it updates the JFrame which is kind of a trick
JFrame frame = new JFrame();
//change the components dynamically
frame.pack();
or use Container methdod validate(). Validating a container means laying out its subcomponents. Layout-related changes, such as setting the bounds of a component, or adding a component to the container.
JFrame frame = new JFrame();
Container container = frame.getContentPane();
container.validate();
or if you want to update an specific component use
Component component = new JPanel();
component.repaint();
If this component is a lightweight component, repaint() method causes a call to this component's paint method as soon as possible .
or if you want for example numerous changes happen one by one dynamically then you could use the code below which is completely different from the things i said above. for that you could use platform.runlater() inside another thread which deals with everything that is about to change in realtime
new Thread(new Runnable()
{
#Override
public void run()
{
Platform.runLater(new Runnable()//use platform.runlater if you are using javafx
{
#Override
public void run()
{
try
{Thread.sleep(50);}catch(Exception e){}//use it in for loop where changes happen
//do some realtime change of components
}
});
}).start();
your Console class would be
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.border.TitledBorder;
public class Console extends JPanel{
private JTextArea area;
public Console(){
this.setBorder(new TitledBorder("Console:"));
area=new JTextArea();
this.setLayout(new BorderLayout());
JScrollPane scroll=new JScrollPane(area);
this.add(scroll,BorderLayout.CENTER);
}
public void clear(){
area.setText("");
}
public void write(String txt){
area.append(txt+" "+"\n");
}
}
and the Calculator class is
public class Calculator {
private Frame parent;
public Calculator(Frame f){
parent=f;
}
public void calculate(){
new Thread(new Runnable() {
#Override
public void run()
{
for (int i = 0; i <= 100; i++) {
try
{
Thread.sleep(50);
}
catch(Exception e)
{
e.printStackTrace();
}
parent.writeOnConsole("Iteration "+i);
}
}
}).start();
}
}
as you can see i used another thread to do the changes
try the update method to call paint method for maintain every change

Swing code compilation error "missing ;"

How do I solve this compilation error? Note that I'm new to Swing.
http://prntscr.com/bpz2ve
package gui;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
public class GUI extends Frame {
public static void main(String[] args) {
JFrame frame = new JFrame("Hello World - YaBoiAce");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 300);
// Layout //
frame.setLayout(new BorderLayout());
// Swing Component //
final JTextArea textarea = new JTextArea();
JButton jbutton = new JButton("Click me");
// Add Component to content pane
Container c = frame.getContentPane();
c.add(textarea,BorderLayout.CENTER);
c.add(jbutton, BorderLayout.SOUTH);
// Action Listener
jbutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
textarea.append("Hello");
} // Eclipse says 'missing ;' on this line.
}
private static void setDefaultCloseOperation(int exitOnClose) {
}
}
Eclipse says "Missing ;" But when I put that in, It highlights the ; saying "Missing ;" again. It keeps on doing that. Any help?
It is on the line marked with:
// Eclipse says 'missing ;' on this line.
There are many problems in your code:
As stated in the
comments
by #HovercraftFullOfEels:
You're not matching closing parenthesis on your addActionListener method too. Again good code formatting will help you see this.
// Action Listener
jbutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
textarea.append("Hello");
} // Eclipse says 'missing ;' on this line.
}); //HERE YOU NEED TO ADD: );
You're extending Frame (Maybe you were trying to extend JFrame)
and creating a JFrame object, choose which one you want to use
(Recommended to create the object instead of extending, because if
you extend a JFrame your class is a JFrame and cannot be
included somewhere else and you're not changing it's functionallity
either so, no need to extend).
You're creating a private static method
private static void setDefaultCloseOperation(int exitOnClose) {}
That method should be public and belongs to JFrame class, I guess your IDE wrote that when you extended Frame instead of JFrame.
Frame belongs to java.awt while JFrame belongs to javax.swing so, they are not the same.
You're creating your windows and every component inside your main
method instead of the constructor
You're adding your components to a Container but never add that container to your JFrame, so you need to call
frame.setContentPane(c);
So your code should look like this:
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class GUI {
JFrame frame;
public GUI() {
frame = new JFrame("Hello World - YaBoiAce");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.setSize(500, 300);
// Layout //
frame.setLayout(new BorderLayout());
// Swing Component //
final JTextArea textarea = new JTextArea();
JButton jbutton = new JButton("Click me");
frame.add(textarea,BorderLayout.CENTER);
frame.add(jbutton, BorderLayout.SOUTH);
// Add Component to content pane
Container c = frame.getContentPane();
c.add(textarea,BorderLayout.CENTER);
c.add(jbutton, BorderLayout.SOUTH);
frame.setContentPane(c);
// Action Listener
jbutton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
textarea.append("Hello");
} // Eclipse says 'missing ;' on this line.
});
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new GUI());
}
}

Is it possible to perform some action BEFORE a JFrame is minimized?

In Swing, there are several ways to capture the event of minimizing a frame (iconifying), but the event happens when the frame is ICONIFIED which means after the frame becomes invisible from the screen.
Now I wish to run some code before disappearance of the frame -- immediately when I click the taskbar button.
In other words, do something when the JFrame is "about to" (NOT AFTER) be minimized. Is it possible to do this?
Use WindowStateListener, and call WindowEvent#getNewState() and check against Frame.ICONIFIED.
Here is an example:
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public Test() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel() {
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 300);
}
};
frame.add(panel);
frame.addWindowStateListener(new WindowAdapter() {
#Override
public void windowStateChanged(WindowEvent we) {
if (we.getNewState() == Frame.ICONIFIED) {
System.out.println("Here");
}
}
});
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test();
}
});
}
}
Create your own JFrame and override setExtendedState method.
public class MyFrame extends JFrame{
....
setExtendedState(JFrame.ICONIFIED);
....
#Override
public void setExtendedState(int state) {
// your code
super.setExtendedState(state);
};
}
Answer to the question "Is it possible to perform some action BEFORE a JFrame is minimized?"
I would say no unfortunately, I checked the native code for openjdk (windows) for frame and window that sends these events to java-space. And as I understand it, it is a callback from the windows API VM_SIZE message. And the SIZE_MINIMIZED is sent when "The window has been minimized" and is not getting any messages before the actual minimization.

Java GUI won't display JLabel

I would like to create a simple GUI in Java. I know the basics of creating JLabel, etc. However, I cannot find why my JLabel is not displayed on the screen. Here is my code:
package test;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
public class A1Panel extends JPanel implements ActionListener {
JLabel firstInt;
public void init() {
makeComponents();
makeLayout();
}
private void makeComponents() {
firstInt = new JLabel("First argument");
firstInt.setFont(new Font("Helvetica", Font.BOLD, 16));
firstInt.setBackground(Color.lightGray);
firstInt.setVisible(true);
firstInt.setHorizontalAlignment(SwingConstants.CENTER);
}
private void makeLayout() {
add(firstInt);
}
public void actionPerformed(ActionEvent e) {
}
}
I then add my JPanel to my JFrame using a different class called GUI:
import test.A1Panel;
public class GUI {
public static void main(String[] args) {
JFrame frame = new JFrame("Testing GUI");
frame.setLayout( new GridLayout(1,3));
JPanel panel = new A1Panel();
panel.setBorder( BorderFactory.createRaisedBevelBorder() );
frame.add( panel);
frame.setSize(800,600);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}
}
When I hit compile, what I get is a simple frame with three empty panels. I do not understand why my JLabel is not in the first panel since I have added it to my frame. Am I missing something?
The frame is not empty, the panel is. Nowhere in your code do I see a call to the methods init() or makeComponents(). In fact, I would turn your init() method into a constructor, like so:
public A1Panel() {
makeComponents();
makeLayout();
}
Another alternative to this would be to call panel.init() after declaring JPanel panel = new A1Panel()
After you instance A1Panel, you haven't called A1Panel.init()
I would suggest removing init() and adding all the code to the constructor of A1Panel. If, however, you wanted to keep the init() function, you would want to call it after JPanel panel = new A1Panel()
The code to add the label was not actually called in the main, was it? So look carefully, when is init actually called?
Look at the
private void makeLayout()
method.
If I replace public void init() by A1Panel(), it does the job. Thank you for your help.

Displaying JFrame

I'm having issues figuring out how to open one window when another closes if the other window is initiated within a sub class. Here is the clumsy code I am trying to use, but it halts the setting visible of the sub classe's window. Perhaps due to it being within an action event or perhaps it is halting the main thread.
tutorial = new tutorialWindow();
this.setVisible(false);
tutorial.setLocationRelativeTo(null);
tutorial.setVisible(true);
tutorial.setCurrentUser(users.getCurrentUser());
while(tutorial.isOpen() == true ) {
}
this.setVisible(true);
users.updateUser(tutorial.getCurrentUser());
My thoughts were that it would just get stuck in the section of code until the other window closes and would then appear again when the tutorialWindow has a Open boolean set to false due to it breaking the while loop.
Im sure this is a matter of using correct threads, or perhaps the various notify methods but as of now I am not sure how to do that.
You could do it using WindowListener. In the following sample WindowAdapter implements WindowListener and I just override the public void windowClosed(final WindowEvent e) method, opening the second window.
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class TestJFrame {
public static void main(final String args[]) {
JFrame jFrame1 = new JFrame();
jFrame1.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
jFrame1.add(new JLabel("First JFrame"));
jFrame1.pack();
final JFrame jFrame2 = new JFrame();
jFrame2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
jFrame2.add(new JLabel("Second JFrame"));
jFrame2.pack();
jFrame1.addWindowListener(new WindowAdapter() {
#Override
public void windowClosed(final WindowEvent e) {
jFrame2.setVisible(true);
}
});
jFrame1.setVisible(true);
}
}

Categories