File browser

L

Lew

Peter said:
Hmmm. Well, that article seems to say that my code is perfectly fine.
It specifically calls out initialization as something that's okay to do
in the main thread.

Odd. Recently Sun has been saying that they were mistaken, and that indeed
even initialization must happen only on the EDT.

Some Swing component methods are labelled "thread safe" in the API specification;
these can be safely invoked from any thread. All other Swing component methods
must be invoked from the event dispatch thread. Programs that ignore this rule
may function correctly most of the time, but are subject to unpredictable errors
that are difficult to reproduce.

What, even construction and layout?

Yep - check out their own example:
<http://java.sun.com/docs/books/tuto...lDemoProject/src/components/TopLevelDemo.java>

Note that they take great care to "create and set up the window" in a
createAndShowGUI() method that is invoked, via SwingUtilities, explicitly on
the EDT, not from the main() thread. (Check out the very Java-idiomatic and
nifty use of an anonymous-class implementation of Runnable.)
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}

Yes, Virginia, there is an EDT clause even for construction and initialization
of your GUI.
 
D

Daniele Futtorovic

On Tue, 05 Feb 2008 17:05:27 -0800, Daniel Pitts

But my reading of the Java docs I've seen, and the article you've
offered, suggest that in Java, the objects can in fact be created on
a different thread from where their events will actually be
processed, and not only that, that it's a reasonably common
technique. The only rule is that once the object has been shown, it
must only be interacted with on the EDT.

And that's not even a "MUST" rule, but rather a strong recommendation
and its scope solely synchronisation/concurrency issues.

BTW, there is ever only one active event pump at any given time in a
java GUI application, It runs on a dedicated thread, the so-called Event
Dispatch Thread (EDT). The pump is implemented in java.awt.EventQueue.

As for your original issue, the problem would seem to be with Apple's
implementation of the JFileChooserUI in their proprietary Look-And-Feel
(L&F). Maybe you'd be able to fix it by providing your own version of
JFileChooserUI, extending the default one and twiddling here and there
-- though it sounds like much work with no certainty of success. Depends
on how badly you want the Swing file chooser, I suppose.

Lastly, as it hasn't been noted before, mind you can also set your
application's default L&F via command-line parameters. See:
<http://java.sun.com/docs/books/tutorial/uiswing/lookandfeel/plaf.html>

DF.
 
P

Peter Duniho

And that's not even a "MUST" rule, but rather a strong recommendation
and its scope solely synchronisation/concurrency issues.

Well, I guess I'm not clear on the replies here then. Lew says that I
have no choice and must invoke the initialization on the EDT. Your reply
seems to say that as long as I know that I won't run into any
synchronization issues (and given that none of my UI is visible while I'm
doing the initialization, why would I?), that initialization is fine on
the initial thread (and in fact, I infer that if you can ensure
synchronization then interacting with the components is fine any time).
[...]
-- though it sounds like much work with no certainty of success. Depends
on how badly you want the Swing file chooser, I suppose.

Not badly at all. I wish I could use the Swing version for the file
filtering, but it's a minor detail and not at all worth that sort of
effort. It would have been nice if Apple had provided in Swing a
full-featured chooser that either replicates or simply uses the built-in
file chooser, but the AWT version works fine for me. The lack of useful
file filtering isn't a big deal.

Thanks,
Pete
 
P

Peter Duniho

[...]
The best experiment would be to provide an SSCCE. Something that simply
creates a JFileChooser on the EDT after setting the look-and-feel
correctly.

To what end? Is it your concern that because of the way I'm initializing
my GUI, that the JFileChooser that is displayed isn't working correctly?
That the problem with the filename being cleared is due to that?

Or is it your concern that because of the way I'm initializing my GUI,
that the JFileChooser that is displayed uses the wrong look-and-feel
somehow, and should be more like the build-in OS one?

