2013-12-11 143 views
0

我有一个带进度条的组合框的例子。Combobox进度条无法正常工作

package javafxapplication4; 

import javafx.application.Application; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.ComboBox; 
import javafx.scene.control.Label; 
import javafx.scene.control.ListCell; 
import javafx.scene.control.ListView; 
import javafx.scene.control.ProgressBar; 
import javafx.scene.layout.StackPane; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 
import javafx.util.Callback; 


public class JavaFXApplication4 extends Application 
{ 

    @Override 
    public void start(Stage primaryStage) 
    { 

    double y1 = 15; 
     ProgressBar p1 = new ProgressBar(); 
     p1.setLayoutY(y1); 
    VBox vb1 = new VBox(); 
    vb1.getChildren().addAll(new Label("Progressbar 1"), p1); 

    double y2 = 15; 
     ProgressBar p2 = new ProgressBar(); 
     p2.setLayoutY(y2); 
    VBox vb2 = new VBox(); 
    vb2.getChildren().addAll(new Label("Progressbar 2"), p2); 

    double y3 = 15; 
     ProgressBar p3 = new ProgressBar(); 
     p3.setLayoutY(y3); 
    VBox vb3 = new VBox(); 
    vb3.getChildren().addAll(new Label("Progressbar 3"), p3); 


    TextChooser textChooser = new TextChooser(
     vb1, vb2, vb3 
    ); 

    textChooser.setStyle("-fx-font: 10px \"Verdana\";"); 





     StackPane root = new StackPane(); 
     root.getChildren().add(textChooser); 

     Scene scene = new Scene(root, 300, 250); 

     primaryStage.setTitle("Hello World!"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 


    public static class TextChooser extends StackPane { 
    private Label label = new Label(); 

    private ComboBox<VBox> combo = new ComboBox<>(); 

    public TextChooser(VBox... options) { 
     StackPane.setAlignment(label, Pos.CENTER_LEFT); 
     StackPane.setAlignment(combo, Pos.CENTER_LEFT); 

     label.graphicProperty().bind(
      //combo.getSelectionModel().selectedItemProperty() 
      combo.getSelectionModel().selectedItemProperty() 
     ); 
     label.visibleProperty().bind(
      combo.visibleProperty().not() 
     ); 
     //label.setPadding(new Insets(0, 0, 0, 10)); 

     combo.getItems().setAll(options); 

     combo.setCellFactory(new Callback<ListView<VBox>, ListCell<VBox>>() { 
      @Override public ListCell<VBox> call(ListView<VBox> p) { 
       return new ListCell<VBox>() { 
        @Override protected void updateItem(VBox item, boolean empty) { 
         super.updateItem(item, empty); 

         if (item == null || empty) { 
          setGraphic(null); 
         } else { 
          setGraphic(item); 
         } 
        } 
       }; 
      } 
     }); 

     combo.getSelectionModel().select(0); 
     combo.setVisible(true); 

     label.setOnMouseEntered(event -> combo.setVisible(true)); 
     combo.showingProperty().addListener(observable -> { 
      if (!combo.isShowing()) { 
       combo.setVisible(false); 
      } 
     }); 
     combo.setOnMouseExited(event -> { 
      if (!combo.isShowing()) { 
       combo.setVisible(false); 
      } 
     }); 

     getChildren().setAll(label, combo); 
    } 

    public static void main(String[] args) 
    { 
     launch(args); 
    } 
    } 
} 

我想在应用程序工作时显示带有工作后台进程的进度条。当我将鼠标移到进度条上时,我想查看所有进程。但由于某些原因代码工作不正常 - 当我选择进度条时,没有进度条显示。你能帮我看看这段代码吗?

回答

2

如这里https://stackoverflow.com/a/20630806/3110608

public class JavaFXApplication5 extends Application 
{ 
    public static void main(String[] args) 
    { 
     launch(args); 
    } 


    public class ProgressData 
    { 
     private final DoubleProperty progressProp = new SimpleDoubleProperty(); 
     private final StringProperty progressName = new SimpleStringProperty(); 

     public ProgressData(String name, double progress) 
     { 
      progressProp.set(progress); 
      progressName.set(name); 
     } 

     public DoubleProperty progressProperty() 
     { 
      return progressProp; 
     } 

     public StringProperty nameProperty() 
     { 
      return progressName; 
     } 

     @Override 
     // Lazy hack for the combo button. 
     public String toString() 
     { 
      return progressName.get(); 
     } 
    } 


    @Override 
    public void start(Stage primaryStage) 
    { 
     ProgressData vb1 = new ProgressData("Progressbar 1", -1); 
     ProgressData vb2 = new ProgressData("Progressbar 2", 0.2); 
     ProgressData vb3 = new ProgressData("Progressbar 3", 0.3); 

     TextChooser textChooser = new TextChooser(vb1, vb2, vb3); 

     textChooser.setStyle("-fx-font: 10px \"Verdana\";"); 

     StackPane root = new StackPane(); 
     root.getChildren().add(textChooser); 

     Scene scene = new Scene(root, 300, 250); 

     primaryStage.setTitle("Hello World!"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public static class TextChooser extends StackPane 
    { 
     private final Label label = new Label(); 

     private final ComboBox<ProgressData> combo = new ComboBox<>(); 

     public TextChooser(ProgressData... options) 
     { 
      StackPane.setAlignment(label, Pos.CENTER_LEFT); 
      StackPane.setAlignment(combo, Pos.CENTER_LEFT); 


      final ProgressBar labelBar = new ProgressBar(); 
      label.visibleProperty().bind(combo.visibleProperty().not()); 
      label.setContentDisplay(ContentDisplay.RIGHT); 
      label.setGraphic(labelBar); 


      combo.getItems().setAll(options); 

      // This will change the label's text and the progress bar value. 
      combo.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<ProgressData>() 
      { 
       @Override 
       public void changed(ObservableValue<? extends ProgressData> observable, ProgressData oldValue, ProgressData newValue) 
       { 
        if (labelBar.progressProperty().isBound()) 
        { 
         labelBar.progressProperty().unbind(); 
        } 

        labelBar.progressProperty().bind(newValue.progressProperty()); 
        label.setText(newValue.nameProperty().get()); 
       } 
      }); 

      combo.setCellFactory(new Callback<ListView<ProgressData>, ListCell<ProgressData>>() 
      { 
       @Override 
       public ListCell<ProgressData> call(ListView<ProgressData> p) 
       { 
        return new ListCell<ProgressData>() 
        { 
         private final ProgressBar cellBar = new ProgressBar(); 
         { 
          cellBar.setMouseTransparent(true); 
          setContentDisplay(ContentDisplay.RIGHT); 
          setGraphic(cellBar); 
         } 

         @Override 
         protected void updateItem(ProgressData item, boolean empty) 
         { 
          super.updateItem(item, empty); 

          if (item != null && ! empty) 
          { 
           if (cellBar.progressProperty().isBound()) 
           { 
            cellBar.progressProperty().unbind(); 
           } 
           cellBar.progressProperty().bind(item.progressProperty()); 
           setText(item.nameProperty().get()); 
          } 
         } 
        }; 
       } 
      }); 

      combo.getSelectionModel().select(0); 
      combo.setVisible(true); 

      label.setOnMouseEntered(new EventHandler<MouseEvent>() 
      { 
       @Override 
       public void handle(MouseEvent event) 
       { 
        combo.setVisible(true); 
       } 
      }); 

      combo.showingProperty().addListener(new InvalidationListener() 
      { 
       @Override 
       public void invalidated(Observable observable) 
       { 
        if (!combo.isShowing()) 
        { 
         combo.setVisible(false); 
        } 
       } 
      }); 

      combo.setOnMouseExited(new EventHandler<MouseEvent>() 
      { 
       @Override 
       public void handle(MouseEvent event) 
       { 
        if (!combo.isShowing()) 
        { 
         combo.setVisible(false); 
        } 
       } 
      }); 

      getChildren().setAll(label, combo); 
     } 

    } 

} 
+0

非常好的例子。谢谢! –

3

要更改显示的“按钮”(即选定值显示),你需要使用

combo.setButtonCell(...); 

我不认为它会在你的情况,但是。问题是你有一个Node子类(一个VBox)作为你的ComboBox的类型。因此,所选项目将出现在场景图的两个位置:一次在下拉列表中,一次在ComboBox按钮中。总的来说这是一个非常糟糕的主意,使用节点作为组合框类型:看到Javadocs

把节点到项目列表强烈不推荐

您应该改用ComboBox的数据类型并在ListCell实现中创建VBox。

+0

贴能否请你告诉我怎么解决这个问题的代码。这对我来说是非常先进的。 –

+0

只要看看Javadoc中的例子。还有一个在https://gist.github.com/james-d/7722752上显示后台任务进度的例子。这个例子使用了ListView而不是ComboBox,但是其基本思想是相似的。 –

+0

我无法解决这个问题。你能编辑我的编辑并修复这个问题吗? –