将组件添加到附加的 AnchorPane 时,JavaFX Scene Builder 在运行时扩展 ScrollPane 区域
JavaFX Scene Builder Expand ScrollPane area at runtime when adding components to attached AnchorPane
我没能找到这方面的信息,但我在 Scene Builder 中创建了一个布局,我在一个空的 ScrollPane 中放置了一个 AnchorPane,并添加了文本、一个滑块和一个标签在行中,然后添加一个按钮供用户在上面添加一个新条目。
基本上是典型的偏好启发 UI,用户还可以在其中添加新条目并指定他们自己的偏好值。
按下时,出于测试目的,按钮会创建一个新标签,将其添加到 AnchorPane,并将其重新定位到 AnchorPane 外部的 Y 位置,然后调整 AnchorPane 的大小以包含新标签。
我遇到的问题是 ScrollPane 不会调整和扩展可滚动区域以适应新的 AnchorPane 高度,因此我无法向下滚动到新标签可见的位置。另一方面,在 Scene Builder 中,如果我调整 AnchorPane 的大小使其大于 ScrollPane,后者会动态调整可滚动区域,所以我不确定问题出在哪里。
感谢任何帮助。
编辑:
根据要求,下面是该项目的最低限度可复制版本。
Class 加载 FXML 并创建场景
package main;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.TitledPane;
import javafx.stage.Stage;
public class Registration_Page extends Application {
private Stage primaryStage;
private TitledPane mainLayout;
@Override
public void start(Stage primaryStage) throws IOException {
this.primaryStage = primaryStage;
showMainView();
}
private void showMainView() throws IOException {
FXMLLoader loader = new FXMLLoader(Registration_Page.class.getResource("resources/Registration_Page.fxml"));
mainLayout = loader.load();
Scene scene = new Scene(mainLayout);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Class 作为按钮控制器,使用 FXML 定义的组件。
package main;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.AnchorPane;
public class ButtonController {
@FXML
private Button plus;
@FXML
private AnchorPane prefValuesAnchorPane;
@FXML
private ScrollPane scrollPane;
@FXML
protected void plusAction(ActionEvent event) {
Label lbl1 = new Label("Hello");
prefValuesAnchorPane.getChildren().add(lbl1);
lbl1.relocate(18, 250);
System.out.println(prefValuesAnchorPane.getHeight());
System.out.println(lbl1.getLayoutY());
if (lbl1.getLayoutY() >= prefValuesAnchorPane.getHeight())
{
prefValuesAnchorPane.resize(prefValuesAnchorPane.getWidth(), lbl1.getLayoutY() + 3);
}
}
}
FXML 文档
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<TitledPane animated="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" text="User Registration" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.ButtonController">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TextField layoutX="52.0" layoutY="79.0" />
<Text layoutX="14.0" layoutY="96.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Name" />
<Text layoutX="14.0" layoutY="130.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Preference Values">
<font>
<Font size="14.0" />
</font>
</Text>
<ScrollPane fx:id="scrollPane" layoutX="14.0" layoutY="137.0" prefHeight="223.0" prefWidth="332.0">
<content>
<AnchorPane fx:id="prefValuesAnchorPane" minHeight="0.0" minWidth="0.0" prefHeight="217.0" prefWidth="329.0">
<children>
<Text layoutX="15.0" layoutY="30.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val1:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="15.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToPixel="false" snapToTicks="true" />
<Label layoutX="280.0" layoutY="12.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Text layoutX="15.0" layoutY="62.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val2:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="50.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToTicks="true" />
<Label layoutX="280.0" layoutY="48.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Text layoutX="15.0" layoutY="97.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val3:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="85.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToTicks="true" />
<Label layoutX="280.0" layoutY="82.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Text layoutX="15.0" layoutY="133.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val4:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="120.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToTicks="true" />
<Label layoutX="280.0" layoutY="118.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Button fx:id="plus" graphicTextGap="1.0" layoutX="289.0" layoutY="153.0" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#plusAction" prefHeight="0.0" prefWidth="30.0" text="+" textAlignment="CENTER" textOverrun="CENTER_ELLIPSIS" AnchorPane.topAnchor="153.0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Button>
</children>
</AnchorPane>
</content>
</ScrollPane>
<Button layoutX="532.0" layoutY="335.0" mnemonicParsing="false" text="Next" />
</children></AnchorPane>
</content>
</TitledPane>
对此的解决方案是改为使用包含 AnchorPane 的 ScrollPane(原样),并为添加的每个条目创建一个 AnchorPane 或 BorderPane 或任何其他容器窗格 (afaik),并向其中添加任何内容,而不是将按钮或标签等组件直接添加到附加到 SP 的原始 AP。
我没能找到这方面的信息,但我在 Scene Builder 中创建了一个布局,我在一个空的 ScrollPane 中放置了一个 AnchorPane,并添加了文本、一个滑块和一个标签在行中,然后添加一个按钮供用户在上面添加一个新条目。
基本上是典型的偏好启发 UI,用户还可以在其中添加新条目并指定他们自己的偏好值。
按下时,出于测试目的,按钮会创建一个新标签,将其添加到 AnchorPane,并将其重新定位到 AnchorPane 外部的 Y 位置,然后调整 AnchorPane 的大小以包含新标签。 我遇到的问题是 ScrollPane 不会调整和扩展可滚动区域以适应新的 AnchorPane 高度,因此我无法向下滚动到新标签可见的位置。另一方面,在 Scene Builder 中,如果我调整 AnchorPane 的大小使其大于 ScrollPane,后者会动态调整可滚动区域,所以我不确定问题出在哪里。
感谢任何帮助。
编辑: 根据要求,下面是该项目的最低限度可复制版本。
Class 加载 FXML 并创建场景
package main;
import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.TitledPane;
import javafx.stage.Stage;
public class Registration_Page extends Application {
private Stage primaryStage;
private TitledPane mainLayout;
@Override
public void start(Stage primaryStage) throws IOException {
this.primaryStage = primaryStage;
showMainView();
}
private void showMainView() throws IOException {
FXMLLoader loader = new FXMLLoader(Registration_Page.class.getResource("resources/Registration_Page.fxml"));
mainLayout = loader.load();
Scene scene = new Scene(mainLayout);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Class 作为按钮控制器,使用 FXML 定义的组件。
package main;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ScrollPane;
import javafx.scene.layout.AnchorPane;
public class ButtonController {
@FXML
private Button plus;
@FXML
private AnchorPane prefValuesAnchorPane;
@FXML
private ScrollPane scrollPane;
@FXML
protected void plusAction(ActionEvent event) {
Label lbl1 = new Label("Hello");
prefValuesAnchorPane.getChildren().add(lbl1);
lbl1.relocate(18, 250);
System.out.println(prefValuesAnchorPane.getHeight());
System.out.println(lbl1.getLayoutY());
if (lbl1.getLayoutY() >= prefValuesAnchorPane.getHeight())
{
prefValuesAnchorPane.resize(prefValuesAnchorPane.getWidth(), lbl1.getLayoutY() + 3);
}
}
}
FXML 文档
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.text.Text?>
<TitledPane animated="false" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" text="User Registration" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.ButtonController">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<TextField layoutX="52.0" layoutY="79.0" />
<Text layoutX="14.0" layoutY="96.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Name" />
<Text layoutX="14.0" layoutY="130.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Preference Values">
<font>
<Font size="14.0" />
</font>
</Text>
<ScrollPane fx:id="scrollPane" layoutX="14.0" layoutY="137.0" prefHeight="223.0" prefWidth="332.0">
<content>
<AnchorPane fx:id="prefValuesAnchorPane" minHeight="0.0" minWidth="0.0" prefHeight="217.0" prefWidth="329.0">
<children>
<Text layoutX="15.0" layoutY="30.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val1:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="15.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToPixel="false" snapToTicks="true" />
<Label layoutX="280.0" layoutY="12.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Text layoutX="15.0" layoutY="62.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val2:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="50.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToTicks="true" />
<Label layoutX="280.0" layoutY="48.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Text layoutX="15.0" layoutY="97.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val3:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="85.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToTicks="true" />
<Label layoutX="280.0" layoutY="82.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Text layoutX="15.0" layoutY="133.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Val4:" />
<Slider blockIncrement="1.0" layoutX="115.0" layoutY="120.0" majorTickUnit="1.0" max="10.0" minorTickCount="0" prefWidth="140.0" showTickLabels="true" snapToTicks="true" />
<Label layoutX="280.0" layoutY="118.0" text="0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Label>
<Button fx:id="plus" graphicTextGap="1.0" layoutX="289.0" layoutY="153.0" maxHeight="-Infinity" maxWidth="-Infinity" mnemonicParsing="false" onAction="#plusAction" prefHeight="0.0" prefWidth="30.0" text="+" textAlignment="CENTER" textOverrun="CENTER_ELLIPSIS" AnchorPane.topAnchor="153.0">
<font>
<Font name="System Bold" size="14.0" />
</font>
</Button>
</children>
</AnchorPane>
</content>
</ScrollPane>
<Button layoutX="532.0" layoutY="335.0" mnemonicParsing="false" text="Next" />
</children></AnchorPane>
</content>
</TitledPane>
对此的解决方案是改为使用包含 AnchorPane 的 ScrollPane(原样),并为添加的每个条目创建一个 AnchorPane 或 BorderPane 或任何其他容器窗格 (afaik),并向其中添加任何内容,而不是将按钮或标签等组件直接添加到附加到 SP 的原始 AP。