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