Giving an application a window icon in a sensible way

T

Twisted

Hrm. How to go about doing this?

I want to give a Java application a window icon in a manner that is
independent of how it is installed, etc.

The trick is obtaining an Image object for myJFrame.setIconImage().
Loading it from a URL means it won't work without a working network
connection, and I need to host the image somewhere. Every copy of the
app running anywhere in the world will, on startup, hit that host with
a request for the file(!). Loading it from a file path requires a
separate installer that sets the image into a specific directory.
Putting it in a JAR file with the app means learning a big new chunk of
API, plus it won't work when running in the development environment
rather than as a standalone executable JAR.

This suggests doing the ListMessageBundle sort of thing, and somehow
packaging it as a class -- an Image subclass, presumably. Is there a
tool for turning a jpeg, gif, or png into Java source code for an Image
subclass that will, when instantiated, behave as the appropriate jpeg?

I don't have the google-fu to find this -- searches for queries like
"image resource class java" didn't do much for me. Damn, we need *real*
natural language search. :p
 
L

Larry Barowski

Twisted said:
Hrm. How to go about doing this?

I want to give a Java application a window icon in a manner that is
independent of how it is installed, etc.

The usual method is to use Class.getResource(), which will work
whether the class and icon are in a jar file or not.
 
M

Mark Rafn

Twisted said:
I want to give a Java application a window icon in a manner that is
independent of how it is installed, etc.
The trick is obtaining an Image object for myJFrame.setIconImage().
Loading it from a URL means it won't work without a working network
connection, and I need to host the image somewhere.

Not at all. A URL doesn't always mean http. It could be a file URL, or a
resource URL inside your jarfile.
Putting it in a JAR file with the app means learning a big new chunk of
API, plus it won't work when running in the development environment
rather than as a standalone executable JAR.

URL imgURL = getClass().getClassLoader().getResource("img/path");

Works if the image is in a jarfile OR a directory on the classpath.
 
T

Twisted

Larry said:
The usual method is to use Class.getResource(), which will work
whether the class and icon are in a jar file or not.

Where does it look, if the class isn't in a jar file? The directory
with the .class file?
 
T

Twisted

Mark said:
Not at all. A URL doesn't always mean http. It could be a file URL, or a
resource URL inside your jarfile.

File URL and jar I was considering separately.
URL imgURL = getClass().getClassLoader().getResource("img/path");

Works if the image is in a jarfile OR a directory on the classpath.

Hrm.

Anyway I found something interesting. My google-fu isn't as weak as I
thought -- I was eventually able to dredge up a way to encode icons
into a class file.

It involved exporting the file from photoshop as an XPM, pasting most
of the result into the declaration of a string array, and feeding it to
a class named XImageSource. Of course, this turned out not to be a
standard library class, and tracking it down posed its own challenge
(during which time Firefox crashed for the second time today -- it hit
a crapplet on a page somewhere and died the number. It actually
tottered along sort-of-working until I quit it, but wouldn't load
anything -- and after being quit I couldn't start a new instance until
I terminated a bunch of firefox-related processes that were idling in
the task manager that didn't have any UI or cpu activity!).

Naturally, the XImageSource class had dependencies to track down as
well.

Naturally, one of those dependencies had a bug -- XpmParser. It had

colors = new int[charsPerPixel*2];

where it appeared to need

colors = new int[(charsPerPixel == 2)?65536:256];

since it actually multiplies one char by 256 and adds a second in the
latter case, and was throwing ArrayOutOfBoundsExceptions like they were
going out of style.

Naturally, the author of those classes included a copyright notice and
will probably sue me for copyright infringement for fixing their bug
without permission, too, now that I've copped to this heinous act in a
public newsgroup posting.

But it actually works, and the source code is completely
self-contained, without requiring any extra files besides the .java
files. Which is what I was hoping to accomplish.

Thanks anyway. :)
 
T

Twisted

Twisted said:
But it actually works, and the source code is completely
self-contained, without requiring any extra files besides the .java
files. Which is what I was hoping to accomplish.

