【问题标题】:Scale up or down text to fit label container JavaFX放大或缩小文本以适应标签容器 JavaFX
【发布时间】:2021-06-28 18:26:56
【问题描述】:

基本上我想要实现的是希望字体大小自动调整。我有一个 1920*1080 的窗口,标签是全宽和全高。我启用了文本换行,因为我打算在该软件中运行歌词。所以想法是使文本尽可能大的字体适合容器。或者,如果文本太多,不要消失在屏幕底部,而是简单地缩小字体。我使用场景构建器制作了大部分框架,它运行 FXML。提前谢谢你的帮助。也许我所拥有的图像会有所帮助。[这是图像][1]

Presentation.fxml

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="1080.0" prefWidth="1920.0" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.presentationController">
  <children>
     <Canvas fx:id="screen" height="1080.0" nodeOrientation="INHERIT" width="1920.0">
        <cursor>
           <Cursor fx:constant="NONE" />
        </cursor>
     </Canvas>
     <Label fx:id="displayText" alignment="CENTER" layoutX="-2.0" layoutY="-4.0" prefHeight="1085.0" prefWidth="1924.0" text="Стучатся молитвы в небо, Касаясь святых небес! Звучат в них печаль и горе, И боль, как глубокий порез! Молитвы такие о детях, Родители в небо кричат! Они днем и  ночью взывают! Не могут сердца их молчать!" textAlignment="CENTER" textFill="WHITE" textOverrun="WORD_ELLIPSIS" wrapText="true">
        <font>
           <Font size="79.0" />
        </font>
        <padding>
           <Insets bottom="40.0" left="40.0" right="40.0" top="40.0" />
        </padding>
        <cursor>
           <Cursor fx:constant="NONE" />
        </cursor>
     </Label>
  </children>
  <cursor>
     <Cursor fx:constant="NONE" />
  </cursor>

演示控制器.java

    package main;

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.control.Label;

import java.net.URL;
import java.util.ResourceBundle;

public class presentationController implements Initializable {

    @FXML public Canvas screen;
    @FXML public Label displayText;
    public drawScreen toscreen;

    public presentationController() {
        toscreen = new drawScreen();

    }

    public void initialize(URL url, ResourceBundle resourceBundle) {
        toscreen.initd(screen,displayText);
        toscreen.draw();
        toscreen.displayText("Стучатся молитвы в небо, Касаясь святых небес!\n" +
                "Звучат в них печаль и горе,\n" +
                "И боль, как глубокий порез!\n" +
                "Молитвы такие о детях,\n" +
                "Родители в небо кричат!\n" +
                "Они днем и  ночью взывают!\n" +
                "Звучат в них печаль и горе,\n" +
                "И боль, как глубокий порез!\n" +
                "Молитвы такие о детях,\n" +
                "Родители в небо кричат!\n" +
                "Они днем и  ночью взывают!\n" +
                "Звучат в них печаль и горе,\n" +
                "И боль, как глубокий порез!\n" +
                "Молитвы такие о детях,\n" +
                "Родители в небо кричат!\n" +
                "Они днем и  ночью взывают!\n" +
                "Не могут сердца их молчать");
        
    }


}

画屏

    package main;

import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.control.Label;
import javafx.scene.image.Image;

import java.io.IOException;

