2016-05-30 27 views
1

通常SplitMenuButtonは次のようになります。私はJavaFXのSplitMenuButtonの矢印の位置を変更したいと思いますが、その意志さえ設定がある場合はうまくいかないことができStandard SplitMenuButtonJavaFXのSplitMenuButtonは、矢印の位置を設定すること

私に次のようなものを教えてください: SplitMenuButton with arrow on bottom

これは可能ですか、スプリットメニューボタンの特注版を作成する必要がありますか?

答えて

1

JavaFX SplitMenuButtonで再生した後、私は必要なもの(デフォルトの右以外のメニュー矢印)を簡単に再現する方法が見つかりませんでした。矢印ボタンをメインボタンのいずれかの側に置くことができるボタンクラスを作成しました。クラスは洗練されていませんが、仕事をしています。このサンプルクラスの大きな点は、矢印の側を動的に変更できることです。

クラスのコード:

public class MyButton extends Group { 

private ButtonBase label; 
private ButtonBase arrowButton; 
protected ContextMenu popup; 
private ObjectProperty<SplitMode> splitMode; 
private DoubleProperty sizeBinding; 
private DoubleProperty layoutBinding; 
private double oldSizeValue; 
private double oldLayoutValue; 
private PseudoClass layoutClass; 

// 
private static PseudoClass TOP_PSEUDO_CLASS = PseudoClass.getPseudoClass("top"); 
private static PseudoClass BOTTOM_PSEUDO_CLASS = PseudoClass.getPseudoClass("bottom"); 
private static PseudoClass LEFT_PSEUDO_CLASS = PseudoClass.getPseudoClass("left"); 
private static PseudoClass RIGHT_PSEUDO_CLASS = PseudoClass.getPseudoClass("right"); 
private static PseudoClass HIDDEN_PSEUDO_CLASS = PseudoClass.getPseudoClass("hidden"); 

public static enum SplitMode { 
    SPLIT_TOP, // put arrow buton on top 
    SPLIT_RIGHT, // put arrow button on right 
    SPLIT_BOTTOM, // bottom 
    SPLIT_LEFT, // left 
    HIDDEN // hides the arrow button regardless of visibility 
} 

private void changeToPseudoClass(PseudoClass newClass) { 
    pseudoClassStateChanged(layoutClass, false); 
    pseudoClassStateChanged(newClass, true); 
    layoutClass = newClass; 
} 

private void bindHidden() { 

    if (sizeBinding != null) { 
     sizeBinding.unbind(); 
     sizeBinding.set(oldSizeValue); 
    } 
    if (layoutBinding != null) { 
     layoutBinding.unbind(); 
     layoutBinding.set(oldLayoutValue); 
    } 
    arrowButton.setVisible(false); 
    changeToPseudoClass(HIDDEN_PSEUDO_CLASS); 
} 

private void bindSizeAndLayout(DoubleProperty sizeFrom, ReadOnlyDoubleProperty sizeTo, 
     DoubleProperty layoutFrom, ReadOnlyDoubleProperty layoutTo, 
     PseudoClass newPseudoClass) { 

    if (sizeBinding != null) { 
     sizeBinding.unbind(); 
     sizeBinding.set(oldSizeValue); 
    } 
    if (layoutBinding != null) { 
     layoutBinding.unbind(); 
     layoutBinding.set(oldLayoutValue); 
    } 
    oldSizeValue = sizeFrom.get(); 
    sizeBinding = sizeFrom; 
    oldLayoutValue = layoutFrom.get(); 
    layoutBinding = layoutFrom; 
    sizeFrom.bind(sizeTo); 
    layoutFrom.bind(layoutTo); 
    changeToPseudoClass(newPseudoClass); 
    arrowButton.setVisible(true); 
} 

public void setSplitMode(SplitMode mode) { 
    if (splitMode == null) { 
     splitMode = new SimpleObjectProperty(); 
    } 
    if (splitMode.get() == mode) { 
     return; 
    } // no changes needed 
    splitMode.set(mode); 

    // set up new bindings 
    switch (mode) { 
     case SPLIT_BOTTOM: 
      // bind arrowbutton width to label width 
      // bind arrowbutton starting position to bottom of label 
      bindSizeAndLayout(arrowButton.prefWidthProperty(), label.widthProperty(), 
        arrowButton.layoutYProperty(), label.heightProperty(), 
        BOTTOM_PSEUDO_CLASS); 
      break; 
     case SPLIT_RIGHT: 
      // bind arrowbutton height to label height 
      bindSizeAndLayout(arrowButton.prefHeightProperty(), label.heightProperty(), 
        arrowButton.layoutXProperty(), label.widthProperty(), 
        RIGHT_PSEUDO_CLASS); 
      break; 
     case SPLIT_LEFT: 
      // bind arrowbutton height to label height 
      bindSizeAndLayout(arrowButton.prefHeightProperty(), label.heightProperty(), 
        label.layoutXProperty(), arrowButton.widthProperty(), 
        LEFT_PSEUDO_CLASS); 
      break; 
     case SPLIT_TOP: 
      // bind arrowbutton width to label height 
      bindSizeAndLayout(arrowButton.prefWidthProperty(), label.widthProperty(), 
        label.layoutYProperty(), arrowButton.heightProperty(), 
        TOP_PSEUDO_CLASS); 
      break; 
     case HIDDEN: 
      // unbind all and hide button 
      bindHidden(); 
      break; 
    } 

} 

public SplitMode getSplitMode() { 
    return (splitMode == null) ? SplitMode.HIDDEN : splitMode.get(); 
} 

public ObjectProperty splitModeProperty() { 
    return splitMode; 
} 

public ButtonBase getButton() { 
    return label; 
} 

public ButtonBase getArrowButton() { 
    return arrowButton; 
} 

// Test suite 
public MyButton() { 
    this(""); 
} 

public MyButton(String text) { 
    this(text, SplitMode.SPLIT_RIGHT); 
} 

@SuppressWarnings("OverridableMethodCallInConstructor") 
public MyButton(String text, SplitMode mode) { 
    label = new Button(text); 
    label.getStyleClass().setAll("label"); 
    arrowButton = new Button(); 
    // bind the managed property to visibility. 
    // we dont want to manage an invisible button. 
    arrowButton.managedProperty().bind(arrowButton.visibleProperty()); 
    arrowButton.getStyleClass().setAll("arrow-button"); 
    getStyleClass().setAll("split-menu-button"); 
    getChildren().clear(); 
    getChildren().addAll(label, arrowButton); 
    setSplitMode(mode); 

} 

}// end of class 