Update: with another hack and more copyright infringement (further
editing the XImageSource code) I now have working transparency as well
-- the first color index set to perfectly white (255, 255, 255) in the
XPM disappears. The thing looks far better in my task list now.
 
M

Mark Rafn

Twisted said:
Anyway I found something interesting. My google-fu isn't as weak as I
thought -- I was eventually able to dredge up a way to encode icons
into a class file.

It doesn't need to be a class file for the classloader to find it as a
resource.
It involved exporting the file from photoshop as an XPM, pasting most
of the result into the declaration of a string array, and feeding it to
a class named XImageSource. ....
Naturally, the XImageSource class had dependencies to track down as
well. ....
But it actually works, and the source code is completely
self-contained, without requiring any extra files besides the .java
files. Which is what I was hoping to accomplish.

Wouldn't it be MUCH easier to put gif/jpg/png files directly into the jar,
then let the classloader find them using getResource or getResourceAsStream?
 
P

Patricia Shanahan

Twisted said:
Update: with another hack and more copyright infringement (further
editing the XImageSource code) I now have working transparency as well
-- the first color index set to perfectly white (255, 255, 255) in the
XPM disappears. The thing looks far better in my task list now.

What's the advantage of this approach compared to using getResource?

Patricia
 
T

Twisted

Patricia said:
What's the advantage of this approach compared to using getResource?

It's built right into the frame subclass file it applies to?
It doesn't need to be put in some jar file, then retrieved, then all
kinds of recovery code written to deal with the IOExceptions that can
result if Something Goes Wrong(tm)?
No need to fiddle with classpath?
Everything is self-contained in the source files?
 
T

Twisted

Mark said:
Wouldn't it be MUCH easier to put gif/jpg/png files directly into the jar,
then let the classloader find them using getResource or getResourceAsStream?

First of all, I don't *have* a jar, at least not yet.

Second of all, this is the kind of thing that should really just work
without being able to bomb with IOExceptions and suchlike, in my
opinion. Retrieving even the most basic stuff from a bunch of external
files adds unnecessary points of failure, and gobs of extra recovery
code to check for and cope with anything that goes wrong. This way, it
Just Works(tm). :)
 
A

Andrew Thompson

Twisted said:
It's built right into the frame subclass file it applies to?

Why would it? It's built into the classloader that
many different classes use to get paths to resources.
It doesn't need to be put in some jar file, then retrieved,

Why? Where were you intending to put it.. the cookie jar?
...then all
kinds of recovery code written to deal with the IOExceptions that can
result if Something Goes Wrong(tm)?

Oh, of course, if nothing could conceivably go wrong
with your own home rolled method* - don't bother with
all this getResource crap.

* Such as the image showing 'all white'.
No need to fiddle with classpath?

Nope. You just need to specify it correctly for the application
(once).
Everything is self-contained in the source files?

Now you're ust being silly. Are you intending to put
- properties files
- help text
- localization data
- any of many other resources..
...'stitched in' to the code?

Therein lies the path to madness, but (checks sig.)
'Twisted'.. I see your on your way there, so...

Go for it! ;-)

Andrew T.
 
T

Twisted

Andrew said:
Why would it? It's built into the classloader that
many different classes use to get paths to resources.

Eh -- getResource is, but the resource itself isn't.
Oh, of course, if nothing could conceivably go wrong
with your own home rolled method* - don't bother with
all this getResource crap.

* Such as the image showing 'all white'.

It works fine, and doesn't do any I/O to get it. The only way for
something to go wrong would be if classloading went wrong at a
fundamental level, rather than some image on disk somewhere not being
found. If classloading goes that wrong, the image not being loaded is
the least of my problems.
Now you're ust being silly. Are you intending to put
- properties files
- help text
- localization data
- any of many other resources..
..'stitched in' to the code?

If it gets complex enough to involve such, then there will be separate
files for some of those, and I'll have to worry about how to get a user
directory in a system-independent way to put the properties files in,
and how to get the app's directory to look for help and non-English
localizations in.
 
