4

目标:创建一个具有多种文本字体的圆形按钮。

示例:参见 RoundButtonWithMultipleFonts.java 和 RoundButtonWithMultipleFonts.css

RoundButtonWithMultipleFonts.java:

import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Control;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class RoundButtonWithMultipleFonts extends Application {
  public static void main(String... args) {
    launch(args);
  }

  @Override
  public void start(Stage stage) throws Exception {
    stage.setTitle("Button with multiple fonts?");
    stage.setScene(new Scene(getRoot(), 400, 400));
    stage.getScene().getStylesheets().addAll(getClass().getResource("RoundButtonWithMultipleFonts.css").toExternalForm());
    stage.sizeToScene();
    stage.show();
  }

  private Parent getRoot() {
    Button button = new Button(""); // The labels should be the buttons text
    button.setOnMouseClicked(new EventHandler<MouseEvent>() {
      @Override
      public void handle(MouseEvent mouseEvent) {
        System.out.println("Button clicked");
      }
    });

    Label header = new Label("A Prideful Header"); // Label for big font on button
    header.getStyleClass().addAll("header");

    Label footer = new Label("a humble footer"); // Label for small font on button
    footer.getStyleClass().addAll("footer");

    // Since the labels are on top of the button, pass any events they capture to the button
    configurePassThroughEvents(button, header, footer);

    StackPane stack = new StackPane();
    stack.getChildren().addAll(button, header, footer);

    return stack;
  }

  private void configurePassThroughEvents(Control targetControl, Control... sourceControls) {
    MouseEventPassThrough passThroughEvent = new MouseEventPassThrough(targetControl);
    for(Control sourceControl : sourceControls) {
      sourceControl.setOnMouseClicked(passThroughEvent);
      sourceControl.setOnMouseDragged(passThroughEvent);
      sourceControl.setOnMouseDragEntered(passThroughEvent);
      sourceControl.setOnMouseDragExited(passThroughEvent);
      sourceControl.setOnMouseDragOver(passThroughEvent);
      sourceControl.setOnMouseDragReleased(passThroughEvent);
      sourceControl.setOnMouseEntered(passThroughEvent);
      sourceControl.setOnMouseExited(passThroughEvent);
      sourceControl.setOnMouseMoved(passThroughEvent);
      sourceControl.setOnMousePressed(passThroughEvent);
      sourceControl.setOnMouseReleased(passThroughEvent);
    }
  }

  private static class MouseEventPassThrough implements EventHandler<MouseEvent> {
    private final Control targetControl;
    private MouseEventPassThrough(Control targetControl) { this.targetControl = targetControl; }
    @Override public void handle(MouseEvent mouseEvent) { targetControl.fireEvent(mouseEvent); }
  }
}

RoundButtonWithMultipleFonts.css:

.button {
  -fx-border-width: 1px;
  -fx-border-color: #000000;
  -fx-border-radius: 45;
  -fx-background-color: linear-gradient(#ffffff 0%, #cccccc 100%);
  -fx-background-radius: 45;
  -fx-padding: 50 100;
}
.button:hover {
  -fx-background-color: linear-gradient(#ffffff 0%, coral 100%);
}

.label {
  -fx-padding: 10;
  -fx-background-color: cornflowerblue;
}

.header {
  -fx-font-size: 110%;
  -fx-font-weight: bold;
  -fx-translate-y: -20;
}

.footer {
  -fx-font-size: 80%;
  -fx-translate-y: 20;
}

运行时结果:

鼠标位于按钮的角上,但不在按钮的视觉边界内。 该按钮显示为好像鼠标悬停在其上,但鼠标未位于由 css 边框和背景属性指定的按钮的视觉边界上。

问题:

  1. 当鼠标滚动到按钮的一个角上时,按钮进入悬停状态,但鼠标仍在按钮的边框和背景所指示的按钮的视觉范围之外。(见图。)

  2. 此示例使用堆栈窗格、多个标签、事件传递机制和 css 技巧来提供包含具有多种字体的文本的按钮的外观。

问题:

  1. 仅当鼠标与具有边框或背景属性的css中指定的按钮视觉边界发生冲突时,如何指定按钮应进入悬停状态?

  2. 有没有比本例更简单的方法来为按钮指定多种字体(具有一般文本布局)?理想情况下,我只想使用带有嵌套节点的按钮作为文本。这将允许我在按钮文本区域内放置我想要的任何内容,而无需事件通过机制、StackPane 和 css 技巧。

4

1 回答 1

6

您可以使用类setGraphic(Node node);方法Button在按钮上设置自定义标签。这是一个例子,

Label header = new Label("A Prideful Header");
header.getStyleClass().addAll("header");

Label footer = new Label("a humble footer");
footer.getStyleClass().addAll("footer");


VBox box = new VBox();
box.getChildren().addAll(header,footer);

Button button = new Button();
button.setGraphic(box);
于 2013-06-20T04:10:33.083 回答