views:

1911

answers:

4

Hello

First of all, using gnome is not an option (but it is possible to install its libraries).

I need to know what is necessary to display a Java Swing desktop application using the current installed KDE look and feel of KDE. Ideally, the solution should allow me to apply a look and feel that looks like the underlying windowing system (ie: Windows LNF for Windows, GTK LNF for Gnome(GTK), QT LNF for KDE (QT), the default one for other platforms).

Under KDE, you can configure it to use the current KDE theme for GTK applications, too. So, if the solution works with GTK it is fine.

When I run the following piece of code under Gnome (Ubuntu 8.04), the Java application looks beautiful. It integrates very well with the rest of applications:

try {
  // Set System L&F
  UIManager.setLookAndFeel(
  UIManager.getSystemLookAndFeelClassName());
} catch(Exception e) { //Handle it }

However, if I run the same thing under Debian (Lenny) with KDE, the UIManager.getSystemLookAndFeelClassName() call returns the Java default one. If I go ahead and force it to use the GTK LNF, the application doesn't work. Some fields are invisible, others become out of place, everything is unusable:

try {
  //Force the GTK LNF on top of KDE, but **it doesn't work**
  UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
} catch (Exception e) { /*Handle it*/ }

I've also tried to put the following code. It let's the user chose any one of the available LNF and then tries to set it. Metal and Motif work fine. GTK doesn't. The slider is really messed up. The list box looks ugly and disappears, but seems to work. Buttons and menu seem ok. The relevant code is shown here:

(...)
    /** Creates new form SwingFrame */
    public SwingFrame() {

    initComponents();

    //Save all available lafs in a combobox
    cbLafs.removeAllItems();
    UIManager.LookAndFeelInfo[] lafs=UIManager.getInstalledLookAndFeels();

    for (int i=0,t=lafs.length;i<t;i++)
    {
        cbLafs.addItem(lafs[i]);
        System.out.println(lafs[i].getName());
    }

    }

public void changeLookAndFeel(String laf)
{
    //If not specified, get the default one
    if (laf==null) {
    laf=UIManager.getSystemLookAndFeelClassName();
    }

        try {
        // Set System L&F
        UIManager.setLookAndFeel(laf);
    }
    catch (Exception e) {
       // handle exception
        e.printStackTrace();
    }
    SwingUtilities.updateComponentTreeUI(this);

}

   private void cbLafsActionPerformed(java.awt.event.ActionEvent evt) {                                       
        // TODO add your handling code here:
        UIManager.LookAndFeelInfo laf=(UIManager.LookAndFeelInfo)cbLafs.getSelectedItem();
        if (laf==null)
            changeLookAndFeel(null);
        else
            changeLookAndFeel(laf.getClassName());
    }

This same system has all GTK applications working (for example: Firefox) as expected. So:

1) What is missing from the environment to have a Java GTK LNF application working under KDE?

2) What does the JVM checks for to return GTK as the default system theme?

Thanks for you help Luis Fernando

PS->I've tried other solutions,too, such as JGoodies, plain AWT and SWT. However, Swing with GTK LNF would be the best solution to avoid the hassle of SWT native libraries and JGoodies extra jars (also, JGoodies LNF doesn't look as integrated as Swing GTK under Gnome). AWT looks hideous (motif-like) and misses lots of features.

A: 

maybe this works:

try {
// sure look and feel
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
// not-so-sure look and feel
System.setProperty("os.name", "Windows");
System.setProperty("os.version", "5.1");
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} 
catch (Exception ex) {
ex.printStackTrace();
}
FunnyBoy
HiI've tried that first option. Somehow, all widgets get really messed up (wrong sizes, missing items, wrong click positions and some don't even show up)...Outside Java, all GTK applications work well and also use the current KDE Theme. I could get this code to work only on Ubuntu (Gnome).
Luis Soeiro
+1  A: 

Quoting the documentation:

  1. If the system property swing.defaultlaf is non-null, use its value as the default look and feel class name.

  2. If the Properties file swing.properties exists and contains the key swing.defaultlaf, use its value as the default look and feel class name. The location that is checked for swing.properties may vary depending upon the implementation of the Java platform. In Sun's implementation the location is ${java.home}/lib/swing.properties

Refer to the release notes of the implementation being used for further details.

But I'm 99% sure that your problem is this one (quoting the docs again):

Once the look and feel has been changed it is imperative to invoke updateUI on all JComponents. The method SwingUtilities.updateComponentTreeUI(java.awt.Component) makes it easy to apply updateUI to a containment hierarchy. Refer to it for details. The exact behavior of not invoking updateUI after changing the look and feel is unspecified. It is very possible to receive unexpected exceptions, painting problems, or worse.

If you don't want to invoke updateUI on all JComponents, be sure to invoke UIManager.setLookAndFeel before every other swing code.

Davide
Ok. I'm using updateUI on the base frame, hoping that it will update the whole tree. However, the controls are still messed up.
Luis Soeiro
+1  A: 

You can set the look and feel from the command line:

java -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel MyApp

Also, SwingSet2.jnlp provides a sample demo of all the different things that can be changed. The source and other info can be found here: link text

Joshua
Even the SwingSet2 doens't work! The slider and the combo box are broken... But they work under gnome. Is this a bug or something missing (some gtk library)?
Luis Soeiro
I would wager that if the SwingSet2 doesn't work, then it would be a bug or something missing.
Joshua
A: 

The GTK Laf is, IMHO, broken period. It does not honor some random settings. I believe it is not supposed to honor any setBackground(), setForeground(), or setFont() on most components.

If you are using java >1.4.2 I suggest using MetalLookAndFeel [should be UIManager.getCrossPlatformLookAndFeelClassName()]. If you are using >1.6.0_u10 you can try NautilusLookAndFeel. I personally find Metal nicer looking.

KitsuneYMG