2014-04-02 99 views
14

我目前正在評估是否可以使用SwingNode將當前的Swing應用程序轉換爲JavaFX 8,然後將所有內容逐漸更改爲JavaFX組件。我偶然發現了兩個問題,這可能是JavaFX 8中存在的錯誤,但我無法確定。JavaFX 8 swing兼容性

  1. 添加內容到SwingNode JavaFX的菜單不塗 正確(大部分時間),導致黑條後
  2. 製作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); 
        } 
    } 
    

    Executable jar

編輯: 我編輯米例如使用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); 
    } 
} 
+3

我在JavaFX錯誤報告RT-36285中詢問了這個問題,並且聽到:「...請檢查代碼中的線程,你在stackoverflow上提供的示例在JavaFX用戶線程上調用Swing API。 Swing和FX都只能在EDT和FX API上調用 - 在JavaFX用戶線程中相應地調用Swing API,請先修復線程並查看它是如何改變的,然後在出現任何問題時提交新的錯誤。「 –

+0

您不要將JScrollBar設置爲非透明,而是將整個JScrollPane設置爲。但是,兩者都行不通。您不清楚JScrollPane具有非透明的JScrollBar的行爲,但它很可能不會以這種方式工作(*原則上*)。 – Holger

+0

當我將您的代碼與[Oracle的教程](http://docs.oracle.com/javase/8/javafx/interoperability-tutorial/embed-swing.htm)進行比較時,您似乎需要將'swingNode.setContent(...)'調用到'SwingUtilities.invokeLater(...)'中,而不是創建Swing內容本身。結合@Dashy的單線程系統屬性,你應該已經給它最好的。但目前你的代碼看起來不對我。 – dzim

回答

1

必須已在JavaFX的一個bug,這個非常一例進行工作的罰款。

4

嘗試在更新呼叫中包裝更新代碼。此代碼在其他項目之前幫助過我。

Platform.runLater(new Runnable() { 
      @Override 
      public void run() { 
       // Update the text node with calculated results 
      } 
     }); 

Source

+1

既然這是Java8'Platform.runLater(() - > ...)'可以使用。 – ggovan

+0

你救了我一天 –

1

您可以使用-Djavafx.embed.singleThread=true,所以你不要有使事件分派你自己。

JavaFx APIDesign

+0

嗯......據我瞭解博客,這隻適用於MacOS? – kleopatra

+0

在Windows上完美工作,在當前項目中對其進行測試。 – Dashy

+0

感謝您的信息:-) – kleopatra