14

I'm trying to set the icon image for a Jar file:

setIconImage(new ImageIcon(getClass().getResource("logo.png")).getImage());

When running in Mac OS X 10.7.4 I get the following error:

Jun 28 15:21:40 (my dhcp) java[73383] <Error>: CGContextGetCTM: invalid context 0x0
Jun 28 15:21:40 (my dhcp) java[73383] <Error>: CGContextSetBaseCTM: invalid context 0x0
Jun 28 15:21:40 (my dhcp) java[73383] <Error>: CGContextGetCTM: invalid context 0x0
Jun 28 15:21:40 (my dhcp) java[73383] <Error>: CGContextSetBaseCTM: invalid context 0x0
Jun 28 15:21:40 (my dhcp) java[73383] <Error>: CGContextGetCTM: invalid context 0x0
Jun 28 15:21:40 (my dhcp) java[73383] <Error>: CGContextSetBaseCTM: invalid context 0x0
xav
  • 5,452
  • 7
  • 48
  • 57
rhombidodecahedron
  • 7,693
  • 11
  • 58
  • 91

6 Answers6

30

setIconImage does not set the jar icon. It will set the icon for what the minimized window for that JFrame will look like. The jar icon (which controls the finder icon and the dock application icon) cannot be set in the jar file itself. You just get the default icon provided by the OS. You will need to wrap it using something like JarBundler for OS X or Launch4J for Windows.

You can set the application dock icon while your application is running, see com.apple.eawt.Application.setDockIconImage. It isn't perfect though, because when you double-click on your jar, it starts up in the dock using the generic java icon and only switches to your custom icon after a bounce or two when the java code starts running. Also, I don't think it would set the dock icon for an jar which isn't running (not that you can drag a jar file into the dock anyway - doesn't seem to work for me).

Here's some code that demonstrates the different images you can set:

import com.apple.eawt.Application;
import javax.swing.*;

class SetIcon extends JFrame {

    SetIcon() {
        setIconImage(new ImageIcon("doc.png").getImage());
        Application.getApplication().setDockIconImage(
            new ImageIcon("app.png").getImage());
    }

    public static void main(String args[]) {
        SetIcon s = new SetIcon();
        s.setVisible(true);
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Keith Randall
  • 22,985
  • 2
  • 35
  • 54
  • Thanks, where can I download the Application class? – rhombidodecahedron Jul 01 '12 at 18:42
  • It comes installed on every Mac. – Keith Randall Jul 01 '12 at 19:25
  • 3
    +1 for `com.apple.eawt.Application`, which I'd previously overlooked. – trashgod Jul 01 '12 at 19:29
  • 3
    Thanks! This solved my problem. P.S. I needed to do: Application.getApplication().setDockIconImage(new ImageIcon(getClass().getResource("/logo.png")).getImage()); – rhombidodecahedron Jul 02 '12 at 15:29
  • FWIW, you might need to be able to build your JAR on a non-mac. I got the interfaces for Apple's Java extensions here: http://developer.apple.com/library/mac/#/legacy/mac/library/samplecode/AppleJavaExtensions/Introduction/Intro.html at some point in the past. Note that the site says that documentation is out-of-date and I was unable to find a `.jar` to download. Good thing I have it in svn! – Christopher Schultz Feb 13 '13 at 22:10
  • 3
    com.apple.eawt.Application.setDockIconImage is now a dead link.. any ideas on where to look for this in 2015? – Mshnik Nov 06 '15 at 18:42
  • 1
    To elaborate here, it appears that in mac, when you run a java app, there are two "icons" at play, as it were. The java process itself, as a whole, by default gets one icon (the java cpu), and then new windows that you create, each new window has "its own icon" that is apparently not even visible until you minimize that window. So be careful which icon you set, this answer describes how to affect the "main" icon, which is apparently always visible. Weird. – rogerdpack May 02 '16 at 17:45
  • The link for the "com.apple.eawt.Application.setDockIconImage" is gone -> The page you’re looking for can’t be found. – Shai Alon Dec 18 '21 at 13:58
9

Just to add my final solution for adding a MacOSX Dock icon in a pure-java application:

public boolean exists(String className)
{
    try {
        Class.forName( className, false, null );
        return true;
    }
    catch (ClassNotFoundException exception) {
        return false;
    }
}

public void setIcon( BufferedImage icn )
{
    if ( exists( "com.apple.eawt.Application" ) )
    {
        com.apple.eawt.Application.getApplication().setDockIconImage( icn );
    }
}

This silently ensures the class is available and the executes the setDockIconImage() method. Works very well for me and it does not interfere with other platforms.

mvreijn
  • 2,807
  • 28
  • 40
  • @rogerdpack of course that is an option, however this check ensures that `setDockIconImage()` can be safely executed. – mvreijn May 02 '16 at 14:31
6

You can place your .icns file in the application bundle's Contents/Resources directory and reference it in your Info.plist file. For example, a file named ApplicationName.icns would be referenced by a <dict> entry of this form:

<key>CFBundleIconFile</key>
<string>ApplicationName.icns</string>

Some related details are mentioned here.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Is there any way of accomplishing this without bundling it as an .app? We chose to develop this technology on Java so that we could distribute one file to all users regardless of platform. – rhombidodecahedron Jun 29 '12 at 21:58
  • You can distribute a JAR-with-manifest or use [tag:java-web-start], but you'll get a (different) generic icon for each. – trashgod Jun 29 '12 at 23:17
4

java -Xdock:icon=/path/myIcon.png myApp

Alex Teixeira
  • 158
  • 1
  • 5
  • This works fantastically, as long as you're on a Mac (other platforms will bomb out, unfortunately). – tresf Jul 13 '22 at 16:52
1

as i have gone through your error its related to MacOS jdk which has started appearing after upgrade to 10.7.4

go through this if this helps you :

Harmeet Singh
  • 2,555
  • 18
  • 21
1

A Java 9+ solution:

Taskbar.getTaskbar().setIconImage(myImage);

... or for projects that still need to compile against Java 8...

/**
 * Use reflection to attempt to set the taskbar icon using Java 9+
 */
public void setTaskbarIcon(Image image) {
    try {
        Class taskbar = Class.forName("java.awt.Taskbar");
        Method getTaskbar = taskbar.getDeclaredMethod("getTaskbar");
        Object instance = getTaskbar.invoke(taskbar);
        Method setIconImage = instance.getClass().getDeclaredMethod("setIconImage", Image.class);
        setIconImage.invoke(instance, image);
    } catch (Throwable t) {
        t.printStackTrace();
    }
}

This still suffers the limitations explained in other posts (e.g. startup icon is incorrect) as well as the limitation of the icon resolution not using an multidimensional .icns file, but for many cases, this will be better than the generic Java icon. :)

tresf
  • 7,103
  • 6
  • 40
  • 101