I am writing a script which will call a bunch of other scripts, passing proper parameters when necessary. Since multiple scripts are being called, multiple points of failure are possible. If a script fails halfway through the flow, it is logged and the user will be prompted to resume from that position when the program next starts.
Both a server and a user have the ability to start the program. One is autonomous, one is not. In the case of autonomy, I want the prompt to resume to have a 10 second timeout so if no input is received, the script will just start at the beginning.
I have moved from the static showOptionDialog to a JOptionPane constructed dialog so I can access it programmatically to kill it after 10 seconds. My issue is with the constructor, no prompt will occur.
What I have tried:
I have verified the code is entering the code block via the debug
Log() script below.
As you can see, I have tried adding a JFrame
constructor. The JFrame constructor, .add(), and
frame.SetVisible(true) are new additions that have yielded no prompt
as well.
I have also commented out the 10 second
dialog.setVisible(false) just in case it was getting called
prematurely.
I am sure I'm missing something obvious, but I can't see it.
if(foundErroredScript != null)
{
Log("debug - Found errored script, \"" + foundErroredScript + "\"");
//Resume prompt
Object[] options = {"Yes, resume", "No, start over"};
JFrame frame = new JFrame();
JOptionPane pane = new JOptionPane("Would you like to resume from \"" + foundErroredScript + "\", AKA the last run script which errored?",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options);
frame.add(pane);
final JDialog dialog = pane.createDialog("Found last errored module");
Timer timer = new Timer(10000, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//dialog.setVisible(false);
}
});
timer.setRepeats(false);
timer.start();
frame.setVisible(true);
dialog.setVisible(true);
Log("User selected " + pane.getValue());
I figured it out.
After following mKorbel's advice to simplify and isolate, I moved the JOptionPane to its own simple class. I accidentally flipped the MessageType and OptionType. The program threw an exception when isolated, but doesn't when running inside the main program. This happens because the main program logic, which branches out from a class constructor, is originally called from the Main method which throws IOException.
So instead of this,
JOptionPane pane = new JOptionPane("Would you like to resume from \"here\", AKA the last run script which errored?",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
options);
it should be this,
JOptionPane pane = new JOptionPane("Would you like to resume from \"here\", AKA the last run script which errored?",
JOptionPane.QUESTION_MESSAGE,
JOptionPane.YES_NO_OPTION,
null,
options);
Silly mistake.
EDIT: I also removed the frame, as it was unnecessary for a primarily GUI-less application.
Related
I have a class with only static methods and one of them opens a JOptionPane error message dialogue using a JFrame object as component.
This is the class + method:
public class miscMethods
{
static JFrame errorWindow = null;
public static void ErrorPopup(String message)
{
errorWindow = new JFrame();
errorWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
errorWindow.setAlwaysOnTop(true);
JOptionPane.showMessageDialog(errorWindow, message, "Error", JOptionPane.ERROR_MESSAGE);
errorWindow = null;
}
}
The ErrorPopup method is used inside a JavaFX controller and other places, called like this:
import static code.miscMethods.ErrorPopup;
...
ErrorPopup("This is the error message");
Problem is that the application's process won't close when I close the the program from the window's ✕ after the popup appears, because the JFrame was created and shown.
I know the JFrame is the culprit, so I added the errorWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
but it doesn't seem to do anything, since the program isn't closing.
In this question: JFrame and why stay running
The accepted answer talks about non-daemon threads, but the only thread I open is a daemon one, so unless JavaFX open one then it can't be that I believe.
So, why does the process keep running and how can I solve it?
I'm still new to Java so if I made a mistake and/or my code shows bad practices please do point them out!
Edit: I'm using a JFrame because I need the setAlwaysOnTop, since using
JOptionPane.showMessageDialog(null, message, "Error", JOptionPane.ERROR_MESSAGE); opens it not on top of the JavaFX window. If there's a better way let me know.
This:
errorWindow = null;
does nothing of use since the object is still displayed. You want this instead:
errorWindow.dispose();
Actually, even better, simply get rid of errorWindow altogether and pass null as the first parameter to the JOptionPane.
I want to dispose a frame in its constructor when the condition is true.
this.dispose is not disposing frame. I want that, when my constructor is called, if condition i.e (configurationBean.getCode().equals(macPass)) is true then a new frame have to be called and this frame must have to be closed. Else this frame have to be created.
public ConfigurationFrame() {
String pcMac = getPcMacAddress();
String macPass = getPassword(pcMac);
ConfigurationDao configurationDao = new ConfigurationDaoImpl();
ConfigurationBean configurationBean = configurationDao.checkCode(macPass);
if(configurationBean == null)
initComponents();
else if(configurationBean.getCode().equals(macPass))
{
new MainLoginFrame().setVisible(true);
this.dispose();
super.setVisible(false);
}
}
}
Note that your question is a classic "XY Problem" type question where you ask "how do I do X", when the best solution is "Don't do X but instead do Y". In other words you definitely do not want to dispose of a top-level window object such as a JFrame in its constructor as you're trying to do.
I think that what you want to do (a guess) is to
Test the configuration of things
If OK, display the main GUI
If not OK, then display a window that allows the user to re-set the configuration
Key point: then re-test if the configuration is OK,
And if so, then display main GUI
Repeat as necessary.
If so, then I would use a while loop to show the set configuration window and exit the loop if the configuration is OK, but also allow the user to exit the loop if they simply want to quit or can't set the configuration OK. Something like this:
// configurationGood: true if config is good
// justQuit: true if the user has had enough and wants to quit
while (!configurationGood && !justQuit) {
// create configuration dialog here
// calling constructors, and all
// use a **modal** dialog here
// change configurationGood and/or justQuit values in here
}
if (!justQuit) {
// create and display main application here
}
Note that
this code is not called within any GUI window constructor, but rather prior to displaying the GUI
The re-set configuration window shouldn't be a JFrame but rather a modal JDialog
This way the program code flow halts while the dialog is displayed and only resumes after the dialog has been dealt with.
This allows the code within the while loop to query the dialog the state of its fields and use this to re-test that the configuration is OK
I am currently attempting to add functionality to a program such that if a user closes a child window, it will also close the parent window that created it. I boot the starting program, select an option in the menu that will create the parent window, which then creates the child window. The program already has a endProcess function that prints something to the parent window so I figured it would be a good place to accomplish this task. Here is that function:
private synchronized void endProcess(Exec.FinishedEvent e) {
exec.removeFinishedListener(this);
exec = null;
String str;
if (e.getExitValue() != 0) {
JOptionPane.showMessageDialog(this, exec, "Exec '"+e.getExec()+"' failed: return value: "+e.getExitValue(), JOptionPane.ERROR_MESSAGE);
str = "Process FAILED [exit="+e.getExitValue()+"]: '"+e.getExec()+"'\n";
} else
str = "Process Done [exit="+e.getExitValue()+"]: '"+e.getExec()+"'\n";
statusLabel.setText(str);
outputTextArea.append("*****" + str);
//this.dispose();
//this.dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
The bottom two commented out lines are what I have tried to add. (Two different ideas) Both of these work properly in that when I close the child window, the parent window also closes. However, it also freezes the original program window and will not respond to anything. I believe I am somehow calling some sort of kill function to the original program window as well? Thank you and let me know if I need to provide anything else!
To clarify...
Original Program = Window that first opens when booting the program
Parent Window = Command I run in the original program to produce the child window (I wish this one to close and NOT the Original Program when closing the child)
Child Window = The Window created from the Parent Window that I wish to also close the Parent Window upon the Child Window's closing.
I'm working on a Java7 Swing "wizard" type of project that needs to validate a web address before continuing on to the next step of the wizard. The validation requires accessing a URL over the internet to verify that expected resources are available. In some cases, this can take a few seconds which can be long enough to confuse a user.
As a quick solution to this, I would like to disable the "next" button and change the display text while the validation is running so the user knows that the wizard is working and not hung up on anything. The problem is that when I add the code to modify the JButton, none of the changes happen until after the validation has completed. This is the case even if I change the button and call revalidate() before I execute the validation methods.
Here is an excerpt of what I've tried:
// create next button
next = new JButton("Next", new ImageIcon(getClass().getResource("/navigate_right.png")));
next.setActionCommand("MYACTION");
next.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
System.out.println("Is this the event dispatch thread? "
+ javax.swing.SwingUtilities.isEventDispatchThread());
System.out.println("Changing button");
next.setEnabled(false);
next.setText("Testing Connection");
next.getRootPane().revalidate();
System.out.println("Validating Service");
boolean isValidLocation = ServiceValidator.serviceExists(locationField.getText());
// ...etc...
When I run this code, the lines "Changing button" and "Validating Service" both get printed before the actual button changes in the display. How can I get the JButton to change before System.out.println("Validating Service"); is printed?
The problem is that when I add the code to modify the JButton, none of the changes happen until after the validation has completed.
Your code is executing on the EDT, so you long running code prevents the GUI from repainting itself until the task is finished executing. You need to use a separate Thread for the long running task, maybe a SwingWorker. Read the section from the Swing tutorial on Concurrency for more information.
I have problem currently for my swing reminder application, which able to minimize to tray on close. My problem here is, I need JOptionPane dialog to pop up on time according to what I set, but problem here is, when I minimize it, the dialog will pop up, but not in the top of windows when other application like explorer, firefox is running, anyone know how to pop up the dialog box on top of windows no matter what application is running?
Create an empty respectively dummy JFrame, set it always on top and use it as the component for the JOptionPane instead of null. So the JOptionPane remains always on top over all other windows of an application. You can also determine where the JOptionPane appears on screen with the location of the dummy JFrame.
JFrame frmOpt; //dummy JFrame
private void question() {
if (frmOpt == null) {
frmOpt = new JFrame();
}
frmOpt.setVisible(true);
frmOpt.setLocation(100, 100);
frmOpt.setAlwaysOnTop(true);
String[] options = {"delete", "hide", "break"};
int response = JOptionPane.showOptionDialog(frmOpt, msg, title, JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, "delete");
if (response == JOptionPane.YES_OPTION) {
removeRow();
}
frmOpt.dispose();
}
Old post, but I was struggling with this.
My problem was more with Javafx allowing the JOptionPane to go behind the current Java window.
Therefore I used the following which does what the original poster asked by putting the JOptionPane in front of all windows; even JAVAFX.
Firstly the old JOptionPane:
JOptionPane.showMessageDialog(null, "Here I am");
Now an JOptionPane that stays in front:
final JDialog dialog = new JDialog();
dialog.setAlwaysOnTop(true);
JOptionPane.showMessageDialog(dialog, "Here I am");
And for fun here is everything in one long line:
JOptionPane.showMessageDialog(
((Supplier<JDialog>) () -> {final JDialog dialog = new JDialog(); dialog.setAlwaysOnTop(true); return dialog;}).get()
, "Here I am");
You can make a static method some where that will return the JDialog for you and then just call it in the JOptionPane to clean up your code a bit.
Are you using one of the canned JOptionPanes? (Like JOptionPane.showCOnfirmDialog(...))
You may want to look at extending JDialog and making your own dialog panel, and then calling myDialog.setAlwaysOnTop(true);
Windows is blocking this operation since XP.
The scenario before was like:
Your a tiping in some text in an editor and not recognize that another dialog is coming to front when you are tipping the text. The coming dialog gets the focus and you are tiping in the new dialog. Maybe you click enter after you are ready and do this in the wrong dialog, which is asking whether you realy want to delet your hard disk ;)
The come to front call in java is only working for java windows.
The possibibilty to notify the user of a new window is to implement a Frame, which will highlighted/flashing in the windows task bar.
Correction the post above..
I have resolve my problem as below:
this.setVisible(true); // show main frame
MyDialog dialog = New MyDialog(this, true); // show my custom dialog
dialog.setVisible(true);
this.setVisible(false);
it works fine for me :)
You might think about using a JFrame instead. It may give you a little more flexibility.
If you are using a JFrame and you want it to popup on top of the other windows use:
myFrame.setVisible(true);
myFrame.setState(Frame.NORMAL);
The setState will show the window to the user if it was in minimized state previously.