Re: basic GUI question
[note to andrew: I think I understand what an SSCCE is, and I've spent
some time reducing its size before posting it]
Ok, here's an SSCCE. Its behavior currently is that, upon "start", a
user dialog is created and displayed. When the dialog is validated,
the result is echoed on the command-line. The command "stop" closes
the dialog. One can do "start", OK and "stop" any number of times
(however it's not robust to several consecutive "start"s).
That's what it should do, and what it does after a while. In fact, the
first time the dialog is demanded, it seems to have a problem running:
it doesn't show, then it freezes, and the only solution to get it
active is to hit enter in the CLI several times. After that subsequent
requests work fine.
Question is: why? How to make it work?
BTW, I'm aware that there will be a number of remarks on the code,
even without the threading issue. No problem... :-)
Oh and thanks to Simon for introducing me to java.util.Scanner. I
didn't know about it, and was still getting input with
new BufferedReader(new InputStreamReader(System.in)).readLine();
It's nicer with Scanner.
(SSCCE indented with only two spaces, otherwise I had trouble limiting
to 80 chars)
============
package jrobinss.cli_dialog;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.Scanner;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class DialogSSCCE {
// CLI stuff
// ---------
/**
* lowercase because they are used as user commands
*/
enum UserCommands {
start,
stop
}
public static void main(String[] args) {
new DialogSSCCE().doOperations();
System.exit(-1);
}
private void doOperations() {
while (true) {
String userStr = getUserInput();
// command "x" is for exit
if ("x".equalsIgnoreCase(userStr)) {
return;
}
doOperation(userStr);
}
}
private String getUserInput() {
System.out.println("Please enter your input... "
+ Arrays.toString(UserCommands.values()));
Scanner scanner = new Scanner(System.in);
return scanner.nextLine();
}
private void doOperation(String str) {
Scanner scanner = new Scanner(str);
if (scanner.hasNext()) {
String word = scanner.next();
if (word != null && ! "".equals(word)) {
try {
UserCommands cmd = UserCommands.valueOf(word);
processCommand(cmd);
} catch (Exception e) {
System.out.println("Sorry, can't understand command " + word
+ ", available commands are: "
+ Arrays.toString(UserCommands.values
()));
}
}
}
}
// now for the GUI part
// --------------------
private JFrame myFrame_ = null;
private JOptionPane myOptionPane_ = null;
private JTextField myTxtField_ = null;
private void buildFrame() {
myFrame_ = new JFrame("my frame");
myTxtField_ = new JTextField(10);
Object[] messageElements = {"Enter something", myTxtField_};
myOptionPane_ = new JOptionPane(messageElements,
JOptionPane.QUESTION_MESSAGE,
JOptionPane.YES_NO_OPTION);
myOptionPane_.addPropertyChangeListener(new MyPptyChangeListener
());
myFrame_.setContentPane(myOptionPane_);
myFrame_.pack();
}
private class MyPptyChangeListener implements PropertyChangeListener
{
public void propertyChange(PropertyChangeEvent evt) {
if (myFrame_ == null) {
return;
}
String prop = evt.getPropertyName();
if (myFrame_ != null
&& myFrame_.isVisible()
&& (evt.getSource() == myOptionPane_)
&& (JOptionPane.VALUE_PROPERTY.equals(prop) ||
JOptionPane.INPUT_VALUE_PROPERTY.equals(prop))) {
Object value = myOptionPane_.getValue();
if (value == JOptionPane.UNINITIALIZED_VALUE) {
return;
}
String result = null;
if (value.equals(JOptionPane.YES_OPTION)) {
result = myTxtField_.getText();
} else {
System.out.println("GUI cancelled, no result");
}
clearAndHide(); // destroys the GUI!
if (result != null) {
System.out.println("got GUI result=" + result);
}
}
}
}
private void clearAndHide() {
if (myFrame_ != null) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
myFrame_.setVisible(false);
myFrame_ = null;
}
});
}
}
private void processCommand(UserCommands cmd) {
if (cmd == UserCommands.start) {
Runnable showDialog = new Runnable() {
public void run() {
buildFrame();
myFrame_.setVisible(true);
}
};
SwingUtilities.invokeLater(showDialog);
} else {
assert(cmd == UserCommands.stop);
clearAndHide();
}
}
}
===========
Thanks for reading. :-)
--
JRobinss