JavaFX文本框窗口调整时被裁剪的问题解决求助
计时器应用TextField布局裁剪问题解决方案
我正在开发一款计时器应用,使用JavaFX实现,但调整窗口大小时,TextField会出现被裁剪的情况(截图显示文本框底部被窗口边缘截断)。虽后续版本会将文本框替换为菜单按钮,但仍希望尽早解决该布局问题。
以下是我的JavaFX代码:
package com.jammin.timetimer; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.geometry.Insets; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.TextField; import javafx.scene.control.TextFormatter; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.StackPane; import javafx.scene.layout.VBox; import javafx.scene.paint.Color; import javafx.scene.shape.Arc; import javafx.scene.shape.ArcType; import javafx.stage.Stage; import javafx.util.converter.IntegerStringConverter; public class HelloApplication extends Application { @Override public void start(Stage PrimaryStage) { //Adds all the necessary elements into the window StackPane myStackPane = new StackPane(); VBox myVBox = new VBox(myStackPane); myVBox.setAlignment(Pos.BOTTOM_CENTER); // 添加内边距,避免元素贴边被裁剪 myVBox.setPadding(new Insets(10)); // 设置StackPane占满VBox剩余空间 VBox.setVgrow(myStackPane, Priority.ALWAYS); HBox myHBox = new HBox(myVBox); myHBox.setAlignment(Pos.CENTER); // 允许VBox在HBox中填充高度 HBox.setFillHeight(myVBox, true); Scene myScene = new Scene(myHBox, 400,400); ImageView myImageView = new ImageView(new Image("file:src/main/resources/img/timer_ticks.png")); myImageView.fitHeightProperty().bind(myScene.heightProperty()); myImageView.fitWidthProperty().bind(myScene.widthProperty()); myImageView.setPreserveRatio(true); myStackPane.getChildren().addAll(myImageView); Arc myArc = createArc(myStackPane, myScene); TextField myTextField = createTextField(myArc, myScene); myVBox.getChildren().add(myTextField); PrimaryStage.setScene(myScene); PrimaryStage.show(); } //Constructor for my Arc public Arc createArc(StackPane myStackPane, Scene myScene){ Arc myArc = new Arc(100,100,100,100,0,360); myArc.setFill(Color.GREEN); myArc.setType(ArcType.ROUND); myStackPane.getChildren().add(myArc); myScene.widthProperty().addListener(new ChangeListener<Number>() { @Override public void changed(ObservableValue<? extends Number> observableValue, Number number, Number t1) { if (t1.doubleValue() <= myScene.getHeight()*1.05){ myArc.setRadiusX(t1.doubleValue()/2.9); myArc.setRadiusY(t1.doubleValue()/2.9); } } }); myScene.heightProperty().addListener(new ChangeListener<Number>() { @Override public void changed(ObservableValue<? extends Number> observableValue, Number number, Number t1) { if (t1.doubleValue() <= myScene.getWidth()){ myArc.setRadiusX(t1.doubleValue()/2.9); myArc.setRadiusY(t1.doubleValue()/2.9); } } }); return myArc; } //Textfield to enter the time public TextField createTextField(Arc myArc, Scene myScene){ TextField myTextField = new TextField("Enter Time 1-60"); // 绑定最小高度到窗口高度的10%,随窗口调整自动变化 myTextField.minHeightProperty().bind(myScene.heightProperty().multiply(0.1)); // 设置首选高度,保证显示完整 myTextField.setPrefHeight(40); TextFormatter<Integer> myTextFormatter = new TextFormatter<>(new IntegerStringConverter(), 60, this::filter); myTextField.setTextFormatter(myTextFormatter); // myTextField.setOnAction((evt) -> myArc.setLength(myTextFormatter.getValue()!=null ? 6*myTextFormatter.getValue():0)); return myTextField; } //Filter to only allow for use of time between 1-60minutes public TextFormatter.Change filter(TextFormatter.Change myChange){ if (myChange.getControlNewText().isEmpty()){ return myChange; } int myVal = Integer.parseInt(myChange.getControlNewText()); return myVal >=0 && myVal <= 60 ? myChange : null; } }
核心修复说明:
- 添加内边距:给
VBox设置setPadding(new Insets(10)),避免TextField紧贴窗口边缘被截断 - 布局空间分配:通过
VBox.setVgrow(myStackPane, Priority.ALWAYS)让StackPane占满VBox的剩余垂直空间,确保TextField始终保留足够的显示区域 - 动态高度绑定:将TextField的最小高度绑定到窗口高度的10%,而非固定初始值,随窗口大小自动调整高度
- 容器填充设置:给
HBox开启setFillHeight(true),允许VBox在HBox中充分利用垂直空间,避免布局挤压
内容的提问来源于stack exchange,提问作者Jack Wanamaker
相关产品推荐
相关产品推荐

