放大或缩小文本以适合标签容器 JavaFX
Scale up or down text to fit label container JavaFX
基本上我想要实现的是希望字体大小自动调整。我有一个 window 是 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>
演示文稿Controller.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
我的回答背后的基本思想是,比较 Label
及其容器的 width
和 height
属性反映了显示的文本量(以及显示的文本量)已隐藏)。
当标签的字体加倍时,Label
的 width
和 height
加倍。
如果文本完美环绕且每行末尾没有多余空格,则标签的面积会增加四倍。我假设布局节点保持不变,标签的宽度也保持不变。任何额外的文本都会导致高度增加(并且文本会超出布局节点的边界并超出视图)。
目标是保持 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>
在测试时,我发现错误可能需要调整。当文本很少时,大错误效果很好,而文本很多时,小错误效果很好。你可能也想编程。
基本上我想要实现的是希望字体大小自动调整。我有一个 window 是 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>
演示文稿Controller.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
我的回答背后的基本思想是,比较 Label
及其容器的 width
和 height
属性反映了显示的文本量(以及显示的文本量)已隐藏)。
当标签的字体加倍时,Label
的 width
和 height
加倍。
如果文本完美环绕且每行末尾没有多余空格,则标签的面积会增加四倍。我假设布局节点保持不变,标签的宽度也保持不变。任何额外的文本都会导致高度增加(并且文本会超出布局节点的边界并超出视图)。
目标是保持 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>
在测试时,我发现错误可能需要调整。当文本很少时,大错误效果很好,而文本很多时,小错误效果很好。你可能也想编程。