basic GUI question

J

jrobinss

markspace said:
Yes. Your property change listener is just bizarre. You need help with
Swing, not multi-threading. Read the docs on JOptionPane, since you're
trying to use one:

In fact my property change listener is copy pasted from a sample found
on the web. The reason why is that to post an SSCCE, or approaching, I
needed something that compiles and runs, and it's been a long time
since last time I've developed GUIs. And it has no bearing on the
issue.

As I said, these comments are welcome, even though they are not linked
to the problem at hand.
<http://java.sun.com/javase/6/docs/api/javax/swing/JOptionPane.html> [...]
JDialog dialog = pane.createDialog(parentComponent, title);

[minor rant]
BTW, I'm always frustrated when reading up on GUI subjects at the
number of times there are code extracts with some kind of magical
"parentComponent" or "frame" or "panel". Here you are, Java GUI
beginner, trying to understand how to create stuff, and you think you
have a code sample that works, you copy paste it, and voilà, here's a
compilation error, parentComponent not known.
Ok, I understand the logic behind it, but it's still frustrating.
 
R

RedGrittyBrick

jrobinss said:
So I guess the question is now, why doesn't it work as well executing
from inside Eclipse? I suppose Eclipse is using the EDT too. So is the
lesson learned, never test graphical programs from Eclipse??

I always test my Swing programs from within Eclipse.

Is there any special way to launch programs that require EDT from
Eclipse?

With the default configuration of Eclipse, Clicking the "Run" button
works for me.


If I had your problem I'd check the "Run", "Run..." Configuration. Then
the Project Build Path. I'd also use the debugger to step through a
Swing "Hello World". If that was taking too long I'd uninstall Eclipse
and reinstall the latest version.
 
L

Lew

That's what I usually do. Neatly separates HMI from code. In this case
its adds more boilerplate than that, because the user command input is
also not recognized, so I would have to compare the user input to
command.toString() for all commands.

I usually include a 'public static E fromString( String lu )' method for an
enum E that looks up and returns the E instance whose 'toString()' value
equals 'lu', or 'null' if none found.

Sometimes I use 'equalsIgnoreCase()' as the comparison for 'fromString()'.
 
S

Simon

BTW, to the best of my knowledge the Thread:stop() method is
deprecated, and should be replaced with interrupt().

Did you test whether that works? The docs say that this only helps if
the thread is blocked by IO of an interruptible channel. If that applies
to System.in, then this works.
I ran your code, and saw only the CLI, no GUI. When I typed something
in, it obviously triggered the EDT, because I ran into an NPE, so I
changed your line
if (dialog.isVisible()) {
dialog.setVisible(false);
}
to
if (dialog != null && dialog.isVisible()) {
(the dialog wasn't yet created)

With this corrected, upon startup I only see the CLI, and when I type
in some input, the program exits. (same as Daniel's code in fact)

Well, admittedly, it is not very nice that each thread assumes that the
other one has already started, but its only a demo. Wait a few seconds
and give the Dialog a chance to pop up.

The dialog is very small and has no button, it gets lost easily. You can
"confirm" only by closing it.

At least for me, it also works outside eclipse.

Let me know if you find the dialog :)

Cheers,
Simon
 
M

markspace

jrobinss said:
to avoid a NPE.

Yes, if you enter "stop" twice in a row, you'll get an NPE. Also, if
you type "start" twice in a row, the previous window will be replaced
with a new one, and you can't close or dispose the old window anymore.

The example was to show starting and stopping a GUI from another thread,
not bomb proof window handling. Depending on your requirements, you
might want to do nothing if a "start" command is issued and a window
already exists. Or you might want to make a new window, and save both
references. Or you might issue an error message. It all depends.


Re your comment from the other post:
>> JDialog dialog = pane.createDialog(parentComponent, title);
>
> [minor rant]
> BTW, I'm always frustrated when reading up on GUI subjects at the
> number of times there are code extracts with some kind of magical
> "parentComponent" or "frame" or "panel". Here you are, Java GUI


If you want to know what createDialog() does, read the docs! You had a
link to the docs right in that post. This is a little bit silly,
really. "parentComponent" is a variable, the fact that it was
undeclared and used in an example should be pretty obvious if you know
any Java syntax.

JComponent parentComponent = null;
panel.createDialog( parentComponent, title );

This really seems like you just don't know Java very well.
Multi-threading can be tricky for anyone, but variables and method calls
should be one of the first things you learn. If you're new, no worries,
we all have to start somewhere, but I think you might benefit from some
actual study of the language itself. Java Passion is Sun's free web
site where you can get free online courses in Java:

http://www.javapassion.com/javaintro/

I went through this course myself. Even though much of it was remedial,
the organization and exercises helped cement my understand of the basic
language, and made it much easier to progress to more advanced Java
topics. Just a thought.


Lastly, I'd be curious to know where you got that code example from.
It's probably doing something different that you thought, but I'd like
to check it out if you don't mind posting a link.
 
J

John B. Matthews

[...]
I thought I'd show you my solution.
[...]

Your excellent example prompted me to update my GUI launcher that uses
exec() to run programs in a separate JVM:

<code>
package gui;

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/** @author John B. Matthews */
public class Launcher extends JPanel implements Runnable {

private final JButton launch = new JButton();
private final JLabel label = new JLabel();
ProcessBuilder pb = new ProcessBuilder(
"java", "-cp", "build/classes", "gui.DialogTest");
private volatile Process proc;

public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
createGUI();
}
});
}