And of course, while I can see perhaps the value in doing the exercise
just to make sure I'm not causing the problems, are you suggesting that
providing the code here would be useful? Are there actually people
reading this thread who are also using Mac OS and who could run such a
code sample to double-check the behavior and/or help solve the problem?

I agree that sample code is often very useful, but I'm not clear on what
benefit it would offer here. Can you elaborate please?

Thanks,
Pete
 
D

Daniel Pitts

Peter said:
And that's not even a "MUST" rule, but rather a strong recommendation
and its scope solely synchronisation/concurrency issues.

Well, I guess I'm not clear on the replies here then. Lew says that I
have no choice and must invoke the initialization on the EDT. Your
reply seems to say that as long as I know that I won't run into any
synchronization issues (and given that none of my UI is visible while
I'm doing the initialization, why would I?), that initialization is fine
on the initial thread (and in fact, I infer that if you can ensure
synchronization then interacting with the components is fine any time).
[...]
-- though it sounds like much work with no certainty of success. Depends
on how badly you want the Swing file chooser, I suppose.

Not badly at all. I wish I could use the Swing version for the file
filtering, but it's a minor detail and not at all worth that sort of
effort. It would have been nice if Apple had provided in Swing a
full-featured chooser that either replicates or simply uses the built-in
file chooser, but the AWT version works fine for me. The lack of useful
file filtering isn't a big deal.

Thanks,
Pete
The rule is that you "MUST" if you want to be able to easily prove the
correctness of your program. If you don't, the program *may* function
as expected, but may have subtle problems that arise in circumstances
that you can't predict (multi-core CPUs for instance, or OS thread
scheduling decisions.
 
P

Peter Duniho

The rule is that you "MUST" if you want to be able to easily prove the
correctness of your program. If you don't, the program *may* function
as expected, but may have subtle problems that arise in circumstances
that you can't predict (multi-core CPUs for instance, or OS thread
scheduling decisions.

Okay, well it's easy enough to change.

That said, I did write a sample program that all it does is initialize the
look-and-feel according to the method you suggested, and then shows the
JFileChooser. All on the EDT thread. The dialog works (and doesn't work)
exactly as it did before.

I can post the code here, though I'm not sure what the point of that would
be. It's reasonably short though, so I'll go ahead and attach it below.

Pete



import java.io.File;
import javax.swing.*;


public class TestFileChooser
{

/**
* @param args
*/
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
init();
}
});
}

private static void init()
{
try
{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception e)
{
throw new RuntimeException(e);
}
JFrame.setDefaultLookAndFeelDecorated(true);
JDialog.setDefaultLookAndFeelDecorated(true);

JFileChooser chooser = new JFileChooser();

chooser.setSelectedFile(new File("Test Filename.txt"));
chooser.showSaveDialog(null);
}
}
 
D

Daniele Futtorovic

