我有一个包含
VBox
的 MFXToggleButtons
。我想折叠并展开VBox
中的这个height
,使其完全消失。这样就创建了一个设置窗口,当该窗口展开时,可以移动表单上的其他对象。
但是,当您尝试在 height
中指定任何 VBox
时,没有任何变化。据我了解,这是因为VBox
内的物体不允许它减少。
我的
VBox
<VBox>
<MFXToggleButton selected="true" text="Installed" >
<VBox.margin>
<Insets top="20" bottom="5" left="10" />
</VBox.margin>
</MFXToggleButton>
<MFXToggleButton selected="true" text="Releases">
<VBox.margin>
<Insets top="10" bottom="5" left="10" />
</VBox.margin>
</MFXToggleButton>
<MFXToggleButton selected="true" text="Modified">
<VBox.margin>
<Insets top="10" bottom="5" left="10" />
</VBox.margin>
</MFXToggleButton>
<MFXToggleButton selected="false" text="Snapshots">
<VBox.margin>
<Insets top="10" bottom="5" left="10" />
</VBox.margin>
</MFXToggleButton>
<MFXToggleButton selected="false" text="Olds">
<VBox.margin>
<Insets top="10" bottom="20" left="10" />
</VBox.margin>
</MFXToggleButton>
</VBox>
我已经尝试过使用其他容器并降低
MFXToggleButton
本身的高度。但它没有给我任何结果。
TitledPane
实现。通常,当内置功能满足您的需要时,您应该使用它,而不是尝试自己实现它。
如果您想编写自己的动画来折叠窗格,您可以为
maxHeightProperty()
的值设置动画。要折叠它,您应该将最大高度从当前高度设置为零。要再次展开它,请使用 prefHeight(width)
计算首选高度,并将最大高度从零动画化到首选高度。在“展开”动画结束时,您可能希望将最大高度设置为 Region.USE_PREF_HEIGHT
,以便在内容发生变化时它可以继续遵循其首选高度。
请注意,如果子节点溢出分配给它们的边界,则并非所有容器都会剪辑子节点的内容。因此,您可能需要显式提供一个剪辑并将其绑定到内容的边界。
这是一个简单的例子:
hello-view.fxml
:
<?xml version="1.0" encoding="UTF-8"?>
<?import io.github.palexdev.materialfx.controls.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.shape.Rectangle?>
<VBox spacing="20.0" xmlns:fx="http://javafx.com/fxml"
fx:controller="com.example.demo.HelloController">
<padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
</padding>
<Button text="Expand/Collapse" onAction="#expand"/>
<VBox fx:id="expandContent" minHeight="0">
<clip><Rectangle fx:id="expandClip"/></clip>
<MFXToggleButton selected="true" text="Installed" >
<VBox.margin>
<Insets top="20" bottom="5" left="10" />
</VBox.margin>
</MFXToggleButton>
<MFXToggleButton selected="true" text="Releases">
<VBox.margin>
<Insets top="10" bottom="5" left="10" />
</VBox.margin>
</MFXToggleButton>
<MFXToggleButton selected="true" text="Modified">
<VBox.margin>
<Insets top="10" bottom="5" left="10" />
</VBox.margin>
</MFXToggleButton>
<MFXToggleButton selected="false" text="Snapshots">
<VBox.margin>
<Insets top="10" bottom="5" left="10" />
</VBox.margin>
</MFXToggleButton>
<MFXToggleButton selected="false" text="Olds">
<VBox.margin>
<Insets top="10" bottom="20" left="10" />
</VBox.margin>
</MFXToggleButton>
</VBox>
<Label fx:id="welcomeText"/>
<Button text="Hello!" onAction="#onHelloButtonClick"/>
</VBox>
HelloController.java
:
package com.example.demo;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
public class HelloController {
@FXML
private Label welcomeText;
@FXML
private VBox expandContent;
private boolean expanded = true;
@FXML
private Rectangle expandClip;
@FXML
private void initialize() {
expandClip.widthProperty().bind(expandContent.widthProperty());
expandClip.heightProperty().bind(expandContent.heightProperty());
}
@FXML
protected void onHelloButtonClick() {
welcomeText.setText("Welcome to JavaFX Application!");
}
@FXML
private void expand() {
if (expanded) {
// animate collapse:
double currentHeight = expandContent.getHeight();
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(expandContent.maxHeightProperty(), currentHeight)),
new KeyFrame(Duration.seconds(0.5), new KeyValue(expandContent.maxHeightProperty(), 0))
);
timeline.setOnFinished(e -> {
expanded = false;
});
timeline.play();
} else {
// animate expand:
// compute the preferred height of the content:
double prefHeight = expandContent.prefHeight(expandContent.getWidth());
// animate the max height from zero to the pref height:
Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new KeyValue(expandContent.maxHeightProperty(), 0)),
new KeyFrame(Duration.seconds(0.5), new KeyValue(expandContent.maxHeightProperty(), prefHeight))
);
// when done, set the flag, and set the max height to the sentinel value
// this latter part is necessary to allow the content to continue to respect
// the pref height if the scene graph changes, etc.
timeline.setOnFinished(e -> {
expanded = true;
expandContent.setMaxHeight(Region.USE_PREF_SIZE);
});
timeline.play();
}
}
}
HelloApplication.java
:
package com.example.demo;
import io.github.palexdev.materialfx.css.themes.MFXThemeManager;
import io.github.palexdev.materialfx.css.themes.Themes;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class HelloApplication extends Application {
@Override
public void start(Stage stage) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));
Scene scene = new Scene(fxmlLoader.load());
MFXThemeManager.addOn(scene, Themes.DEFAULT, Themes.LEGACY);
stage.setTitle("Hello!");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
扩展:
崩溃了: