2014-02-17 14 views
1

我曾嘗試使用JFXPanel作爲包裝爲Scene一個Swing應用程序中使用JavaFX,但我面臨由以下困難:所有具有的彈出窗口無法正確控制長列表滾動的能力 - 例如組合框。JavaFX的有彈出窗口的問題,例如組合框,通過在Swing

我的示例代碼:

import javafx.application.Platform; 
import javafx.embed.swing.JFXPanel; 
import javafx.scene.Scene; 
import javafx.scene.control.ComboBox; 
import javafx.scene.layout.HBox; 
import javax.swing.*; 
import java.awt.*; 

public class SwingDialog extends JDialog { 
    public static void main(String[] args){ 
     final SwingDialog dialog = new SwingDialog(); 
     dialog.setVisible(true); 
    } 

    public SwingDialog(){ 
     setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
     setSize(new Dimension(250, 250)); 
     final JComboBox combo = new JComboBox(); 
     for (int i = 0; i< 101; i++){ 
      combo.addItem("text" + i); 
     } 
     final JPanel panel = new JPanel(); 
     panel.setLayout(new FlowLayout()); 
     panel.setPreferredSize(new Dimension(100, 300)); 
     panel.add(combo); 
     panel.add(createJFXPanel()); 
     final JScrollPane scroll = new JScrollPane(panel); 
     getContentPane().add(scroll); 
    } 

    private JFXPanel createJFXPanel(){ 
     final JFXPanel panel = new JFXPanel(); 
     Platform.runLater(new Runnable() { 
      @Override 
      public void run() { 
       final HBox hbox = new HBox(); 
       final ComboBox combo = new ComboBox(); 
       for (int i = 0; i< 101; i++){ 
        combo.getItems().add("text" + i); 
       } 
       hbox.getChildren().add(combo); 
       final Scene scene = new Scene(hbox); 
       panel.setScene(scene); 
      }; 
     }); 
     return panel; 
    } 
} 

還有就是JDialogJPanelJScrollPane具有兩個組合框裏面:第一個是一個JComboBox和第二個是JFXPanel內部的JavaFX組合框。 JComboBox正常工作,但JavaFX組合框無法使用鼠標滾輪進行滾動。看起來,代替滾動本身,鼠標滾輪與所有者JPanel一起滾動JScrollPane(請參見下面的屏幕截圖)。

Behavior on Scroll

在此先感謝非常您的建議。

+0

這是一個知道的bug,它已在JavaFX 8中修復。請嘗試一下。它可以從https://jdk8.java.net下載 – Petr

+0

謝謝,實際的版本jdk-8-fcs-bin-b129-windows-x64-07_feb_2014通過鼠標滾輪在JavaFX ComboBox內解決了問題,但你可以再次看到它的彈出窗口(scrollpane)通過對話框的邊界,最糟糕的是,當您打開JavaFX ComboBox的彈出窗口並滾動對話框的JScrollPane時,比JavaFX ComboBox的彈出窗口開始「飛」。它幾次(不穩定)關閉對話框,並且JavaFX ComboBox的彈出窗口停留在沒有任何對話框的情況下「飛行」。 – alexkishko

+0

因此,最新的研究 - 實際的版本JavaFX 8 beta 129有更多的問題 1)當我打開JavaFX組合框的彈出列表時,我不能點擊JPanel或JScrollPane,但我可以移動JDialog,彈出列表保持「飛出」JDialog。 – alexkishko

回答

0

作爲一個臨時的解決方案,以顯示我的原型客戶我已經這樣:

import javafx.application.Platform; 
import javafx.embed.swing.JFXPanel; 
import javafx.scene.Node; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.scene.layout.VBox; 
import javax.swing.*; 
import java.awt.*; 
import java.awt.event.*; 

public class SwingDialog extends JFrame { //or JDialog 
    public static void main(String[] args){ 
     final SwingDialog dialog = new SwingDialog(); 
     dialog.setVisible(true); 
    } 

