2014-04-02 15 views
14

Attualmente sto valutando se sia possibile convertire la mia attuale applicazione Swing in JavaFX 8 utilizzando SwingNode e quindi modificare lentamente tutto in componenti JavaFX. Mi sono imbattuto in due problemi, che possono essere bug persistenti in JavaFX 8, ma non posso esserne sicuro.Compatibilità swing JavaFX 8

  1. Dopo l'aggiunta di contenuti al SwingNode menu JavaFX non è dipinta correttamente (la maggior parte del tempo), con conseguente una barra nera
  2. Fare JScrollBars non opachi non sembra funzionare

    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

Edit: ho modificato m y esempio per usare EDT per creare i componenti Swing. Questo non ha cambiato nulla. O sto facendo qualcosa di sbagliato?

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

Ho chiesto informazioni su questa domanda nel report bug JavaFX RT-36285 e ho sentito: "... controlla il thread nel codice. L'esempio che fornisci su StackOverflow chiama le API Swing sul thread utente JavaFX. Sia Swing che FX Le API Swing devono essere invocate solo su EDT e FX API - sul thread utente JavaFX in modo corrispondente, correggere prima il threading e vedere come cambia le cose, quindi creare nuovi bug se i problemi persistono ". –

+0

Non si imposta 'JScrollBar's su non opaco ma l'intero' JScrollPane'. Tuttavia, entrambi non funzioneranno. Non è abbastanza chiaro quale comportamento ti aspetti da un 'JScrollPane' con' JScrollBar' non-opaco, ma è molto probabile che non funzioni in questo modo (* in linea di principio *). – Holger

+0

Quando paragono il tuo codice con [Tutorial da Oracle] (http://docs.oracle.com/javase/8/javafx/interoperability-tutorial/embed-swing.htm), sembra che tu debba la chiamata 'swingNode.setContent (...)' in 'SwingUtilities.invokeLater (...)' invece della creazione del contenuto Swing stesso. In combinazione con la proprietà di sistema a thread singolo di @Dashy, dovresti averlo dato il meglio. Ma attualmente il tuo codice mi sembra sbagliato. – dzim

risposta

1

deve essere stato un bug in JavaFX, questo esempio, sta lavorando bene ora.

4

Provare a inserire il codice di aggiornamento in questo quando si effettua una chiamata di aggiornamento. Questo codice mi ha aiutato prima su altri progetti.

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

Source

+1

Poiché questo è Java8, è possibile utilizzare 'Platform.runLater (() -> ...)'. – ggovan

+0

hai salvato la mia giornata –

1

È possibile utilizzare -Djavafx.embed.singleThread=true, in modo da non dover rendere l'evento di dispacciamento per conto proprio.

JavaFx APIDesign

+0

hmm ... per quanto ne so, il blog è disponibile solo per MacOS? – kleopatra

+0

Funziona perfettamente su Windows, testato nel mio progetto attuale. – Dashy

+0

grazie per informazioni :-) – kleopatra

Problemi correlati