MyButtonというクラスは、それぞれの側のための特別な書式設定を有効にするために、追加の疑似クラスを作成します。

サンプルCSS:

.split-menu-button > .label { 
 
    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; 
 
    -fx-background-insets: 0, 1 0 1 1, 2 1 2 2; 
 
    -fx-background-radius: 5 0 0 5, 4 0 0 4, 3 0 0 3; 
 
    -fx-padding: 0.166667em 0.667em 0.25em 0.833333em; /* 2 8 3 10 */ 
 
    /* -fx-graphic:url("./icon_32.png"); */ 
 
    -fx-content-display: top; 
 
    -fx-alignment: center; 
 
} 
 
.split-menu-button:top > .label { 
 
    -fx-background-insets: 0, 1 0 1 1, 2 1 2 2; 
 
    -fx-background-radius: 0 0 5 5, 0 0 4 4, 0 0 3 3; 
 
} 
 
.split-menu-button:right > .label { 
 
    -fx-background-insets: 0, 1 0 1 1, 2 1 2 2; 
 
    -fx-background-radius: 5 0 0 5, 4 0 0 4, 3 0 0 3; 
 
} 
 
.split-menu-button:bottom > .label { 
 
    -fx-background-insets: 0, 1 0 1 1, 2 1 2 2; 
 
    -fx-background-radius: 5 5 0 0, 4 4 0 0, 3 3 0 0; 
 
} 
 