    public SwingDialog(){ 
     setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
     setSize(new Dimension(250, 250)); 
     final JComboBox combo = new JComboBox(); 
     for (int i = 0; i< 101; i++){ 
      combo.addItem("text" + i); 
     } 
     final JPanel panel = new JPanel(); 
     panel.setBorder(BorderFactory.createEmptyBorder(20, 0,0,0)); 
     panel.setLayout(new FlowLayout()); 
     panel.setPreferredSize(new Dimension(100, 300)); 
     panel.add(combo); 
     panel.add(createJFXPanel()); 
     final JScrollPane scroll = new JScrollPane(panel); 
     getContentPane().add(scroll); 
    } 

    private JFXPanel createJFXPanel(){ 
     final JFXPanelEx panel = new JFXPanelEx(); 
     Platform.runLater(new Runnable() { 
      @Override 
      public void run() { 
       final VBox vbox = new VBox(); 
       final ComboBox combo = new ComboBox(); 
       for (int i = 0; i< 101; i++){ 
        combo.getItems().add("text" + i); 
       } 
       vbox.getChildren().addAll(combo); 
       final Scene scene = new Scene(vbox); 
       panel.setScene(scene); 
      }; 
     }); 
     return panel; 
    } 

    private class JFXPanelEx extends JFXPanel { 
     public JFXPanelEx(){ 
      addFocusListener(new FocusAdapter() { 
       @Override 
       public void focusLost(FocusEvent e) { 
        hidePopUps(); 
       } 
      }); 
     } 

     private ComponentListener componentListener; 

     @Override 
     public void removeNotify() { 
      super.removeNotify(); 
      final Component parent = SwingUtilities.getRoot(this); 
      if (parent != null){ 
       parent.removeComponentListener(componentListener); 
      } 
     } 

     @Override 
     public void addNotify() { 
      super.addNotify(); 
      final Component parent = SwingUtilities.getRoot(this); 
      componentListener = new ComponentAdapter() { 
       @Override 
       public void componentMoved(ComponentEvent e) { 
        hidePopUps(); 
        processComponentEvent(new ComponentEvent(JFXPanelEx.this, ComponentEvent.COMPONENT_MOVED)); 
       } 

       @Override 
       public void componentResized(ComponentEvent e) { 
        hidePopUps(); 
        processComponentEvent(new ComponentEvent(JFXPanelEx.this, ComponentEvent.COMPONENT_RESIZED)); 
        processComponentEvent(new ComponentEvent(JFXPanelEx.this, ComponentEvent.COMPONENT_MOVED)); //is important!!! 
       } 
      }; 
      parent.addComponentListener(componentListener); 
     } 

     private void hidePopUps(){ 
      final Runnable runnable = new Runnable() { 
       @Override 
       public void run() { 
        hidePopUpsImpl(); 
       } 
      }; 
      if (Platform.isFxApplicationThread()){ 
       runnable.run(); 
      } else { 
       Platform.runLater(runnable); 
      } 
     } 

     private void hidePopUpsImpl(){ 
      if (getScene() != null && getScene().getRoot() != null){ 
       for (final Node node : getScene().getRoot().getChildrenUnmodifiable()){ //JavaFX need interfaces!!! 
        final ComboBox combo = (ComboBox)node; 
        if (combo.isShowing()){ //JavaFX need interfaces!!! 
         combo.hide(); 
        } 
       } 
      } 
     } 
    } 
} 

在Eclispe的多窗口RCP-環境我發佈這些事件從殼容器(REZISED和MODEV)(綜合)到我的框架或對話框。因此我的JFXPanelEx也可以捕獲它們。 以COMPONENT_REZISED觸發COMPONENT_MOVED很重要!否則彈出窗口在Shell-Container內的許多窗口的大小調整後不會得到實際的位置。 看來,這個彈出窗口會以舊的位置打開,所以在那裏沒有窗口。

這是一個補丁,但我希望JavaFX不會很快出現這樣的問題,否則它看起來毫無用處。