private static void createGUI() {
final JFrame frame = new JFrame();
frame.setLayout(new GridLayout(0, 1));
frame.add(new Launcher());
frame.add(new Launcher());
frame.add(new Launcher());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}

public Launcher() {
this.setPreferredSize(new Dimension(225, 50));
launch.addActionListener(new ActionListener() {
//@Override
public void actionPerformed(ActionEvent e) {
if (proc == null) {
launch.setText("Terminate");
label.setText("Status: run");
new Thread(Launcher.this).start();
} else {
proc.destroy();
reset();
}
}
});
this.add(launch);
this.add(label);
reset();
}

//@Override
public void run() {
try {
proc = pb.start();
int status = proc.waitFor();
} catch (IOException ex) {
ex.printStackTrace();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
reset();
}
});
}

private void reset() {
proc = null;
launch.setText("Launch");
label.setText("Status: idle");
}
}

class DialogTest {

public static void main(String... args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
JOptionPane.showMessageDialog(null, "Running",
"Test", JOptionPane.INFORMATION_MESSAGE);
System.exit(0);
}
});
}
}
</code>
 
D

Daniel Pitts

jrobinss said:
Daniel Pitts wrote:
[solution deleted]

Sorry for being obtuse, but I copy-pasted your code into Eclipse, and
its execution only waits for any input by the user, and then exits.

The EDT seems to never be activated.

This is purely an experimentation result. I suppose for you it
produces an "OK" dialog?
Yes, for me it produces an "Okay" dialog box, and waits for the user to
either type something on the console, or press the Okay box.

This was meant to demonstrate that the EDT is started separately from
the Main thread, and it happens automatically with the first call to
EventQueue.invoke[Later|AndWait]
 
J

jrobinss

RedGrittyBrick answered me:
With the default configuration of Eclipse, Clicking the "Run" button
works for me.

If I had your problem I'd check the "Run", "Run..." Configuration. Then
the Project Build Path. I'd also use the debugger to step through a
Swing "Hello World". If that was taking too long I'd uninstall Eclipse
and reinstall the latest version.

Many thanks for these practical suggestions. I'll jump to it ASAP.
(I'm in the midst of several things at the moment)
 
J

jrobinss

Simon answered me:
Well, admittedly, it is not very nice that each thread assumes that the
other one has already started, but its only a demo. Wait a few seconds
and give the Dialog a chance to pop up.

The dialog is very small and has no button, it gets lost easily. You can
"confirm" only by closing it.

At least for me, it also works outside eclipse.

Let me know if you find the dialog :)

No problem, as I said elsewhere, I saw the dialog, but only when
executing outside Eclipse.
 
J

jrobinss

markspace answered me:
The example was to show starting and stopping a GUI from another thread,
not bomb proof window handling.

I had already written:
(yes, I enter a lot of commands, which leads me to these NPEs, not to
test your solution, but to see what it takes to display a GUI)

We're basically saying the same thing. I simply thought it polite to
mention the minor modification I did to your code, I wasn't
criticizing it for being unfit for production. :)
Re your comment from the other post:

 >>       JDialog dialog = pane.createDialog(parentComponent, title);
 >
 > [minor rant]
 > BTW, I'm always frustrated when reading up on GUI subjects at the
 > number of times there are code extracts with some kind of magical
 > "parentComponent" or "frame" or "panel". Here you are, Java GUI

If you want to know what createDialog() does, read the docs!   You had a
link to the docs right in that post.  This is a little bit silly,
really.  "parentComponent" is a variable, the fact that it was
undeclared and used in an example should be pretty obvious if you know
any Java syntax.