public class drawScreen {
    Canvas previewScreen;
    Canvas displayScreen;
    public GraphicsContext g1;
    public GraphicsContext g2;
    public Label songLyricsPre;
    public Label songLyricsDis;
    public drawScreen(){

    }
    public void initp(Canvas previewScreen, Label text){
        this.previewScreen = previewScreen;
        this.songLyricsPre = text;
        System.out.println("Display Initialized: Preview");
    }
    public void initd( Canvas displayScreen, Label text){
        this.displayScreen = displayScreen;
        this.songLyricsDis = text;
        System.out.println("Display Initialized: Main");
    }
    public void draw(){
        Image i = new Image("/img/basic.png");

        try {
            if (previewScreen != null) {
                g1 = previewScreen.getGraphicsContext2D();
                g1.drawImage(i, 0, 0, previewScreen.getWidth(), previewScreen.getHeight());
            }
            if (displayScreen != null) {
                g2 = displayScreen.getGraphicsContext2D();
                g2.drawImage(i, 0, 0, displayScreen.getWidth(), displayScreen.getHeight());
            }
        } catch (Exception e){
            System.out.println("Failed to read Canvas");
        }
    }
    public void displayText(String text){
        try {
            if (previewScreen != null) {
                songLyricsPre.setText(text);
            }
            if (displayScreen != null) {
                songLyricsDis.setText(text);
            }
        } catch (Exception e){
            System.out.println("Failed to read Canvas");
        }

    }



}

我希望这足以帮助您了解发生了什么 [1]:https://i.stack.imgur.com/QKrLb.png

【问题讨论】:

  • 请使用java命名约定
  • 等等什么意思?
  • 你问的不是认真的,是吗 :) 只需在你最喜欢的在线搜索字段中输入单词即可找到..
  • 老兄,对不起,我不擅长 java 中的命名约定。我对此有点菜鸟,否则我不会在这里问任何问题。我觉得我遵循的很好,也许不是,我还有改进的地方。
  • 我也只是查了一下,我的代码不符合这些命名约定。

标签: java javafx scenebuilder


【解决方案1】:

我的回答背后的基本思想是,比较 Label 及其容器的 widthheight 属性可以反映正在显示的文本量(以及隐藏的量)。
当一个标签的字体加倍时,widthheightLabel 加倍。

如果文本被完美包裹,每行末尾没有多余的空格,则标签的面积将增加四倍。我假设布局节点保持不变,标签的宽度也保持不变。任何额外的文本都会导致高度增加(并且文本会超出布局节点的范围并超出视图)。

目标是保持label 和容器的区域相同(所以没有任何东西被隐藏)。它们的面积之比就是它们的高度之比,因为宽度是恒定的。现在应该乘以字体的因子是面积比的平方根。 (因为面积与字体^2 成正比)。每次Label 的高度发生变化时,都可以按照上面的说明对字体进行相应的更改。

由于每行末尾有多余的空格,现在该方法存在固有错误。每次更改字体时,额外空格的数量可能会增加或减少,即使在计算之后也会导致Label 和容器的区域不匹配。重新计算往往会减少这个错误。在我的代码中,如果计算出的font 在前一个的 5% 以内,则不会重新计算。

这是一个有效的应用程序:

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage stage) throws Exception{
        FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
        Parent root = loader.load();
        Controller c = loader.getController();
        stage.setTitle("Hello World");
        stage.setScene(new Scene(root));
        stage.show();
    }


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

import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.Pane;

public class Controller {
    @FXML Label label;
    double font;
    int error = 5;//%
    @FXML Pane pane;
    @FXML TextField input;

    @FXML void initialize(){
        font = 15;
        label.setStyle("-fx-font-size: " + font);

        label.heightProperty().addListener(new ChangeListener<Number>() {
            //The changed(...) method is called every time a change in the height is detected
            @Override
            public void changed(ObservableValue<? extends Number> value, Number number, Number t1) {
                double tentativeFont = font * Math.sqrt(pane.getHeight()/ label.getHeight());
                if (tentativeFont < font*(100-error)/100 || tentativeFont > font*(100+error)/100) {
                    font = tentativeFont;
                    label.setStyle("-fx-font-size: " + font);
                }
            }
        });
    }
}
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<Pane fx:id="pane" prefHeight="275" prefWidth="800" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/11.0.1" fx:controller="sample.Controller">
    <HBox>
        <Label fx:id="label" text="${input.text}" wrapText="true" prefWidth="400" />
        <TextField text="enter stuff" fx:id="input"/>
    </HBox>
</Pane>

在测试时,我发现错误可能需要调整。当文本很少时,大错误效果很好,而文本很多时小错误。您可能也想对其进行编程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多