Well, I guess I'm not clear on the replies here then. Lew says that
I have no choice and must invoke the initialization on the EDT. Your
reply seems to say that as long as I know that I won't run into any
synchronization issues (and given that none of my UI is visible
while I'm doing the initialization, why would I?), that
initialization is fine on the initial thread

Well, you tried doing the initial GUI setup in the main thread and
showing it there, didn't you? It works. Consequently it's not a MUST
rule as the examples of the Win and Mac API you spoke of.
As a matter of fact, you probably would get an application to run
properly even if you ignored that rule -- provided you didn't went
overboard with threads, mayhap issued a supplementary repaint() or two
here and there and, most importantly, ran on a single core CPU.

BUT...
(and in fact, I infer that if you can ensure synchronization then
interacting with the components is fine any time).

Not quite. You should know how slippery beasts synchronisation issues (I
do not primarily mean dead-locks or race-conditions, but memory
visibility issues) can be. I don't think it is possible to tell with
sufficient certainty that you won't have synchronisation problems in
your GUI -- given its sheer complexity. I'd venture even someone who'd
have written Swing (presuming it had been written by one single person)
wouldn't be able to tell. Also, keep in mind that Swing components are
unsynchronised by design.
So you MIGHT run into problems, or rather: there most probably WILL be
problems, whether you notice them or not -- the more complex your GUI,
the more you use different threads, the more cores: the more likely --
and such problems as would be *very* difficult to track down.

Therefore: strong recommendation.

DF.
 
L

Lew

See upthread - even prior to being shown, Swing methods must be called on the EDT.

Daniele said:
And that's not even a "MUST" rule, but rather a strong recommendation
and its scope solely synchronisation/concurrency issues.

It is a "MUST" rule,
Some Swing component methods are labelled "thread safe" in the API specification;
these can be safely invoked from any thread. All other Swing component methods
be invoked from the event dispatch thread.
/op. cit./
 
D

Daniele Futtorovic

It is a "MUST" rule,
/op. cit./

But not "must" in the sense that it strictly will not work if you don't
(synchronisation issues aside), is it?
I'm familiar with the issues relating to using GUI objects on a
thread other than where they are created, having a fair amount of
experience writing to both the Windows and Mac OS API, both of which
are very strict about making sure you create the object on the same
thread where the message pump for the object will be run (for
example, on Windows you won't even get messages for a given window
instance except on the thread where that window was created, so you
must always have a message pump on the thread where the object was
created, and the OS will always marshal calls to the window procedure
across to the correct thread).

It's not /that/ kind of a "must". Not as in e.g.: a statement MUST end
with a semi-colon. "Strong recommendation", as I put it, might be too
weak and I agree that for all practical purposes, it's a "must". But not
/sensu strictu/.

DF.
 
L

Lew

Daniele said:
But not "must" in the sense that it strictly will not work if you don't
(synchronisation issues aside), is it?


It's not /that/ kind of a "must". Not as in e.g.: a statement MUST end
with a semi-colon. "Strong recommendation", as I put it, might be too
weak and I agree that for all practical purposes, it's a "must". But not
/sensu strictu/.

I guess it's like the old dentist's riddle: "Which teeth do I have to brush?"
"Just the ones you want to keep."

The tutorial says, "must". I just quoted it. I guess whether you regard that
as "merely" a recommendation depends on whether you want your code to work.

Me, I'm shocked at how hard people resist making programs more maintainable,
and spend many ergs arguing how less safe idioms are actually acceptable. I
guess they never had to maintain software themselves, or they'd come down a
lot more on the side of *good* practices and *safer* programming idioms.

But hey, argue all you want for unsafe, buggy code idioms. Go for it. Just
don't write any software I have to use, please.
 
D

Daniele Futtorovic

I guess it's like the old dentist's riddle: "Which teeth do I have to
brush?" "Just the ones you want to keep."

The tutorial says, "must". I just quoted it. I guess whether you
regard that as "merely" a recommendation depends on whether you want
your code to work.

Me, I'm shocked at how hard people resist making programs more
maintainable, and spend many ergs arguing how less safe idioms are
actually acceptable. I guess they never had to maintain software
themselves, or they'd come down a lot more on the side of *good*
practices and *safer* programming idioms.

But hey, argue all you want for unsafe, buggy code idioms. Go for
it. Just don't write any software I have to use, please.

Hey come on, cut that nonsense and read what I write. I did _not_ argue
for an unsafe, buggy idiom. I did _not_ say that idiom was acceptable. I
offered a reasoning based on what appeared to be the OP's background.
If you think presenting someone who learns a programming language with
brick walls of apodictic statements is superior a pedagogy to helping
them understand *why* they should or shouldn't do something (when the
latter is clearly possible and even more accurate), then go ahead. This
is not the way I do things.

DF.
 
D

Daniele Futtorovic

Hey come on, cut that nonsense and read what I write. I did _not_
argue for an unsafe, buggy idiom. I did _not_ say that idiom was
acceptable. I offered a reasoning based on what appeared to be the
OP's background. If you think presenting someone who learns a
programming language with brick walls of apodictic statements is
superior a pedagogy to helping them understand *why* they should or
shouldn't do something (when the latter is clearly possible and even
more accurate), then go ahead. This is not the way I do things.

Correction: I mistook Peter Duniho for the OP of this thread. By "OP"
above I meant him.
 
L

Lew

On the contrary, I believe that explaining why putting GUI code on the EDT is
the safe alternative is helping them understand why the should or shouldn't do
something.

And if you took my remark personally it's a "shoe-fits" thing.

You did keep arguing a hair-splitting point about "must" when the cited source
said "must", although it was obvious that the imperative in question was for
good code and not a matter of language syntax. Setting up a notion that
putting GUI code on the EDT is somehow not imperative is actually harmful to
those trying to learn good Swing practices. The question of whether the
language allows it is specious and beside the point. Any programming language
powerful enough to be useful is going to allow one to do harmful things to
one's programs. It is still fair to say that one "must" not do that.

/sensu strictu/ and apodictically dixit notwithstanding.
 
P

Peter Duniho

Well, you tried doing the initial GUI setup in the main thread and
showing it there, didn't you? It works. Consequently it's not a MUST
rule as the examples of the Win and Mac API you spoke of.

I believe that is the correct conclusion. However, since the API isn't
doing what I want, it was my interpretation of the other posts that it was
_possible_ that the failure of the API to do what I wanted was due to the
improper initialization.

Changing the initialization didn't change the behavior, so I feel I've
sufficiently ruled out that hypothesis. But at the time I wrote the post
to which you're responding, I hadn't.
As a matter of fact, you probably would get an application to run
properly even if you ignored that rule -- provided you didn't went
overboard with threads, mayhap issued a supplementary repaint() or two
here and there and, most importantly, ran on a single core CPU.

Not on Windows. As I mentioned, messages for a specific window handle are
delivered only to the message pump running in the same thread that created
the window handle. You must have a message pump in the same thread that
created the window handle, no ifs, ands, or buts. And Windows strictly
enforces the rule about calling the window procedure; granted, the code
that implements the procedure could always call it directly, but if you go
through the normal PostMessage/SendMessage API that you're supposed to
use, Windows will always cause the execution of the window procedure
needed for handling those calls to happen on the same thread that created
the window handle.

But I digress...I'm not sure that sort of talk is really appropriate in a
Java newsgroup. :)
BUT...


Not quite. You should know how slippery beasts synchronisation issues (I
do not primarily mean dead-locks or race-conditions, but memory
visibility issues) can be. I don't think it is possible to tell with
sufficient certainty that you won't have synchronisation problems in
your GUI -- given its sheer complexity.

It may be difficult. But note that I wrote "if you can". You are
refuting the statement by trying to assert that you can't. But that's not
a logical contradiction of the if/then I offered.

All that said, if you write code that intentially blocks the EDT, and then
perform some operation elsewhere on another thread, I would expect that to
synchronize a component assuming there are no other threads accessing the
component. I'm not saying it's a pretty way to write code, or even a way
I would ever attempt. But that's a lot different from saying it's simply
not possible or can't work at all.

The question is academic. My intention is always to use the API as it's
intended, and not try to abuse it. Doing otherwise is just asking for
trouble. But I do like to know the specific details, and I am
particularly interested in resolving discrepancies between two sources of
information. The unresolved tension makes it hard for me to think
otherwise...it's just how I am. I need my world to be well-ordered, with
no loose ends. :)

Pete
 
D

Daniele Futtorovic

On the contrary, I believe that explaining why putting GUI code on
the EDT is the safe alternative is helping them understand why the
should or shouldn't do something.

No, not on the contrary, for that is what I've been doing. Unlike you
when you simply state "you must!". Like you when you quoted (upthread):
Programs that ignore this rule may function correctly most of the
time, but are subject to unpredictable errors that are difficult to
reproduce.

And if you took my remark personally it's a "shoe-fits" thing.

Easier said than done.

Oh, and if by any chance I happened to reply to any future post of yours
by saying: "how I despise fatuous incompetence", and you took offense of
the blatant implication, will I be allowed to answer like you just did?

You did keep arguing a hair-splitting point about "must" when the
cited source said "must", although it was obvious that the imperative
in question was for good code and not a matter of language syntax.

"Must" in technical references is not by any standard a verb used in the
meaning of "to achieve good practice". But yes, I agree that I'm
splitting hairs.

Setting up a notion that putting GUI code on the EDT is somehow not
imperative is actually harmful to those trying to learn good Swing
practices. The question of whether the language allows it is
specious and beside the point. Any programming language powerful
enough to be useful is going to allow one to do harmful things to
one's programs. It is still fair to say that one "must" not do that.

"The small inaccuracy for the greater good" ... am I really having this
conversation with lewscannon?

Anyway. I won't go on splitting hairs. I think the matter itself has
become clear enough, if it wasn't already.

DF.
 
P

Peter Duniho

[...]
Me, I'm shocked at how hard people resist making programs more
maintainable, and spend many ergs arguing how less safe idioms are
actually acceptable. I guess they never had to maintain software
themselves, or they'd come down a lot more on the side of *good*
practices and *safer* programming idioms.

You are misinterpeting the situation here.

I am not proposing to write code in violation of recommendations. I am
proposing to know the difference between what is guaranteed not to work,
and what is simply recommended so as to ensure something always works
without additional effort.
But hey, argue all you want for unsafe, buggy code idioms. Go for it.
Just don't write any software I have to use, please.

What's the point in implying that people will actually disobey the
recommendation? Trying to get more information in no way implies that one
is going to go off and write software that doesn't comply with the
tutorial's recommendation. And while I intend to take the tutorial's
recommendation seriously, I'll point out that IMHO a tutorial is a long
way off from an API specification or documentation. I've seen far too
many flawed tutorials and code samples to think that a tutorial is the
last word on how to use an API.

Granted, the Java API is not all that thoroughly documented in many areas,
and the tutorials do serve an important role in filling those gaps. But
it's the API documentation that is the last word (well, at least
next-to-the-last word...I suppose the last word is really had by the
implementation itself :) ).

Pete
 
L

Lew

Peter said:
I am not proposing to write code in violation of recommendations. I am
proposing to know the difference between what is guaranteed not to work,
and what is simply recommended so as to ensure something always works
without additional effort.

There is a third category - what is not guaranteed to work.

Running GUI events off the EDT is a known source of bugs. That's why Sun now
uses the word "must" with putting GUI events on the EDT.

How you interpret that is up to you. But Sun has warned us that running GUI
events *off* the EDT /might/ work. It's not guaranteed not to work. It's not
guaranteed to work. It is guaranteed to cause trouble under certain
circumstances, circumstances that can occur when a program is ported from an
environment where it appeared to work to a different platform. It's a bad
practice - that is certain.

Whether you call it a "recommendation" or an "imperative" is entirely your
choice. But the facts have been laid out, and GIYF for finding more evidence
in that area.

Let's look at a different but related synchronization issue. If two threads
access a common object for both read and write, must you use synchronization
to coordinate the two threads with respect to that object, or is that a
recommendation? After all, on some platforms if you're lucky the program
might seem to work without synchronization.
 
P

Peter Duniho

Running GUI events off the EDT is a known source of bugs. That's why
Sun now uses the word "must" with putting GUI events on the EDT.

You seem to be confusing the general issue of use of components with the
specific scenario I'm talking about: creating the components off the EDT.

I am willing to take as granted that one must always use components after
initialization in the EDT. There are in fact statements to this effect in
the actual Java API documentation, and that's good enough for me.

