48

We have a Java application that used Swing, but we are migrating it to JavaFX. Therefore, we wrap the old Swing code into SwingNodes and replace them step-by-step.

Before migrating, the Swing application used com.sun.java.swing.plaf.gtk.GTKLookAndFeel as look-and-feel (default on Ubuntu). We used following code to set it (if available):

for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
  if (info.getClassName().equals("com.sun.java.swing.plaf.gtk.GTKLookAndFeel")) {
    UIManager.setLookAndFeel(info.getClassName());
  }
}

This worked fine. Yet, after switching to JavaFX, the call to UIManager.setLookAndFeel() freezes the application, and nothing happens. The manual setting of the look-and-feel is needed since we want to still style the Swing components that have not been migrated to JavaFX based on the GTKLookAndFeel.

Further info: This only does not work with com.sun.java.swing.plaf.gtk.GTKLookAndFeel, since it works when using javax.swing.plaf.metal.MetalLookAndFeel, javax.swing.plaf.nimbus.NimbusLookAndFeel or com.sun.java.swing.plaf.motif.MotifLookAndFeel.

What can we do to make it work with GTKLookAndFeel to style our Swing components in the SwingNodes?

Maytham Fahmi
  • 31,138
  • 14
  • 118
  • 137
Markus Weninger
  • 11,931
  • 7
  • 64
  • 137
  • 2
    Are you doing it in the correct thread? Swing code needs to be run inside [EventQueue.invokeLater](http://docs.oracle.com/javase/8/docs/api/java/awt/EventQueue.html#invokeLater-java.lang.Runnable-). – VGR May 04 '17 at 15:37
  • @VGR: Didn't do that before, changed it now, but still does not change the behavior. Still freezes the application. – Markus Weninger May 04 '17 at 15:51
  • 2
    Try running it on the command line, and dumping all thread stacks. On Windows, this is done with Ctrl-Break; on other systems, SIGQUIT will do it, accomplished with Ctrl-\ or a separate `kill -3` command. One of the stack traces should indicate where setLookAndFeel is stuck. – VGR May 04 '17 at 16:02
  • 1
    @VGR: The thread that is running the look-and-feel setting seems to be stuck at `com.sun.java.swing.plaf.gtk.GTKEngine.native_get_gtk_setting(Native Method)`... Tested this with a thread dump and the eclipse debugger. – Markus Weninger May 04 '17 at 16:18
  • Can you provide a minimal sample? I'm running this snippet https://pastebin.com/wnLFqD6i on Xfce with the latest GTK and Java 8 u121, it runs fine. Looking at native_get_gtk_setting‌, there's a synchronize block, seems suspicious. By the way, have you tried -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel? – AndreLDM May 08 '17 at 13:16
  • @AndreLDM: Okay, your example also works on my machine. We have a `JTabbedPane` that gets set as a SwingNode's content in our view's controller's `initialize` method, and we are currently investigating if it has something to do with that. It seems that the constructor call of `JTabbedPane` hangs the application. I will try to create a minimal example. – Markus Weninger May 10 '17 at 11:29
  • 1
    You can also provide a thread dump with `jstack -l`, it will show you if there is a deadlock. You guys mentioned that the thread was stuck in `native_get_gtk_setting‌​`, and that this method is synchronized, so maybe another thread is holding the lock. And that might happen because Swing and JavaFX each have their own thread... – Hugues M. May 13 '17 at 13:13
  • Is the installed version of GTK >=2.2? I know this is an old question, just wanted to find out if you found a solution to this issue. – Chetan Jadhav CD Nov 30 '17 at 19:38
  • @ChetanJadhavCD: I have access to the PC again tomorrow, then I can check. I know the OS is a default `Ubuntu 16.04 LTS` install. – Markus Weninger Nov 30 '17 at 20:52
  • @ChetanJadhavCD `dpkg -s libgtk2.0-0|grep '^Version'` returns `Version: 2.24.30-1ubuntu1.16.04.2` and `dpkg -s libgtk-3-0|grep '^Version'` returns `Version: 3.18.9-1ubuntu3.3` – Markus Weninger Dec 01 '17 at 11:11
  • 1
    Sorry @MarkusWeninger that was the only thing I had in mind that I could suggest, I dunno what else to try at this point. – Chetan Jadhav CD Dec 01 '17 at 15:27
  • I came across similar scenario with only the swing components and I think this is a problem with the `GKT` deadlocking. These posts https://bugs.eclipse.org/bugs/show_bug.cgi?id=341538 and https://bugs.eclipse.org/bugs/show_bug.cgi?id=341799 helped me solve the issue by calling `gdk_threads_leave()` before Swing/AWT dispatches the threads. – HariUserX Jan 25 '18 at 09:16
  • @hari Thank you for your help. In the meantime since I asked this question we ported all SwingNodes. If I find the time, I will set up an example application to test it. – Markus Weninger Feb 09 '18 at 08:08
  • 1
    Also: shouldn't there be a `break` statement in your if ? – Guilherme Mussi Jun 01 '18 at 09:20

1 Answers1

1

Gui components need to be updated into gui threads.

Try one of the following:

SwingUtilities.invokeLater(() -> {
//commands
});

javafx.application.Platform.runLater(() -> {
//commands
});
justcode
  • 1,562
  • 3
  • 14
  • 25