我目前正在評估是否可以使用SwingNode將當前的Swing應用程序轉換爲JavaFX 8,然後將所有內容逐漸更改爲JavaFX組件。我偶然發現了兩個問題,這可能是JavaFX 8中存在的錯誤,但我無法確定。JavaFX 8 swing兼容性
- 添加內容到SwingNode JavaFX的菜單不塗 正確(大部分時間),導致黑條後
製作JScrollBars非不透明似乎並沒有工作
import java.awt.Color; import java.awt.GridLayout; 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.layout.StackPane; import javafx.scene.layout.VBox; import javafx.stage.Stage; import javax.swing.JPanel; import javax.swing.JScrollPane; public class Test extends Application { @Override public void start(Stage stage) throws Exception { stage.setMaximized(true); VBox vbox = new VBox(); MenuBar menuBar = new MenuBar(); menuBar.getMenus().add(new Menu("bla")); vbox.getChildren().add(menuBar); StackPane mainPane = new StackPane(); mainPane.setPrefSize(9999, 9999); //Better way to ensure all space used? vbox.getChildren().add(mainPane); vbox.setVisible(true); Scene scene = new Scene(vbox, 9999, 9999); //Better way to ensure all space used? stage.setScene(scene); SwingNode swingNode = new SwingNode(); mainPane.getChildren().add(swingNode); JPanel jPanel = new JPanel(); swingNode.setContent(jPanel); //Seems to interfere with painting of menu jPanel.setBackground(Color.WHITE); jPanel.setLayout(new GridLayout(2, 1)); jPanel.add(new JPanel()); JPanel nonOpaquePanel = new JPanel(); nonOpaquePanel.setOpaque(false); JScrollPane scrollPane = new JScrollPane(nonOpaquePanel); scrollPane.setOpaque(false); scrollPane.getViewport().setOpaque(false); //Black background -> Bug? jPanel.add(scrollPane); stage.show(); } /** * Main method launching the application. */ public static void main(String[] args) { launch(args); } }
編輯: 我編輯米例如使用EDT創建Swing組件。這並沒有改變任何事情。或者我做錯了什麼?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.embed.swing.SwingNode;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class Test extends Application {
private JPanel jPanel = null;
@Override
public void start(Stage stage) throws Exception {
if (Platform.isFxApplicationThread()) { // all of this happens on the fx application thread
stage.setMaximized(true);
VBox vbox = new VBox();
MenuBar menuBar = new MenuBar();
menuBar.getMenus().add(new Menu("bla"));
vbox.getChildren().add(menuBar);
StackPane mainPane = new StackPane();
mainPane.setPrefSize(9999, 9999); //Better way to ensure all space used?
vbox.getChildren().add(mainPane);
vbox.setVisible(true);
Scene scene = new Scene(vbox, 9999, 9999); //Better way to ensure all space used?
stage.setScene(scene);
SwingNode swingNode = new SwingNode();
mainPane.getChildren().add(swingNode);
SwingUtilities.invokeLater(new Runnable() { //Use EDT to build swing components
@Override
public void run() {
jPanel = new JPanel();
jPanel.setBackground(Color.WHITE);
jPanel.setLayout(new GridLayout(2, 1));
jPanel.add(new JPanel());
JLabel nonOpaquePanel = new JLabel("Bla");
nonOpaquePanel.setPreferredSize(new Dimension(5000, 5000));
nonOpaquePanel.setOpaque(false);
JScrollPane scrollPane = new JScrollPane(nonOpaquePanel);
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false); //Black background -> Bug?
jPanel.add(scrollPane);
}
});
Thread.sleep(1000); //terrible way to wait for the EDT, I know
swingNode.setContent(jPanel); //Seems to interfere with painting of menu
stage.show();
SwingUtilities.invokeLater(new Runnable() { //I am pretty sure this isn't necessary, but whatever
@Override
public void run() {
jPanel.repaint();
}
});
}
}
/**
* Main method launching the application.
*/
public static void main(String[] args) {
launch(args);
}
}
我在JavaFX錯誤報告RT-36285中詢問了這個問題,並且聽到:「...請檢查代碼中的線程,你在stackoverflow上提供的示例在JavaFX用戶線程上調用Swing API。 Swing和FX都只能在EDT和FX API上調用 - 在JavaFX用戶線程中相應地調用Swing API,請先修復線程並查看它是如何改變的,然後在出現任何問題時提交新的錯誤。「 –
您不要將JScrollBar設置爲非透明,而是將整個JScrollPane設置爲。但是,兩者都行不通。您不清楚JScrollPane具有非透明的JScrollBar的行爲,但它很可能不會以這種方式工作(*原則上*)。 – Holger
當我將您的代碼與[Oracle的教程](http://docs.oracle.com/javase/8/javafx/interoperability-tutorial/embed-swing.htm)進行比較時,您似乎需要將'swingNode.setContent(...)'調用到'SwingUtilities.invokeLater(...)'中,而不是創建Swing內容本身。結合@Dashy的單線程系統屬性,你應該已經給它最好的。但目前你的代碼看起來不對我。 – dzim