.split-menu-button:left > .label { 
 
    -fx-background-insets: 0, 1 0 1 1, 2 1 2 2; 
 
    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0; 
 
} 
 
.split-menu-button:hidden > .label { 
 
    -fx-background-insets: 0, 1 0 1 1, 2 1 2 2; 
 
    -fx-background-radius: 5 5 5 5, 4 4 4 4, 3 3 3 3; 
 
} 
 
.split-menu-button > .arrow-button { 
 
    -fx-background-color: -fx-outer-border, -fx-inner-border, -fx-body-color; 
 
    -fx-background-insets: 0, 1, 2; 
 
    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0; 
 
    -fx-padding: 0; /* 0.5em 0.667em 0.5em 0.667em; /* 6 8 6 8 */ 
 
    -fx-graphic:url("./arrow.png"); 
 
    -fx-alignment:center; 
 
} 
 
.split-menu-button:top > .arrow-button { 
 
    -fx-background-insets: 0, 1, 2; 
 
    -fx-background-radius: 5 5 0 0, 4 4 0 0, 3 3 0 0; 
 
} 
 
.split-menu-button:right > .arrow-button { 
 
    -fx-background-insets: 0, 1, 2; 
 
    -fx-background-radius: 0 5 5 0, 0 4 4 0, 0 3 3 0; 
 
} 
 
.split-menu-button:bottom > .arrow-button { 
 
    -fx-background-insets: 0, 1, 2; 
 
    -fx-background-radius: 0 0 5 5, 0 0 4 4, 0 0 3 3; 
 
} 
 
.split-menu-button:left > .arrow-button { 
 
    -fx-background-insets: 0, 1, 2; 
 
    -fx-background-radius: 5 0 0 5, 4 0 0 4, 3 0 0 3; 
 
}

サンプルアプリケーションは、ボタンをテストします。

import javafx.application.Application; 
import static javafx.application.Application.launch; 
import javafx.event.ActionEvent; 
import javafx.geometry.Pos; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.ContextMenu; 
import javafx.scene.control.Label; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 
import MyButton.SplitMode; 

public class SimpleTest 
    extends Application { 

    Stage primaryStage; 
    protected ContextMenu popup; 

    @Override 
    public void start(final Stage stage) throws Exception { 
     primaryStage = stage; 
     primaryStage.setTitle("SimpleTest."); 

     Label label = new Label(); 
     Button rotate = new Button("Rotate"); 
     MyButton b = new MyButton("My Test", SplitMode.SPLIT_TOP); 
     label.setText(b.getSplitMode().toString()); 
     StackPane sp = new StackPane(); 
     sp.setPrefSize(200, 200); 
     sp.getStylesheets().add("test.css"); 

     rotate.setOnAction((ActionEvent t) -> { 
      switch(b.getSplitMode()){ 
       case SPLIT_TOP: 
        b.setSplitMode(SplitMode.SPLIT_RIGHT); 
        break; 
       case SPLIT_RIGHT: 
        b.setSplitMode(SplitMode.SPLIT_BOTTOM); 
        break; 
       case SPLIT_BOTTOM: 
        b.setSplitMode(SplitMode.SPLIT_LEFT); 
        break; 
       case SPLIT_LEFT: 
        b.setSplitMode(SplitMode.HIDDEN); 
        break; 
       case HIDDEN: 
        b.setSplitMode(SplitMode.SPLIT_TOP); 
        break; 
      } 
      label.setText(b.getSplitMode().toString()); 
     }); 
     StackPane.setAlignment(label, Pos.TOP_LEFT); 
     StackPane.setAlignment(rotate, Pos.TOP_RIGHT); 
     sp.getChildren().addAll(b, label, rotate); 
     primaryStage.setScene(new Scene(sp)); 
     primaryStage.toFront(); 
     primaryStage.show(); 
    } 


    public static void main(String[] args) { 
     launch(args); 
    } 
    } 
関連する問題