【问题标题】:How to bind text size to slider in javafx?如何将文本大小绑定到 javafx 中的滑块?
【发布时间】:2021-05-07 08:01:36
【问题描述】:

您好,我正在尝试显示一个 Text 对象和一个控制文本字体大小的滑块。 使用 JavaFX 属性值观察滑块值的变化,然后根据滑块值更新文本大小。我错过了什么吗?

import javafx.event.ActionEvent;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.text.Text;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;

public class TextSlider extends VBox
{
    private Text text;
    private Slider slider;
    private VBox vbox;
    private Font font;
    private double initVal = 20;
    public TextSlider()
    {
        text = new Text("Amsterdam");
        slider = new Slider(0,150,100);
        text.setFont(new Font(initVal));
       // slider.setShowTickMarks(true);
        //slider.setPadding(new Insets(10,10,10,10));
        //text.fontProperty();
        text.textProperty().bind(slider.valueProperty());
        vbox = new VBox(text,slider);
        vbox.setAlignment(Pos.CENTER);
        vbox.getChildren().addAll(vbox);

    }
}

【问题讨论】:

  • 我不确定您是否可以直接使用属性绑定来执行此操作,但您可以将更改侦听器注册到滑块值属性并在侦听器中更新文本字体的大小。
  • 如果您将文本的 textProperty 绑定到滑块的 valueProperty(在本例中是一个数字),您期望会发生什么?使用正确的类型,编译器会告诉你这是不可能的(想知道这怎么不会爆炸......)
  • *hach .. 它甚至无法编译 ;)
  • @Puce 我不确定你是否可以使用属性绑定来做到这一点如果 OP 真的想更改文本的字体大小(字体是不可变的)
  • 即使打字和编译问题得到解决,这实际上也不会做任何事情,因为代码存在结构问题。您有一个 VBox 子类,但您永远不会更改当前 VBox 实例的任何状态。相反,您创建一个新的VBox 并向其中添加内容,但您永远无法使该新的VBox 可访问。您需要确定是使用继承(不推荐)还是某种创建模式(推荐),坚持一个,并正确实施。

标签: java user-interface javafx


【解决方案1】:

您不能直接绑定字体大小。但是你可以使用text.styleProperty()。 style 属性使您可以通过类似 css 的样式来更改外观。您甚至可以将其绑定到其他属性。

textNode.styleProperty().bind(
    Bindings.concat("-fx-font-size: ", slider.valueProperty().asString()));

这将在每次滑块的 value 属性更改时更新文本节点的 style 属性。如果滑块值更改为 20,样式将设置为 -fx-font-size: 20

另一种选择是使用更改侦听器并在更改的事件上设置新字体:

slider.valueProperty().addListener(new ChangeListener<Number>() {

      @Override
      public void changed(
         ObservableValue<? extends Number> observableValue, 
         Number oldValue, 
         Number newValue) { 
            text.setFont(new Font(newValue.doubleValue()));
      }
});

Java 8+:(与上面相同的代码)

slider.valueProperty().addListener(
        (observableValue, oldValue, newValue) ->
                text.setFont(new Font(newValue.doubleValue()))
);

【讨论】:

  • 您也可以使用适当的自定义绑定来执行text.fontProperty().bind(...)。但请注意,如果不解决 OP 代码中的结构性问题,这些似乎都不起作用。 (VBox 子类也包含不可访问的 VBox 等)
  • @James_D Shure 但绑定 fontProperty 对我来说似乎更复杂。当我对绑定不太了解时,以上是我发现最有用的内容。感谢您指出 OP 代码中的结构性问题。至少这个答案可以帮助其他正在搜索绑定字体大小的人。
  • 感谢@Matt 我想了解 Lamba 真正在做什么,但除了 youtube 上的 bucky 的 fx 教程之外,我无法理解它们。在我的书中,我看到你在匿名内部类中所做的事情也很酷,我已经修改它以使用一个单独的类,除了我对这个主题仍然有点困惑
  • @Matt slider.valueProperty().addListener(this::changed); // // ////////////////////////////////////// ////////////////// public void changed(ObservableValue extends Number> observableValue, Number oldValue, Number newValue) { text.setFont(new Font(newValue.doubleValue ())); }
【解决方案2】:

请注意,问题中的代码结构已损坏。您将TextSlider 类作为VBox 的子类,但从未向TextSlider 实例添加任何元素。相反,您创建一个新的VBox 并向其中添加内容;但是,由于无法访问新的 VBox,因此无法使用您的 TextSlider 类来实际查看任何内容。

其他答案显示了将字体大小绑定到滑块的其他方法; imo 最直接的方法是使用自定义绑定来绑定文本的fontProperty()。这看起来像:

text.fontProperty().bind(Bindings.createObjectBinding(
    () -> Font.font(slider.getValue()),
    slider.valueProperty()
));

这是一个使用此绑定的工作 TextSlider 类:

import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Slider;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.scene.text.Text;

public class TextSlider {

    private Text text;
    private Slider slider;
    private VBox vbox;
    private double initVal = 20;
    public TextSlider(String text) {
        this.text = new Text(text);
        slider = new Slider(0,150,initVal);

       // slider.setShowTickMarks(true);
        //slider.setPadding(new Insets(10,10,10,10));

        this.text.fontProperty().bind(Bindings.createObjectBinding(
            () -> Font.font(slider.getValue()),
            slider.valueProperty()
        ));        

        vbox = new VBox(this.text,slider);
        vbox.setAlignment(Pos.CENTER);
    }

    public Node asNode() {
        return vbox ;
    }

    public StringProperty textProperty() {
        return text.textProperty();
    }

    public final String getText() {
        return textProperty().get();
    }

    public final void setText(String text) {
        textProperty().set(text);
    }

    public DoubleProperty fontSizeProperty() {
        return slider.valueProperty();
    }

    public final double getFontSize() {
        return fontSizeProperty().get();
    }

    public final void setFontSize(double fontSize) {
        fontSizeProperty().set(fontSize);
    }
}

典型的用例如下所示:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class App extends Application {

    @Override
    public void start(Stage stage) {
        BorderPane root = new BorderPane();
        TextSlider textSlider = new TextSlider("Amsterdam");
        root.setTop(textSlider.asNode());
        
        Scene scene = new Scene(root, 800, 800);
        stage.setScene(scene);
        stage.show();
    }

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

}

【讨论】:

    猜你喜欢
    • 2012-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-25
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多