我有一个我无法解决的问题.我想将进度条实现到组合框中:
public class JavaFXApplication4 extends Application { @Override public void start(Stage primaryStage) { double y1 = 15; ProgressBar p1 = new ProgressBar(); p1.setLayoutY(y1); HBox vb1 = new HBox(10); vb1.getChildren().addAll(new Label("Progressbar 1"),p1); double y2 = 15; ProgressBar p2 = new ProgressBar(); p2.setLayoutY(y2); HBox vb2 = new HBox(10); vb2.getChildren().addAll(new Label("Progressbar 2"),p2); double y3 = 15; ProgressBar p3 = new ProgressBar(); p3.setLayoutY(y3); HBox vb3 = new HBox(10); 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<HBox> combo = new ComboBox<>(); public TextChooser(HBox... 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,10)); combo.getItems().setAll(options); combo.setCellFactory(new Callback<ListView<HBox>,ListCell<HBox>>() { @Override public ListCell<HBox> call(ListView<HBox> p) { return new ListCell<HBox>() { @Override protected void updateItem(HBox 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); } } }
你能告诉我如何使用setButtonCell将Progressbar显示到组合框中吗?
解决方法
You should not be placing Nodes into the items list – rather the data should be stored there and then rendered with your cell factory.
例如:
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,vb3 ); textChooser.setStyle( "-fx-font: 10px \"Verdana\";" ); StackPane root = new StackPane(); root.getChildren().add( textChooser ); Scene scene = new Scene( root,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 ); } } }