A

Andrew Thompson

Twisted said:
If it gets complex enough to involve such, then there will be separate
files for some of those, and I'll have to worry about how to get a user
directory

Try
System.getProperty("user.home");

(then make a subdirectory based on you main's
package name, to contain the resources - so
they don't get wiped by other applications)
...in a system-independent way to put the properties files in,
and how to get the app's directory to look for help and non-English
localizations in.

JWS can handle localisation for you (in the sense
of delivering the correct files for each locale),
finding and using those localised resources would
then most naturally be done using getResource().

Java access to (internal - program specific) files is
heavily based around getResource(), I suspect things
will go a lot quicker for you once you have it working
for you.

Note: I never found a way to use getResource() for
both jar'd and 'loose' resources, but with ant build files
(or anything else with even half Ant's abilities) it
is trivial to stamp out a jar(s) of the current project,
and launch it(/them).

Andrew T.
 
T

Twisted

Andrew said:
Note: I never found a way to use getResource() for
both jar'd and 'loose' resources, but with ant build files
(or anything else with even half Ant's abilities) it
is trivial to stamp out a jar(s) of the current project,
and launch it(/them).

Of course, for that I'd need Ant, and to know how to use it...
 
C

Chris Smith

Twisted said:
If it gets complex enough to involve such, then there will be separate
files for some of those, and I'll have to worry about how to get a user
directory in a system-independent way to put the properties files in,
and how to get the app's directory to look for help and non-English
localizations in.

Actually, getResource is exactly the solution to everything you are
mentioning. Nothing is stored in some directory on some disk somewhere.
Everything is stored in the same JAR file with all of your code; one
file that you can distribute around that contains the whole application.
All this, and you don't have to do kludgy things like build images into
the source code of your classes.

(By the way, if exceptions should never happen, as is the case when
using getResource on a resource that's packaged in a JAR file with your
application, then it's pretty trivial to add

try
{
...
}
catch (SomeException e)
{
throw new RuntimeException(e);
}

No information is lost, and you don't have to write any complex error
reporting code or anything like that. Just be careful that you don't
catch some exceptions indicating real plausible problems like this.)
 
J

Joe Attardi

Of course, for that I'd need Ant, and to know how to use it...

Learning how to use Ant is a bad thing why? It's a very valuable and
widely used development tool in the Java world.
 
D

Daniel Pitts

Twisted said:
First of all, I don't *have* a jar, at least not yet.

Second of all, this is the kind of thing that should really just work
without being able to bomb with IOExceptions and suchlike, in my
opinion. Retrieving even the most basic stuff from a bunch of external
files adds unnecessary points of failure, and gobs of extra recovery
code to check for and cope with anything that goes wrong. This way, it
Just Works(tm). :)

"It Just Works(TM)" is considered a very bad approach to software
design. Doing things that "Just Work" versus doing things that "Work
Right", tends to save a minute now and cost a week later. What happens
when you have three icons? 10? What happens when you rebrand those 10
icons? Having them as actual image files rather than converting them.
Ouch.

BTW, if you REALLY wanted to go that route, you could do a byte dump of
the original (png/jpeg/gif) image, and use imageio and a
ByteArrayInputStream (there is such a thing, right?). Releasing you
from using the apperantly buggy XImageWhatchamawhosit. Although, I
wouldn't recommend either approach.
 
T

Twisted

I find the phenomenon of topic drift curious. There seems to be a
recurrent pattern in this group in which a person creates an initial
topic of some Java related sort or another and the topic quickly drifts
to criticism and "bashing" of the person that started the thread.

This does nothing to encourage people to seek information here.

Perhaps some people need to leave their egos at home when they visit?

Re: the most recent round of (universally hostile-toned) replies, I'd
already mentioned that bundling stuff in a jar is not a complication I
wish to handle just yet. Particularly as it means the app has to look
for resources in two places: in a jar with the app (where they'd be
when the app's been packaged and installed somewhere) and in my
computer's specific directory structure somewhere (where they'd be
during development). Someone mentioned putting them along the class
path and their being found automatically if they're there or in a jar
with the app; but then I need to set my class path on my development
machine to include the source directory for every project that has
resources, don't I? Ouch. Or I can track down, download, study, and use
a new build tool (when Eclipse has been serving me well so far)...it
sounds to me like if I'd gone that route I'd still be fiddling with
something merely preliminary to getting the icon to work *now*, around
48 hours later. When there's a lot more resources, and
optional/switchable ones like internationalization resources, then that
looks like a wise investment of time; when there's only the one little
32x32 gif, it seems more like a *waste* of time.
 
T

Thomas Kellerer

Twisted wrote on 21.11.2006 00:06:
Re: the most recent round of (universally hostile-toned) replies, I'd
already mentioned that bundling stuff in a jar is not a complication I
wish to handle just yet. Particularly as it means the app has to look
for resources in two places: in a jar with the app (where they'd be
when the app's been packaged and installed somewhere) and in my
computer's specific directory structure somewhere (where they'd be
during development). Someone mentioned putting them along the class
path and their being found automatically if they're there or in a jar
with the app; but then I need to set my class path on my development
machine to include the source directory for every project that has
resources, don't I?

Hmm. Netbeans does that automatically for me. I have all my resource in my Java
source directory (gif, properties, xml and txt files). When I build my project,
NetBeans compiles my Java classes (of course) and then copies all non-Java files
to the classpath (according to their location in the Source path).

I use getClassLoader().getResourceAsStream() in several places and this approach
has never given me any headaches. It works fine from within NetBeans and as well
when I distribute my (Swing) application as a jar file.

Maybe you can convince Eclipse to copy the non-Java files as well?

My 0.02€

Thomas
 
I

Ian Wilson

Twisted said:
I find the phenomenon of topic drift curious. There seems to be a
recurrent pattern in this group in which a person creates an initial
topic of some Java related sort or another and the topic quickly drifts
to criticism and "bashing" of the person that started the thread.

I suspect it is proportional to the amount of good advice previously
ignored.
Perhaps some people need to leave their egos at home when they visit?

True, have you considered whether your own ego might be getting in the
way of your accepting good advice?
Re: the most recent round of (universally hostile-toned) replies, I'd
already mentioned that bundling stuff in a jar is not a complication I
wish to handle just yet.

You must be aware that Eclipse has a wizard for creating Jars. I find it
a lot less complex than your method of encoding image data within
class files seems.
Particularly as it means the app has to look
for resources in two places: in a jar with the app (where they'd be
when the app's been packaged and installed somewhere) and in my
computer's specific directory structure somewhere (where they'd be
during development). Someone mentioned putting them along the class
path and their being found automatically if they're there or in a jar
with the app; but then I need to set my class path on my development
machine to include the source directory for every project that has
resources, don't I? Ouch. Or I can track down, download, study, and use
a new build tool (when Eclipse has been serving me well so far)...it
sounds to me like if I'd gone that route I'd still be fiddling with
something merely preliminary to getting the icon to work *now*, around
48 hours later. When there's a lot more resources, and
optional/switchable ones like internationalization resources, then that
looks like a wise investment of time; when there's only the one little
32x32 gif, it seems more like a *waste* of time.

I use Eclipse, I have an image for my app in a subdirectory of my
project. I have this code (and this code only) to load the image:

setIconImage(new ImageIcon(MainForm.class
.getResource("/resources/logo32.png")).getImage());

When I run the app from Eclipse it finds the image from the subdirectory
in the filesystem.

After getting Eclipse to make a jar that includes the image, running the
jar causes the image to be loaded from the jar instead. No change to the
above code.

I just don't see the problem you seem to be struggling against. I didn't
need to do anything with my classpath or change my build tool (I use
plain old Eclipse without Ant etc)

Maybe I'm missing something, but it looks like you've spent more time
thinking up arguments why you shouldn't try the suggestions offered than
you would have spent simply trying them.
 

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

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top