I know that this program needs window Closing function to close the frame but I don't know why
explanation would be helpful
public class NoLayoutDemo {
public static void main(String[] args) {
Frame frame= new Frame("no layout teset");
frame.setLayout(null);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent evt) {
System.exit(0);
}
}
According to java documentation
WINDOW_CLOSING:
If the program doesn't explicitly hide or dispose the window while processing this
event, the window close operation is canceled.
Then you have to do the close operation yourself, otherwise the close operation has no effect.
Hope this helps
Maybe like this?
public class NoLayoutDemo {
public static void main(String[] args) {
Frame frame = new Frame("no layout teset");
frame.setLayout(null);
frame.setSize(200, 300);
frame.show();
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent evt) {
frame.dispose();
}
});
}
}
Related
I am trying to make a Swing GUI that includes some 3D stuff using Java3D's Canvas3D object. The problem is that it takes a while for a Canvas3D object to initialize, and I want the Swing GUI to come up right away. My solution to this problem is to initialize the Canvas3D in a separate thread, and then add it to the JFrame once it is initialized. However, when that separate thread adds the Canvas3D to the JFrame, the window loses focus for a moment, which is undesirable. How can I prevent that from happening? I have included a simple example to illustrate what I am trying to do:
public class Main extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Main()::setup);
}
private void setup() {
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
Thread thread = new Thread() {
#Override
public void run() {
Canvas3D canvas = new Canvas3D(SimpleUniverse.getPreferredConfiguration());
SwingUtilities.invokeLater(() -> {
Main.this.add(canvas); //the window loses focus for a moment here
Main.this.revalidate();
});
}
};
thread.start();
}
}
I am using Java3D 1.7.1.
I have modified my code as per R VISHAL's comment, but the problem still persists.
public class Main extends JFrame {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Main()::setup);
}
private void setup() {
setSize(600, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
SwingWorker<Canvas3D, Object> worker = new SwingWorker<Canvas3D, Object>() {
#Override
public Canvas3D doInBackground() {
return new Canvas3D(SimpleUniverse.getPreferredConfiguration());
}
#Override
public void done() {
try {
Main.this.add(get());
} catch (InterruptedException|ExecutionException e) {
throw new RuntimeException();
}
Main.this.requestFocusInWindow();
Main.this.revalidate();
}
};
worker.execute();
}
}
Ok so this might not be the answer but it was to large to put it as an comment
Use a JPanel having a CardLayout as your frame's contentpane, have one screen inside this panel set as the background[or whatever initial screen you want to display before the canvas is displayed], and then once the canvas is initialized add it to the content pane as the second screen and then call the CardLayout's show() method do display the canvas
public class Add
{
public static void main(String args[])
{
JFrame frame=new JFrame("Test");
JPanel mainPanel=new JPanel(new CardLayout());
mainPanel.addMouseListener(new MouseAdapter()
{
int count=0;
#Override
public void mouseClicked(MouseEvent m)
{
System.out.println("Focus "+(++count));
}
});
JPanel background=new JPanel();
background.setBackground(Color.WHITE);
mainPanel.add("Screen1",background); //Initial Screen To Show Something To The User While Canvas Is Being Initialized
frame.setContentPane(mainPanel);
SwingWorker worker=new SwingWorker<Canvas3D,Object>()
{
#Override
public Canvas3D doInBackground(){return new Canvas3D();}
#Override
public void done()
{
try
{
mainPanel.add("Screen2",get()); //Add Canvas To MainPanel
CardLayout layout=(CardLayout)mainPanel.getLayout();
layout.show(mainPanel,"Screen2"); //Remember This While Using CardLayout
}
catch(InterruptedException | ExecutionException ex){}
}
};
frame.setSize(500,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
worker.execute();
}
private static final class Canvas3D extends JPanel
{
private Canvas3D()
{
super(new BorderLayout());
try{Thread.sleep(5000);}//Mimicing Long Operations
catch(Exception ex){}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0,0,500,500);
g.setFont(new Font("",Font.BOLD,15));
g.setColor(Color.RED);
g.drawString("CANVAS 3D",100,100);
}
}
}
Of course you would use your actual canvas3d instead of this custom one and there is no need to revalidate or requestFocus()
If you are still worried about focus you could always create an javax.swing.Timer class to request focus to your mainPanel or frame[Or Both See What Works For You] every second/or millisecond
Timer timer=new Timer(1000,new ActionListener() //milliseconds make it 1 if your are dead serious about focus
{
#Override
public void actionPerformed(ActionEvent e)
{
mainPanel.requestFocusInWindow();
frame.requestFocusInWindow(); //May not be required since we are already requesting focus in mainPanel
}
});
timer.start();
If you want to get even more paranoid about focus you could always add an focus listener
mainPanel.addFocusListener(new FocusListener()
{
#Override
public void focusLost(FocusEvent e)
{
mainPanel.requestFocusInWindow();
frame.requestFocusInWindow();
}
#Override
public void focusGained(FocusEvent e){}
});
If any of these suggestions did/didn't work comment below :)
Hi I created this java code for AWT Window
package labelExample;
import java.awt.*;
import java.awt.event.*;
public class labelExample extends Frame implements ActionListener{
Frame f;
TextField tf; Label l; Button b;
labelExample(){
Frame f=new Frame("Label Example");
tf=new TextField("www.google.de");
tf.setBounds(50,50, 150,20);
l=new Label();
l.setBounds(50,100, 250,20);
b=new Button("Find IP");
b.setBounds(50,150,60,30);
b.addActionListener(this);
add(b);add(tf);add(l);
setSize(400,400);
setLayout(null);
setVisible(true);
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
f.dispose(); // use dispose method
}
}
);
}
public void actionPerformed(ActionEvent e) {
try{
String host=tf.getText();
String ip=java.net.InetAddress.getByName(host).getHostAddress();
l.setText("IP of "+host+" is: "+ip);
}catch(Exception ex){System.out.println(ex);}
}
public static void main(String[] args) {
new labelExample();
}
}
When I try to close the window by pushing the X button, nothing happens. The windows
stays open. I made these changes my example code:
public class labelExample extends Frame implements ActionListener{
I added new awt-frame f with name the "Label Example".
frame f;
frame f=new Frame("Label Example");
And added this code to close the frame
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
f.dispose(); // use dispose method
}
}
);
How do have change my code to fix this problem ?
I believe that in labelExample(){ ... } you should add a line setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); to close the window.
I am trying to figure out how can we exit the application with button click.
The problem i faced which makes me unable to exit the application is because i am using "extend JFRame" from the main class.
For an example,
app.class
public class app{
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
JFrame frame = new MainFrame("Exercise one");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
.. .. ..
frame.setVisible(true);
})
}
}
MainFrame.java
public class MainFrame extends JFrame(){
public MainFrame(String title){
super(title)
//set layout manager
setLayout(new BorderLayout());
//swing components
JButton exit = new JButton("Exit");
//add container
Container container = getContentPane();
container.add(exit);
//create actionlist logic
exit.addActionListener(new ActionListener()){
#Override
public void actionPerformed(ActionEvent arg0){
// on click , this logic will end the application
}
}
}
}
I fully understand how i can cancel the application from app class.But in scenarios where i want to cancel the application from MainFrame.Can it be done ?
Thank you in advance.
The defaultCloseOperation is only processed by the frame when it encounters a WINDOW_CLOSING event, neither setVisible or dispose trigger this event, which means the the defaultCloseOperation won't be processed
The only way to ensure that this operation is triggered is to manually dispatch a WINDOW_CLOSING event
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
One of the main reasons for wanting to follow this path is that it ensures the application is following the configured defaultCloseOperation and making up it's own mind (like calling System.exit manually)
The following demonstrates hiding, disposing and dispatching approaches. Only the dispatch approach will close the window and terminate the JVM
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.AbstractAction;
import static javax.swing.Action.NAME;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.HORIZONTAL;
frame.add(new JButton(new HideAction(frame)), gbc);
frame.add(new JButton(new DisposeAction(frame)), gbc);
frame.add(new JButton(new DispatchAction(frame)), gbc);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.out.println("Closing");
}
#Override
public void windowClosed(WindowEvent e) {
System.out.println("Closed");
}
});
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class HideAction extends AbstractAction {
private JFrame frame;
public HideAction(JFrame frame) {
this.frame = frame;
putValue(NAME, "Hide");
}
#Override
public void actionPerformed(ActionEvent e) {
frame.setVisible(false);
}
}
public class DisposeAction extends AbstractAction {
private JFrame frame;
public DisposeAction(JFrame frame) {
this.frame = frame;
putValue(NAME, "Dispose");
}
#Override
public void actionPerformed(ActionEvent e) {
frame.dispose();
}
}
public class DispatchAction extends AbstractAction {
private JFrame frame;
public DispatchAction(JFrame frame) {
this.frame = frame;
putValue(NAME, "Dispatch");
}
#Override
public void actionPerformed(ActionEvent e) {
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
}
}
If I run this in my IDE, unless I use the dispatch option, the JVM is left running and I have to terminate the session to close it fully.
I also noted that calling dispose only triggers the WINDOW_CLOSED event, while the dispatch method will trigger the WINDOW_CLOSING event
Problem solved.
Credits to #XtremeBaumer.
Basically, when using "classname" extend JFRame.
We can input dispose() which will kill the application completely. This will causes the JFrame window to be destroyed and cleaned up by the operating system. :)
Indeed, dispose() is the right solution. I also suggest to add a pack() call so the UI shows up properly:
public class MainFrame extends JFrame {
public MainFrame(String title) {
super(title);
...
// create actionlist logic
exit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
System.out.println("--> closing app programmatically");
MainFrame.this.dispose();
}
});
this.pack();
}
}
You can test the events with a WindowListener on the MainFrame. They are invoked as if the user pressed the close button:
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame = new MainFrame("Exercise one");
frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
// .. .. ..
frame.setVisible(true);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.out.println("--> closing...");
}
public void windowClosed(WindowEvent e) {
System.out.println("--> closed...");
}
});
}
});
}
I have copied most of my Code from an oracle-example, so I think at least the code I did not add should be correct and I donĀ“t like to change that. But in the oracle-code I can not implement this line to properly close my JFrame: frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
private static void createGUI() {
JFrame frame = new JFrame("NameChooser");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
...
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createGUI();
}
});
}
public void actionPerformed(ActionEvent e) {
if (e.getSource()==skipButton){
frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING)); WindowEvent.WINDOW_CLOSING)); // does not work ofc
}
}
How can I close my JFrame in the actionPerformed-method without destroying this correct way of opening a JFrame ?
Or is this oracle-code just suitable for examples and not for real applications ?
You should make frame an instance field like this:
private static JFrame frame;
private static void createGUI()
{
frame = new JFrame( "NameChooser" );
...
}
The JFrame provides a method setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) . I want to run some code before this Frame is actually closed. How do I do that ?
JFrame frame = new JFrame();
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
// The window is closing
}
});
Implement WindowListener and capture window closing event. Something like-
yourWindow.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
// do something here
}
});
Do this
frame.addWindowsListener(new WindowAdapter() {
public void windowClosing() {
// do your work here
frame.dispose();
}
}
Please refer WindowListener documentation