我遇到了JavaFx的SwingNode问题,显示它在Java 1.8.0_102-b14中保存的组件。我不确定这个问题是否是由于我的Java版本老了,当前(如果我的是当前的)Java版本中的错误,或者我正在做错的一些SwingNode进程。我知道在JavaFX and SwingNode - partial black Window之前已经报告了这个问题,所以我真的在寻找关于我的Java版本的反馈。
此代码通常会显示" button1"错误,如黑色或背景颜色,直到鼠标悬停在它上面或点击它。这对我来说不是一个理想的解决方法,因为我的项目在Fx项目中使用更复杂的摆动面板而且纯粹的Fx不幸是不可选择的。
import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javax.swing.JButton;
public class Test extends Application {
@Override
public void start(Stage stage) {
final SwingNode swingNode1 = new SwingNode();
final SwingNode swingNode2 = new SwingNode();
swingNode2.setContent(new JButton("Click me!"+2));
swingNode1.setContent(new JButton("Click me!"+1));
BorderPane pane = new BorderPane();
pane.setLeft(swingNode1);
pane.setRight(swingNode2);
stage.setScene(new Scene(pane, 200, 50));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
在创建此sssce时,我发现在设置右侧SwingNode中的内容之前在左侧SwingNode中设置内容更正了这个简单代码的问题,但不适用于我的大型项目。所以我猜这是一个内存泄漏,但我无法通过我的机器告诉你。
有人可以测试此代码并查看它们是否会得到类似的结果吗?
编辑:感谢您的快速反馈,请不要专注于按钮,因为它们只是展示我问题的工具。奇怪的功能与其他对象的作用方式相同,而不是按钮。
答案 0 :(得分:3)
您必须在AWT事件调度线程上创建和显示Swing组件(请参阅Swing's threading policy)。 Application.start()
方法为invoked on the FX Application Thread。
因此你需要
public class Test extends Application {
@Override
public void start(Stage stage) {
final SwingNode swingNode1 = new SwingNode();
final SwingNode swingNode2 = new SwingNode();
SwingUtilities.invokeLater(() -> {
swingNode2.setContent(new JButton("Click me!"+2));
swingNode1.setContent(new JButton("Click me!"+1));
});
BorderPane pane = new BorderPane();
pane.setLeft(swingNode1);
pane.setRight(swingNode2);
stage.setScene(new Scene(pane, 200, 50));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
答案 1 :(得分:1)
有一个bug report关于这个和类似的问题据说已经解决,但显然它并没有完全修复,因为我仍然在启动时看到黑色方块而不是按钮(1.8。 0_91-B15)。
这种情况正在发生,因为您的Swing组件之前正在创建JavaFX组件。您可以通过在每个组件上调用requestFocus()
来确保它们得到正确呈现来修复此行为:
SwingUtilities.invokeLater(() -> {
swingNode1.setContent(new JButton("Click me!"+1));
swingNode1.requestFocus();
swingNode2.setContent(new JButton("Click me!"+2));
swingNode2.requestFocus();
});
或者使用invokeAndWait()
,以便您的应用程序等待,直到Swing组件的创建完成。
SwingUtilities.invokeAndWait(() -> {
swingNode1.setContent(new JButton("Click me!"+1));
swingNode2.setContent(new JButton("Click me!"+2));
});
另外,正如James_D在answer中提到的那样,不要忘记你已经在EDT上创建了Swing组件。
答案 2 :(得分:1)
在显示舞台之后,我通过延迟方式重新绘制Swing组件来解决此问题:
new Timer().schedule(new TimerTask() {
public void run() {
swingNode1.getContent().repaint();
swingNode2.getContent().repaint();
}
}, 100L);
因此,您的代码将如下所示:
import javafx.application.Application;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javax.swing.JButton;
public class Test extends Application {
@Override
public void start(Stage stage) {
final SwingNode swingNode1 = new SwingNode();
final SwingNode swingNode2 = new SwingNode();
swingNode2.setContent(new JButton("Click me!"+2));
swingNode1.setContent(new JButton("Click me!"+1));
BorderPane pane = new BorderPane();
pane.setLeft(swingNode1);
pane.setRight(swingNode2);
stage.setScene(new Scene(pane, 200, 50));
stage.show();
new Timer().schedule(new TimerTask() {
public void run() {
swingNode1.getContent().repaint();
swingNode2.getContent().repaint();
}
}, 100L);
}
public static void main(String[] args) {
launch(args);
}
}
希望对您有帮助!
答案 3 :(得分:0)
在SwingNode中使用JTextArea时(使用JDK 1.8.0_202),我再次看到了此渲染问题。对我而言,此问题发生在两种情况下:
在每次尝试调整窗口大小时:为了解决这个问题,我添加了一个侦听器,以在窗口的每次调整大小时设置swing节点的内容。
在SplitPane分隔器位置更新上:由于swingNode在SplitPane中,因此我也将侦听器添加到了它。
这两个更新似乎可以解决问题,除非我将分隔线移得太快,黑色背景会再次出现。为了解决这个问题,我将SwingNode上的缓存更改为true,并将cacheHint更改为CacheHint.SPEED
。这消除了所有渲染问题,但是仍然有一个副作用,因为textArea被缓存并显示为位图,因此它在很短的时间内不会响应用户交互。这适用于我的情况,因为我的文本区域不可编辑。
请注意,使用SwingUtilities.invokelater似乎对渲染没有任何影响,因此我将其排除在代码之外。
swingNode.setContent(textArea);
ChangeListener<Number> sizeListener = (o, oldSize, newSize) -> {
swingNode.setContent(textArea);
};
splitPane.getDividers().forEach( divider -> divider.positionProperty().addListener(sizeListener));
primaryStage.heightProperty().addListener(sizeListener);
primaryStage.widthProperty().addListener(sizeListener);
swingNode.setCache(true);
swingNode.setCacheHint(CacheHint.SPEED);
此问题似乎已针对JButton修复。