Of course I read the docs. Of course it's a bit silly, it's a rant. Of
course parentComponent is a variable, and declared and initialized
somewhere. Of course I know some Java syntax.

Thanks for the advice you went on to provide about learning, but
although I'm certainly no guru, I think I may be just at the level
above learning about variables and method calls. At least
syntactically.
(for the record, I once met an intern in IT who actually did not know
about variables... hard to believe, I know, but there it was)

What was the point of my rant? Same point as many postings in NGs: on
one hand you're talking to people, but on the other hand you're also
simply creating content (accessible through GG for example), and on
the third hand (!) you're generating traffic on a public billboard. It
may of some comfort to some Java beginner or lurker to know that
they're not alone in wishing for an example that would also include
declaration and initialization of stuff such as parentComponent. It
may also trigger, who knows, interesting discussions, remarks or
whatnot. Or not.

What it doesn't mean is that I, for one, stop short when I read such
extracts and freak out because the variable is missing. :)
Lastly, I'd be curious to know where you got that code example from.
It's probably doing something different that you thought, but I'd like
to check it out if you don't mind posting a link.

Sure
http://java.sun.com/docs/books/tuto...gDemoProject/src/components/CustomDialog.java
 
M

markspace

jrobinss said:
We're basically saying the same thing. I simply thought it polite to
mention the minor modification I did to your code, I wasn't
criticizing it for being unfit for production. :)


No worries. I wasn't offended; I was just agreeing that my code is
unfit for production. Just something I whipped up quickly as an example.

What was the point of my rant? Same point as many postings in NGs: on
one hand you're talking to people, but on the other hand you're also
simply creating content (accessible through GG for example), and on


My answer to your rant was aimed at the same audience. We get a lot of
folks on cljp who are first year students, hobbyists or new to Java
after modest experience with another language.

Most of those have the same problem you did, and in fact the same
problem I did when I first tried to learn Java. Sun's tutorial is lousy
and the API docs are impenetrable.

What worked for me was the link I posted. Even though that course is
remedial (it was for me), the fact that it forces you to sit down and
write code forced me to learn the language and small parts of the API in
an orderly fashion. After that, learning the rest was much easier.
After a few small projects on my own and I could understand the API docs
and follow code examples in the tutorial.

Everyone tries to use the tutorial and dive right in and learn in great
big gulps. That didn't work for me. Carefully chewing my food in
smaller bites was the answer.


That's from this page:

<http://java.sun.com/docs/books/tutorial/uiswing/components/dialog.html>

It's a custom dialog. The prefab dialogs are much easier to use. Even
making dialogs for myself for my own projects, I didn't use anything as
fancy as that custom code. Normally I just made my own panels and
dropped them in a plain JDialog.

One of the advantages of that course I posted earlier is that we used
the simple static methods in JOptionPane a lot to display simple
messages. Once you get used to doing it that way, you look at the big
example of custom code you posted and go "Pfft, why bother?" and just do
it the easy way.
 
J

jrobinss

markspace answered me:
One of the advantages of that course I posted earlier is that we used
the simple static methods in JOptionPane a lot to display simple
messages.  Once you get used to doing it that way, you look at the big
example of custom code you posted and go "Pfft, why bother?" and just do
it the easy way.

I completely agree, I started off with JOptionPane's static utilities.
It's really a great relief from managing dialogs. :)

However, there's no way in my case to use these methods and then hide
or destroy the dialog upon the command "stop". Is there?

I don't have any pointer to any object such as dialog for hiding, and
stopping or interrupting the thread in which I run the static method
doesn't work either.

So that the remaining option is to create my panel, keep a pointer to
it (instance attribute), and hide or destroy it upon "stop".
 
J

jrobinss

I'm answering myself, because it's fairly easy to show/hide while
still using JOptionPane's static methods.

My new code, without any callbacks: (this is not SSCCE, it's just an
extract)
[...]
private void onInput(String input) {
System.out.println("got input=" + input);
}

private Component dialogParent_ = new JFrame();

private Runnable showDialog_ = new Runnable() {
public void run() {
String input = JOptionPane.showInputDialog(dialogParent_,
"Please enter input");
onInput(input);
}
};

private Runnable hideDialog_ = new Runnable() {
public void run() {
dialogParent_.setVisible(false);
}
};

public void processCommand(MyCommand cmd, List<String> args) {
if (cmd == MyCommand.start) {
SwingUtilities.invokeLater(showDialog_);
} else {
SwingUtilities.invokeLater(hideDialog_);
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,775
Messages
2,569,601
Members
45,182
Latest member
alexanderrm

Latest Threads

Top