But as far as initialization goes, there's ample ambiguity here, in the
documentation, in the tutorials, and in sample code I've seen all over the
place. I've been writing Java code for a month, and this is the first
I've seen of any suggestion that _initialization_ is also required to be
done on the EDT. And it's not from lack of exposure to the documentation
or to sample code.
How you interpret that is up to you. But Sun has warned us that running
GUI events *off* the EDT /might/ work.

I'm not talking about "running events".
It's not guaranteed not to work. It's not guaranteed to work. It is
guaranteed to cause trouble under certain circumstances,

Such as? I can reproduce synchronization problems at will in other
contexts, through careful control of the threads involved (i.e. putting in
different synchronization that ensures things happen in the wrong order).
Under what circumstances is it _guaranteed_ that initializing my GUI
components off the EDT will cause trouble? Please provide sufficiently
detailed information such that it would allow me to write sample code to
reproduce the trouble.
circumstances that can occur when a program is ported from an
environment where it appeared to work to a different platform. It's a
bad practice - that is certain.

No doubt. But that's not the question here.
Whether you call it a "recommendation" or an "imperative" is entirely
your choice. But the facts have been laid out, and GIYF for finding
more evidence in that area.

I'm quite familiar with Google. I've been Googling Java issues for a
month now. But Google is not a great resource when one has already
Googled and as a result of failing to find sought-after information has
posted a question to a newsgroup.

If you have a point to make, surely you have some reference that supports
the point. Telling someone to Google for that reference when you already
know what it is is just lame. Asserting a point when you don't actually
have a reference that supports the point is also lame. Making a point and
providing a reference, that's actually quite nice and helpful behavior.
Let's look at a different but related synchronization issue. If two
threads access a common object for both read and write, must you use
synchronization to coordinate the two threads with respect to that
object, or is that a recommendation?

You must use synchronization. So?
After all, on some platforms if you're lucky the program might seem to
work without synchronization.

I can easily write code that will consistently produce wrong results with
incorrect synchronization. It's true that one can get lucky and have it
work without. But it's also true that it's relatively simple to force a
problem in order to demonstrate the risk of failing to synchronize.

So, how can I force a problem to demonstrate that my GUI initialization
must occur on the EDT? How can I write a program that initializes the GUI
off the EDT, and in doing so consistently suffers from whatever problem it
is that you're saying could happen if I do that?

I don't think I can fully understand the recommendation or the assertion
that something might break until I know exactly how it would break and
under what circumstances that might happen.

You might not be able to provide that information, and if so that's fine.
But please don't make it sound like I have no reason to seek or receive
that information.

Thanks,
Pete
 
R

RedGrittyBrick

Peter said:
So I don't actually know how to inspect the
current look-and-feel, nor do I know how to change the dialog to a
different look-and-feel. If it's a simple process, I welcome any
specific advice on how to do that,

Like this:
String laf = UIManager.getSystemLookAndFeelClassName();
UIManager.setLookAndFeel(laf);

Other L&Fs:
UIManager.getCrossPlatformLookAndFeelClassName()
"com.sun.java.swing.plaf.gtk.GTKLookAndFeel"
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel"
"com.sun.java.swing.plaf.motif.MotifLookAndFeel"
etc.

ISTR Sun's JRE on Mac has a Mac specific L&F that isn't available in
Sun's JREs for other platforms (for copyright reasons I believe).
 
R

RedGrittyBrick

Peter said:
I don't think I can fully understand the recommendation or the assertion
that something might break until I know exactly how it would break and
under what circumstances that might happen.

This looks promising:
http://www.javaworld.com/javaworld/jw-08-2007/jw-08-swingthreading.html

Personally I just accept vague assertions that it's best to do GUI
initialisation on the EDT. This frees me up to do stuff I find more
interesting.
 

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,776
Messages
2,569,602
Members
45,182
Latest member
BettinaPol

Latest Threads

Top