gpt4 book ai didi

JavaFX SplitMenuButton 设置箭头的位置

转载 作者:太空宇宙 更新时间:2023-11-04 12:34:05 26 4
gpt4 key购买 nike

普通的 SplitMenuButton 看起来像这样: Standard SplitMenuButton

我想更改 JavaFX SplitMenuButton 中箭头的位置,但无法确定是否有一个配置可以给我这样的东西: SplitMenuButton with arrow on bottom

这可能吗?或者我需要创建拆分菜单按钮的定制版本?

最佳答案

使用 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);
}
}

关于JavaFX SplitMenuButton 设置箭头的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37522801/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com