Linux SwingNode focus work around?

Neil Brown N.C.C.Brown at kent.ac.uk
Thu May 5 14:19:17 UTC 2016


Hi,

I recently found what seems to be a bug involving SwingNode and new 
windows on Linux.  Essentially, when you have a SwingNode in an FX 
window, and show a new pure-Swing window, components in the new window 
will not receive focus even when clicked on, unless you focus away to 
another application and back again.  I've confirmed it on several Ubuntu 
machines, using Oracle JDKs including 8u77, 8u91 and 9-ea+115.  The 
problem is not present on Windows or Mac.

I have filed this as a bug in the Java bug tracker (JI-9036410), but 
this will make a big difference to our plans as it prevents us from 
using SwingNode as part of a plan to slowly transition our application 
across to FX until the bug gets fixed.  So I wondered if anyone here 
might have an idea for a work-around?  No fix too hacky!

I've tried all sorts of requestFocus calls but that doesn't seem to do 
it.  It's not a mouse issue: a mouse listener receives the clicks, but 
focus is not correctly transferred to the new window. Making the new 
window an FX window with SwingNode inside can be used to avoid the 
problem, but that would mean transitioning all our Swing windows to FX 
or FX/SwingNode, which is a lot to do in one step.  So I wondered if 
anyone here had any better ideas, or had encountered the same bug and 
already worked around it.

Thanks,

Neil.

P.S. Code to reproduce -- using either the FX menu or Swing button to 
show the new window has the same issue:
/////////////////////////////////////////

import javax.swing.*;
import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class TestSwingNodeWindow extends Application
{
     @Override
     public void start(Stage primaryStage) throws Exception
     {
         SwingNode swingNode = new SwingNode();
         BorderPane root = new BorderPane(swingNode);
         SwingUtilities.invokeAndWait(() -> {
             JPanel panel = new JPanel();
             JButton button = new JButton("Open window");
             button.addActionListener(e -> {
                 showSwingTextFieldWindow();
                 // This makes it work (but not a realistic solution):
                 //Platform.runLater(() -> root.getChildren().clear());
             });
             panel.add(button);

             swingNode.setContent(panel);
         });
         MenuItem menuItem = new MenuItem("Show window");
         menuItem.setOnAction(e -> 
SwingUtilities.invokeLater(this::showSwingTextFieldWindow));
         root.setTop(new MenuBar(new Menu("Menu", null, menuItem)));
         primaryStage.setScene(new Scene(root, 400, 400));
         primaryStage.show();
     }

     private void showSwingTextFieldWindow()
     {
         JFrame window = new JFrame("The new window");
         window.add(new JTextField("text field"));
         window.pack();
         window.setVisible(true);
     }
}

/////////////////////////////////////////////



More information about the openjfx-dev mailing list