如何在 JavaFX 中将 Pane 与另一个 Pane 绑定
How to bind Pane with another Pane in JavaFX
我正在寻找将窗格大小与外部窗格绑定的方法。
我可以将矩形的大小与窗格绑定,
但无法将内部窗格(红色虚线矩形)与外部窗格(蓝色虚线矩形)绑定
为什么我做不到
好像是Pane
没有为widthProperty
提供bind
方法
对象
- 至少,内层Pane与外层Pane的宽度
TextArea
绑定
- 我会制作很多新的标签页,因此,我更喜欢将 inner Pane 与 outer Pane 绑定而不是
TextArea
直接绑定到 outer Pane。
情况
- 蓝色和橙色矩形与窗格绑定良好
dropPane
- 但是蓝色边框面板的宽度应该与红色边框面板的宽度相同!
我的资源
main.kt
:
import javafx.application.Application
import javafx.fxml.FXMLLoader
import javafx.scene.*
import javafx.scene.control.*
import javafx.scene.paint.Paint
import javafx.scene.shape.Rectangle
import javafx.stage.Stage
import javafx.scene.layout.*
import javafx.scene.paint.*
fun main(args : Array<String>) {
println("EntryPoint")
Application.launch(PaneBindingTest().javaClass, *args)
}
class PaneBindingTest : Application() {
private var tabCount = 0
private fun generateNewTab (): Tab {
val tab = Tab()
tabCount += 1
tab.text = "Tab$tabCount"
val fxml = javaClass.getResource("fxml/Tab.fxml")
val aTabPane: Pane = FXMLLoader.load(fxml)
aTabPane.border = Border(BorderStroke(Paint.valueOf("Red"),BorderStrokeStyle.DASHED, CornerRadii.EMPTY, BorderWidths.DEFAULT))
tab.content = aTabPane
return tab
}
override fun start(primaryStage: Stage) {
primaryStage.title = "EntryPoint"
primaryStage.isAlwaysOnTop = true
val fxml = javaClass.getResource("fxml/EntryPoint.fxml")
val root: Parent = FXMLLoader.load(fxml)
val scene = Scene(root)
val epPane= root.lookup("#EPPane") as AnchorPane // Entry Point Pane
val dropPane= root.lookup("#DropPane") as AnchorPane // Drop Pane
val tabPane= root.lookup("#TabPane") as TabPane // Tab Pane
val singleDropPoint= root.lookup("#ForSingle") as Rectangle // Single-ArchiveSet drop point
val multiDropPoint = root.lookup("#ForMulti") as Rectangle // Multi-ArchiveSet drop point
//epPane.background = Background(BackgroundFill(Paint.valueOf("Yellow"), CornerRadii(0.0), Insets(0.0,0.0,0.0,0.0)))
//dropPane.background = Background(BackgroundFill(Paint.valueOf("Green"), CornerRadii(0.0), Insets(0.0,0.0,0.0,0.0)))
tabPane.tabClosingPolicy = TabPane.TabClosingPolicy.ALL_TABS // or SELECTED_TAB, UNAVAILABLE
tabPane.border = Border(BorderStroke(Paint.valueOf("Blue"),BorderStrokeStyle.DASHED, CornerRadii.EMPTY, BorderWidths.DEFAULT))
singleDropPoint.heightProperty().bind(epPane.heightProperty().divide(32).multiply(23))
multiDropPoint.yProperty().bind(singleDropPoint.yProperty().add(dropPane.heightProperty().divide(4).multiply(3)))
multiDropPoint.heightProperty().bind(epPane.heightProperty().divide(4))
primaryStage.scene = scene
primaryStage.show()
val newTab = generateNewTab()
tabPane.tabs.add(newTab)
tabPane.selectionModel.select(newTab)
}
}
fxml/EntryPoint.fxml
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Rectangle?>
<AnchorPane fx:id="EPPane" prefHeight="640.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TabPane fx:id="TabPane" prefHeight="640.0" prefWidth="1152.0" tabClosingPolicy="ALL_TABS" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="128.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
</TabPane>
<AnchorPane fx:id="DropPane" layoutY="128.0" maxWidth="128.0" minWidth="128.0" prefWidth="128.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Rectangle fx:id="ForSingle" arcHeight="16.0" arcWidth="16.0" fill="DODGERBLUE" height="360.0" width="120.0" stroke="#1100ff" strokeType="INSIDE" strokeWidth="8.0" AnchorPane.leftAnchor="4.0" AnchorPane.rightAnchor="4.0" AnchorPane.topAnchor="4.0"/>
<Rectangle fx:id="ForMulti" arcHeight="16.0" arcWidth="16.0" fill="#ff9d1f" height="240.0" width="120.0" stroke="#ff8800" strokeType="INSIDE" strokeWidth="8.0" AnchorPane.leftAnchor="4.0" AnchorPane.rightAnchor="4.0" AnchorPane.bottomAnchor="4.0"/>
</children>
</AnchorPane>
</children>
</AnchorPane>
fxml/Tab.fxml
:
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="480.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextArea fx:id="FilePaths" layoutX="4.0" layoutY="80.0" prefHeight="128.0" AnchorPane.leftAnchor="4.0" AnchorPane.rightAnchor="4.0" AnchorPane.topAnchor="72.0" />
<RadioButton layoutX="14.0" layoutY="206.0" mnemonicParsing="false" selected="true" text="Hash/Size only">
<toggleGroup>
<ToggleGroup fx:id="AnalyzeMethod" />
</toggleGroup>
</RadioButton>
<RadioButton layoutX="120.0" layoutY="206.0" mnemonicParsing="false" text="FileName" toggleGroup="$AnalyzeMethod" />
<RadioButton layoutX="200.0" layoutY="206.0" mnemonicParsing="false" text="Directory Structure" toggleGroup="$AnalyzeMethod" />
<CheckBox fx:id="CheckDiff" layoutX="336.0" layoutY="206.0" mnemonicParsing="false" text="Show Diff" />
<CheckBox fx:id="CheckSame" layoutX="420.0" layoutY="206.0" mnemonicParsing="false" text="Show Same" />
<ComboBox fx:id="ComboBox" layoutX="840.0" layoutY="202.0" prefWidth="150.0" />
<HBox fx:id="LabelBox" layoutX="12.0" layoutY="14.0" prefHeight="64.0" prefWidth="978.0" AnchorPane.leftAnchor="4.0" AnchorPane.rightAnchor="4.0" AnchorPane.topAnchor="4.0" />
</children>
</AnchorPane>
我发现几乎 same question,但没有答案。
您不需要绑定即可实现此目的。问题是您将 maxHeight
/maxWidth
的约束设置为 USE_PREF_SIZE
,即设置为在调整 window 大小时可以很好地达到的固定值。删除这些约束以允许 AnchorPane
根据需要增长:
Tab.fxml
<AnchorPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="480.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
...
</AnchorPane>
此外,如果可以避免,我建议避免使用 AnchorPane
s。这种布局很难实现响应式布局。 VBox
和 HBox
在这种情况下会做得更好。
示例:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.Region?>
<VBox prefHeight="480.0"
prefWidth="1000.0" xmlns="http://javafx.com/javafx/10.0.1"
xmlns:fx="http://javafx.com/fxml/1">
<padding>
<Insets topRightBottomLeft="4" />
</padding>
<children>
<HBox fx:id="LabelBox" prefHeight="64.0" prefWidth="978.0" />
<TextArea VBox.vgrow="ALWAYS" fx:id="FilePaths"
prefHeight="128.0">
</TextArea>
<HBox spacing="10" minWidth="-Infinity">
<VBox.margin>
<Insets top="5" left="0" right="0" bottom="0" />
</VBox.margin>
<children>
<RadioButton mnemonicParsing="false" selected="true"
text="Hash/Size only">
<toggleGroup>
<ToggleGroup fx:id="AnalyzeMethod" />
</toggleGroup>
</RadioButton>
<RadioButton mnemonicParsing="false" text="FileName"
toggleGroup="$AnalyzeMethod" />
<RadioButton mnemonicParsing="false"
text="Directory Structure" toggleGroup="$AnalyzeMethod" />
<CheckBox fx:id="CheckDiff" mnemonicParsing="false"
text="Show Diff" />
<CheckBox fx:id="CheckSame" mnemonicParsing="false"
text="Show Same" />
<Region HBox.hgrow="ALWAYS" /> <!-- placeholder to grow/shrink -->
<ComboBox fx:id="ComboBox" prefWidth="150.0" />
</children>
</HBox>
</children>
</VBox>
我正在寻找将窗格大小与外部窗格绑定的方法。
我可以将矩形的大小与窗格绑定, 但无法将内部窗格(红色虚线矩形)与外部窗格(蓝色虚线矩形)绑定
为什么我做不到
好像是Pane
没有为widthProperty
bind
方法
对象
- 至少,内层Pane与外层Pane的宽度
TextArea
绑定 - 我会制作很多新的标签页,因此,我更喜欢将 inner Pane 与 outer Pane 绑定而不是
TextArea
直接绑定到 outer Pane。
情况
- 蓝色和橙色矩形与窗格绑定良好
dropPane
- 但是蓝色边框面板的宽度应该与红色边框面板的宽度相同!
我的资源
main.kt
:
import javafx.application.Application
import javafx.fxml.FXMLLoader
import javafx.scene.*
import javafx.scene.control.*
import javafx.scene.paint.Paint
import javafx.scene.shape.Rectangle
import javafx.stage.Stage
import javafx.scene.layout.*
import javafx.scene.paint.*
fun main(args : Array<String>) {
println("EntryPoint")
Application.launch(PaneBindingTest().javaClass, *args)
}
class PaneBindingTest : Application() {
private var tabCount = 0
private fun generateNewTab (): Tab {
val tab = Tab()
tabCount += 1
tab.text = "Tab$tabCount"
val fxml = javaClass.getResource("fxml/Tab.fxml")
val aTabPane: Pane = FXMLLoader.load(fxml)
aTabPane.border = Border(BorderStroke(Paint.valueOf("Red"),BorderStrokeStyle.DASHED, CornerRadii.EMPTY, BorderWidths.DEFAULT))
tab.content = aTabPane
return tab
}
override fun start(primaryStage: Stage) {
primaryStage.title = "EntryPoint"
primaryStage.isAlwaysOnTop = true
val fxml = javaClass.getResource("fxml/EntryPoint.fxml")
val root: Parent = FXMLLoader.load(fxml)
val scene = Scene(root)
val epPane= root.lookup("#EPPane") as AnchorPane // Entry Point Pane
val dropPane= root.lookup("#DropPane") as AnchorPane // Drop Pane
val tabPane= root.lookup("#TabPane") as TabPane // Tab Pane
val singleDropPoint= root.lookup("#ForSingle") as Rectangle // Single-ArchiveSet drop point
val multiDropPoint = root.lookup("#ForMulti") as Rectangle // Multi-ArchiveSet drop point
//epPane.background = Background(BackgroundFill(Paint.valueOf("Yellow"), CornerRadii(0.0), Insets(0.0,0.0,0.0,0.0)))
//dropPane.background = Background(BackgroundFill(Paint.valueOf("Green"), CornerRadii(0.0), Insets(0.0,0.0,0.0,0.0)))
tabPane.tabClosingPolicy = TabPane.TabClosingPolicy.ALL_TABS // or SELECTED_TAB, UNAVAILABLE
tabPane.border = Border(BorderStroke(Paint.valueOf("Blue"),BorderStrokeStyle.DASHED, CornerRadii.EMPTY, BorderWidths.DEFAULT))
singleDropPoint.heightProperty().bind(epPane.heightProperty().divide(32).multiply(23))
multiDropPoint.yProperty().bind(singleDropPoint.yProperty().add(dropPane.heightProperty().divide(4).multiply(3)))
multiDropPoint.heightProperty().bind(epPane.heightProperty().divide(4))
primaryStage.scene = scene
primaryStage.show()
val newTab = generateNewTab()
tabPane.tabs.add(newTab)
tabPane.selectionModel.select(newTab)
}
}
fxml/EntryPoint.fxml
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.shape.Rectangle?>
<AnchorPane fx:id="EPPane" prefHeight="640.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TabPane fx:id="TabPane" prefHeight="640.0" prefWidth="1152.0" tabClosingPolicy="ALL_TABS" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="128.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
</TabPane>
<AnchorPane fx:id="DropPane" layoutY="128.0" maxWidth="128.0" minWidth="128.0" prefWidth="128.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
<children>
<Rectangle fx:id="ForSingle" arcHeight="16.0" arcWidth="16.0" fill="DODGERBLUE" height="360.0" width="120.0" stroke="#1100ff" strokeType="INSIDE" strokeWidth="8.0" AnchorPane.leftAnchor="4.0" AnchorPane.rightAnchor="4.0" AnchorPane.topAnchor="4.0"/>
<Rectangle fx:id="ForMulti" arcHeight="16.0" arcWidth="16.0" fill="#ff9d1f" height="240.0" width="120.0" stroke="#ff8800" strokeType="INSIDE" strokeWidth="8.0" AnchorPane.leftAnchor="4.0" AnchorPane.rightAnchor="4.0" AnchorPane.bottomAnchor="4.0"/>
</children>
</AnchorPane>
</children>
</AnchorPane>
fxml/Tab.fxml
:
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="480.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TextArea fx:id="FilePaths" layoutX="4.0" layoutY="80.0" prefHeight="128.0" AnchorPane.leftAnchor="4.0" AnchorPane.rightAnchor="4.0" AnchorPane.topAnchor="72.0" />
<RadioButton layoutX="14.0" layoutY="206.0" mnemonicParsing="false" selected="true" text="Hash/Size only">
<toggleGroup>
<ToggleGroup fx:id="AnalyzeMethod" />
</toggleGroup>
</RadioButton>
<RadioButton layoutX="120.0" layoutY="206.0" mnemonicParsing="false" text="FileName" toggleGroup="$AnalyzeMethod" />
<RadioButton layoutX="200.0" layoutY="206.0" mnemonicParsing="false" text="Directory Structure" toggleGroup="$AnalyzeMethod" />
<CheckBox fx:id="CheckDiff" layoutX="336.0" layoutY="206.0" mnemonicParsing="false" text="Show Diff" />
<CheckBox fx:id="CheckSame" layoutX="420.0" layoutY="206.0" mnemonicParsing="false" text="Show Same" />
<ComboBox fx:id="ComboBox" layoutX="840.0" layoutY="202.0" prefWidth="150.0" />
<HBox fx:id="LabelBox" layoutX="12.0" layoutY="14.0" prefHeight="64.0" prefWidth="978.0" AnchorPane.leftAnchor="4.0" AnchorPane.rightAnchor="4.0" AnchorPane.topAnchor="4.0" />
</children>
</AnchorPane>
我发现几乎 same question,但没有答案。
您不需要绑定即可实现此目的。问题是您将 maxHeight
/maxWidth
的约束设置为 USE_PREF_SIZE
,即设置为在调整 window 大小时可以很好地达到的固定值。删除这些约束以允许 AnchorPane
根据需要增长:
Tab.fxml
<AnchorPane minHeight="-Infinity" minWidth="-Infinity" prefHeight="480.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/10.0.1" xmlns:fx="http://javafx.com/fxml/1">
...
</AnchorPane>
此外,如果可以避免,我建议避免使用 AnchorPane
s。这种布局很难实现响应式布局。 VBox
和 HBox
在这种情况下会做得更好。
示例:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.Region?>
<VBox prefHeight="480.0"
prefWidth="1000.0" xmlns="http://javafx.com/javafx/10.0.1"
xmlns:fx="http://javafx.com/fxml/1">
<padding>
<Insets topRightBottomLeft="4" />
</padding>
<children>
<HBox fx:id="LabelBox" prefHeight="64.0" prefWidth="978.0" />
<TextArea VBox.vgrow="ALWAYS" fx:id="FilePaths"
prefHeight="128.0">
</TextArea>
<HBox spacing="10" minWidth="-Infinity">
<VBox.margin>
<Insets top="5" left="0" right="0" bottom="0" />
</VBox.margin>
<children>
<RadioButton mnemonicParsing="false" selected="true"
text="Hash/Size only">
<toggleGroup>
<ToggleGroup fx:id="AnalyzeMethod" />
</toggleGroup>
</RadioButton>
<RadioButton mnemonicParsing="false" text="FileName"
toggleGroup="$AnalyzeMethod" />
<RadioButton mnemonicParsing="false"
text="Directory Structure" toggleGroup="$AnalyzeMethod" />
<CheckBox fx:id="CheckDiff" mnemonicParsing="false"
text="Show Diff" />
<CheckBox fx:id="CheckSame" mnemonicParsing="false"
text="Show Same" />
<Region HBox.hgrow="ALWAYS" /> <!-- placeholder to grow/shrink -->
<ComboBox fx:id="ComboBox" prefWidth="150.0" />
</children>
</HBox>
</children>
</VBox>