I have a JFrame with a Button that opens a different JFrame. But I want the button to only open the second frame once. Problem is, every time I click it I get a new instance of the frame. This must be a very common problem, since I'm following a book on how to create this GUI. I find it odd that the author didn't mention this "feature".
So how do I keep my button from opening multiple copies of the new frame?
Instead of letting the button create a new JFrame every time, make the second JFrame a member of the first JFrame, and only let the button call jframe2.setVisible(true);:
class JFrame1 {
JFrame2 jframe2=...;
JButton button=...;
JFrame1() {
...
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
jframe2.setVisible(true);
}
});
...
}
}
UPDATED!
try this:
JFrame frame2 = new JFrame(); // instance variable
...
//when button is clicked
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(!frame2.isVisible())
frame2.setVisible(true);
}
});
make sure you are handling the closing of all of the JFrames manually like this:
frame2.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
// handle closing the window
frame2.setVisible(false);
frame2.dispose();
}
});
instead of using the JFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
hope this helps.
You should keep a reference to the sub frame you open for first time. At second time you first check if you have a reference or not and then decide to create a new frame or to put the focus onto the existing open frame.
Example as answer to comment of OP (similar to other answer of #AlexanderTorstling, but not immediately creating the sub frame):
class MainFrame extends JFrame {
private JFrame subFrame = null;
MainFrame() {
...
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (subFrame == null) {
subFrame = new JFrame();
...
}
subFrame.setVisible(true);
}
});
}
}
This example has also the advantage to give you the possibility to close the subframe via a registered WindowAdapter if the main frame is closed.
please try this one
JFrame frame2 = new JFrame(); // instance variable
boolean secondWindowIsOpne = false;
...
//when button is clicked
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(secondWindowIsOpne == false){
frame2.setVisible(true);
secondWindowIsOpne = true;
}
else{
System.out.println("This Window is already running");
}
});
make sure you are handling the closing of all of the JFrames manually like this:
frame2.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
// handle closing the window
secondWindowIsOpne = false;
frame2.setVisible(false);
frame2.dispose();
}
});
Related
I'm having some problems while working on a project for school. The JDialog renders very slow. Let me show you.
This is the GUI:
When I click "Advance time" it takes around 3 seconds to open the JDialog. When it's open I get this (which is fine):
But when I drag that JDialog around, I get this (which is not ok):
It also takes very long to close the JDialog. It closes, but you can still see it:
This is the snippet of code where I think the problem lays, it's the code for the menu-bar:
private JMenu editMenu()
{
JMenu editMenu = new JMenu("Edit");
editMenu.setMnemonic(KeyEvent.VK_E);
JMenuItem advanceTimeMenuItem = new JMenuItem("Advance time");
advanceTimeMenuItem.setMnemonic(KeyEvent.VK_A);
advanceTimeMenuItem.setToolTipText("Advance the internal clock");
advanceTimeMenuItem.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent event)
{
//We first create panel to add to the dialog.
JPanel panel = new JPanel();
//Calendar
AdvanceTimePanel calendar = new AdvanceTimePanel(internalClockController);
//Button that will be used to confirm the system time change.
JButton btnSave = new JButton("Save");
//Add actionlistener to the save button
btnSave.addActionListener(new ActionListener(){
#Override
public void actionPerformed(ActionEvent e)
{
Date selectedDate = calendar.getDate();
try
{
internalClockController.updateDateTime(selectedDate);
} catch (InvalidInternalClockException e1)
{
System.out.println("InvalidInternalClockException: " + e1.getMessage());
}
}
});
//Add the components to the panel.
panel.add(btnSave);
//This is the calendar added to the panel.
panel.add(calendar);
//Create the dialog and add the panel to it.
JDialog jDialog = new JDialog();
jDialog.add(panel);
jDialog.setBounds(100, 100, 400, 200);
jDialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
jDialog.setVisible(true);
}
});
editMenu.add(advanceTimeMenuItem);
Does someone have an idea how to speed things up?
Thanks in advance.
Events are handled on one single thread. (Also repaint events.) For the application to remain
responsive, perform longer actions a bit later by using invokeLater, as below:
#Override
public void actionPerformed(ActionEvent event)
{
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
... // All code here
}
});
}
This is quite wordy; Java 8 allows:
advanceTimeMenuItem.addActionListener(
(event) -> {
EventQueue.invokeLater(
() -> {
... // All code
});
});
I've looked through topics on how to open only one window when a button is clicked but none of the solutions there helped, perhaps because my code was structured a bit differently.
So I have a main window class extending JFrame and one of the buttons is supposed to open a new window when clicked. I have defined the widgets/panels etc for the new window in a separate class. At the moment, every time I click on the button a new window is opened. I want to make it so that if a window is already opened then it would switch to that window once the button is clicked again.
Here is a bit of my code:
public class MainWindow extends JFrame{
/*
* create widgets and panels
*/
Button.addActionListener(new ActionListener() { // the button that opens
//a new window
#Override
public void actionPerformed(ActionEvent e) {
Window2 ww = new Window2(); //creating the new window here
}
});
}
NB. The Window2 class is also extending JFrame, if that's of any help.
Thanks
pull out ojbect creation from actionPerformed method beacuse each time you click button it's create new object. below can help you :-
Make a Window2 class singalton for more detail about singalton click here.
2 . add null check as below :-
....
Window2 ww = null; // static or instence variable
......
#Override
public void actionPerformed(ActionEvent e) {
if(ww==null)
{
ww = new Window2();
ww.someMethod();
}
else
{
ww.someMethod();
}
}
});
Here is a full working example:
Window2.java
public class Window2 extends JFrame {
private static final long serialVersionUID = 7843480295403205677L;
}
MainWindow.java
public class MainWindow extends JFrame {
private static final long serialVersionUID = -9170930657273608379L;
public static void main(String[] args) {
MainWindow mw = new MainWindow();
mw.go();
}
private void go() {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
private void createAndShowGUI() {
JButton button = new JButton("Click me");
button.addActionListener(new ActionListener() {
private Window2 ww = null;
#Override
public void actionPerformed(ActionEvent e) {
if (ww==null) {
ww = new Window2(); //creating the new window here
ww.setDefaultCloseOperation(HIDE_ON_CLOSE);
ww.setTitle("Window2 created on " + new Date());
ww.setSize(500, 200);
}
pack();
ww.setVisible(true);
}
});
setLayout(new BorderLayout());
add(button);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
pack();
setVisible(true);
}
}
What you can try is make two windows and put the actionPeformed method in the main class so that when the button is pressed it displays the second window
I currently have a button that, when clicked, performs a method that creates a jframe with a panel that loads multiple images. If this button is clicked multiple times, the images keep adding onto the prexisting images loaded onto the jframe. What code should I use so that if the button is clicked after the jframe and elements have been loaded, after clicking once, nothing else will be added.
Many thanks
What about:
public void actionPerformed(ActionEvent evt) {
button.setEnabled(false);
// the other code that creates imgFrame
imgFrame.addWindowListener(new WindowAdapter() {
#Override public void windowClosing(WindowEvent evt) {
button.setEnabled(true);
}});
imgFrame.setVisible(true);
}
don't create lots of JFrames on the runtime, because these Object never gone from Used JVM Memory untill current JVM instance exist
you have look at CardLayout that very confortly to solve your issues with multiple of views (in this case in one JFrame)
put Images as Icon/ImageIcon to the JLabel
Disable the button when frame show up, and when the frame close, enable the button.
public void actionPerformed(ActionEvent evt) {
final JButton finalButton = button;
button.setEnabled(false);
JFrame frame = new JFrame()
{
protected void processWindowEvent(WindowEvent e)
{
if (e.getID() == WindowEvent.WINDOW_CLOSING)
{
finalButton.setEnabled(true);
}
super.processWindowEvent(e);
}
};
frame.setVisible(true);
}
I suggest a boolean that is false when the program starts, and then when the button is clicked, it tests if the boolean is false. If it is false, then create the stuff that you want, and then make it true. If it is true, do nothing, or alert the user not to click the button more that once, or something of that matter
boolean isAlreadyCreated = false;
yourButton.addActionListener(new ActionListener()
{
if(!isAlreadyCreated)
{
//CREATE YOUR NEW FRAME
isAlreadyCreated = true;
}
});
I would like to use setAlwaysOnTop(boolean) in java.
I want to setAlwaysOnTop() when I click on a JButton and this JButton has its own actionListener
My Problem is I don't know how to set the JFrame on top at this situation, because it's not inside the constructor nor there is a method getFrame()
I tried creating a method inside the constructor but it does not work :S.
UPDATE:
private class optionAction implements ActionListener{
public void actionPerformed(ActionEvent e){
if(e.getSource() == onTop) //onTop is a menuItem when I click it it should make the frame Always on top.
frame.setAlwaysOnTop(true); //This does not work of course just to demonstrat you what I want to do
}
}
The following code lines show you how it can be done with a direct implementation of ActionListener() assigned to a button declared inside the constructor. (You can also do this anywhere else in your class.)
class MyFrame extends JFrame {
public MyFrame() {
// ...
JButton button = new JButton("PRESS");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
setAlwaysOnTop(true);
// Alternatively use MyFrame.this.setAlwaysOnTop(true);
}
});
add(button);
// ...
}
}
An idea might be to pass a reference to your JFrame to the constructor of your implementation of the ActionListener.
Maybe something like this:
class MyActionListener implements ActionListener {
private JFrame jFrame;
public MyActionListener(JFrame jFrame) {
this.jFrame = jframe;
}
public void onClick(Event event) {
jFrame.setAlwaysOnTop(true);
}
}
create a boolean called ontop
boolean ontop = false;
jbutton.addActionListener(new ActionListener()) {
public void actionPerformed(ActionEvent e){
if (ontop) {
frame.setAlwaysOnTop(false);
ontop = false;
}
else {frame.setAlwaysOnTop(true); ontop = true}
});
The correct working code for this question is below:
private class optionAction implements ActionListener{
public void actionPerformed(ActionEvent e){
if(e.getSource() == onTop) //onTop is a menuItem
setAlwaysOnTop(true); //This does not work of course just to demonstrate you what I want to do
}
}
The reason this is does not work because I was setting the setAlwaysOnTop on a JFrame object, which it doesn't exists in that class.
To set the setALwaysOnTop on a JFrame you have to remove the frame. and just add `setAlwaysOnTop()
I have a class developed with windowbuilderpro that i want to close also from a JButton further than with the standard X button on the window, so here the example of the class :
public class MainWindow {
public JFrame frame;
public MainWindow() {
initialize();
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
public void show() {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
//Show the main Frame
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
When i close the window from the X button the window close correctly and the process terminate.
When i close instead from a JButton that have this listener :
mntmExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Close the application main form
frame.setVisible(false);
frame.dispose();
}
});
the frame window close correctly but the process remain alive ... Why ?
As you can see there is an AWT-Shutdown thread that start and terminate continuously, How can i achieve the same behaviour of the X button that close also the application process ?
Notes :
System.exit(0); is not suitable because it terminate the application also if there are another background running thread and i don't want that . The MainWindow class should close and release it's resource, the same behaviour that have closing the application with the X button that close the MainWindow instance but if there are background thread running it doesn't kill they but wait until they finished their work...
Enviroment :
JDK 7
Eclipse 3.7.1
not sure what you really needed, that looks like that you create new JFrame again an again, don't do that, create JFrame once and re-use this Container
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // do nothing
frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); // same as setVisible(false)
then for visibily you can only to call frame.setVisible(true);
for more Confortable is override WindowListener, then you can control some Events
All threads in this code stop when either the x button or the Exit button are activated. Are you getting different behavior?
import java.awt.event.*;
import javax.swing.*;
public class MainWindow {
public JFrame frame;
JButton mntmExit = new JButton("Exit");
public MainWindow() {
frame = new JFrame("Close Me!");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
mntmExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Close the application main form
frame.setVisible(false);
frame.dispose();
}
});
frame.add(mntmExit);
frame.pack();
show();
}
public void show() {
//Show the main Frame
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
MainWindow mw = new MainWindow();
mw.show();
}
});
}
}
Just add one line:
System.exit(0);