Acordeón JavaFX con múltiples paneles abiertos
accordion (2)
No, un Accordion JavaFX 2.2 solo puede tener un panel abierto a la vez.
Creé una solicitud de mejora ( control JDK-8090554 StackedTitledPanes ) para una función que le permite abrir más de un panel en el acordeón a la vez, sin embargo, la solicitud de función no se ha implementado actualmente.
Mientras tanto, usted mismo puede construir un control similar fácilmente creando múltiples instancias de TitledPane y ubicándolas en un VBox .
private VBox createStackedTitledPanes() {
final VBox stackedTitledPanes = new VBox();
stackedTitledPanes.getChildren().setAll(
new TitledPane("Pane 1", contentNode1),
new TitledPane("Pane 2", contentNode2),
new TitledPane("Pane 3", contentNode3)
);
((TitledPane) stackedTitledPanes.getChildren().get(0)).setExpanded(true);
return stackedTitledPanes;
}
Si es necesario, puede envolver el VBox
contiene sus paneles en un ScrollPane , de modo que el contenido de todos sus paneles expandidos se pueda usar si su área supera el área disponible.
Creé una solución de muestra (los iconos son linkware de: http://www.fasticon.com ).
¿Es posible tener un acordeón con más de 1 panel abierto en JavaFX?
Tenía requisitos ligeramente diferentes
- El acordeón o bien expande o administra el espacio de vista para las vistas incrustadas
- La vista completa se puede poner en una vista de desplazamiento
- Cada cuadro se expande completamente al tamaño de toda la vista, si el acordeón es de tamaño fijo, o se expande al tamaño del contenido, si no es una vista fija.
Aunque en mi caso, no pude cumplir todos los 3. y la prueba 2., pude encontrar la siguiente solución:
1) Use un ScrollPane, con un VBox dentro, con TitledWindows dentro. 2) Asegúrese de que sus TitledPanes estén configurados en VBox.grow = "ALGUNAS VECES" . 3) Agregue un VBox como el último elemento y configure VBox.vgrow = "SIEMPRE" - esto empuja los TitledPanes hasta su tamaño mínimo. Todos los demás han proporcionado ejemplos de Código, si desea usar fxml, o no quiere usar Java, solo usar los elementos funciona igualmente bien (generado con SceneBuilder):
<ScrollPane fitToHeight="true" fitToWidth="true" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
<content>
<VBox fx:id="leftVBox" maxHeight="1.7976931348623157E308" prefHeight="200.0" prefWidth="100.0">
<children>
<TitledPane fx:id="titledPanelOne" animated="false" expanded="false" style="-fx-background-color: red;" text="Pane One" VBox.vgrow="SOMETIMES">
<content>
<ListView fx:id="listViewOne" maxHeight="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" />
</content>
</TitledPane>
<TitledPane fx:id="titledPanelTwo" animated="false" expanded="false" style="-fx-background-color: green;" text="Pane Two" VBox.vgrow="SOMETIMES">
<content>
<ListView fx:id="listViewTwo" maxHeight="1.7976931348623157E308" prefHeight="200.0" prefWidth="200.0" />
</content>
</TitledPane>
<VBox prefHeight="0.0" prefWidth="0.0" VBox.vgrow="ALWAYS" />
</children>
</VBox>
</content>
</ScrollPane>
4) Aunque esto hace que las cajas apiladas se expandan / contraigan independientemente una de otra, esto no soluciona el problema en el que las cajas no se ajustan correctamente a su contenido (si, por ejemplo, tiene una Vista de lista incrustada como en la del ejemplo anterior), por lo que ahora tiene que desplazarse bastante cuando haya suficiente espacio en la pantalla. ¿La solución? Se requiere un poco de Java.
Para implementar esta solución, primero vincularemos maxHeightProperty()
de TitledPane a heightProperty()
VBox externo:
public class Controller implements Initializable {
//... controller code
@Override
public void initialize(URL location, ResourceBundle resources) {
//...
variablesViewPane.maxHeightProperty().bind(leftVBox.heightProperty());
historyViewPane.maxHeightProperty().bind(leftVBox.heightProperty());
}
}
Nos prefHeighProperty()
la prefHeighProperty()
expandedProperty()
cada panel, y prefHeighProperty()
y desenlazamos dinámicamente la prefHeighProperty()
:
private static void bindExpanded(TitledPane pane, ReadOnlyDoubleProperty prop) {
pane.expandedProperty().addListener((observable, oldValue, newValue) -> {
if(newValue) {
pane.prefHeightProperty().bind(prop);
} else {
pane.prefHeightProperty().unbind();
pane.prefHeightProperty().set(0);
}
});
}
Si nos muestran, pedimos ser tan grandes como el VBox, si no nos muestran, pedimos que sea lo más pequeño posible. El beneficio de hacer las cosas de esta manera es que el diseño luego calcula automáticamente la altura disponible en función del número de Titanes de Titulos que se muestran actualmente, lo que lleva exactamente al comportamiento que queremos.
Entro en más detalle aquí: