JavaFXで複数の開いているペインを持つアコーディオンを持つことは可能ですか?
3 に答える
いいえ、JavaFX2.2アコーディオンは一度に1つのペインしか開くことができません。
アコーディオンで一度に複数のペインを開くことができる機能の拡張リクエスト(JDK-8090554 StackedTitledPanesコントロール)を作成しましたが、機能リクエストは現在実装されていません。
それまでの間、複数のTitledPaneインスタンスを作成し、それらを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;
}
必要に応じて、VBox
ペインを含むペインをScrollPaneでラップして、展開されたすべてのペインの領域が使用可能な領域を超えた場合にその領域を使用できるようにすることができます。
サンプルソリューションを作成しました(アイコンはhttp://www.fasticon.comのリンクウェアです)。
アップデート
TitledPanesのスクロール可能なスタック用に、以前は外部からリンクされていたソリューションの例を最新化してインライン化しました。
また、最新のJavaFX環境では、デフォルトのスタイルが少し異なるため(TitledPaneコンテンツの背景などでは、デフォルトでグラデーションが少なくなります)、この回答の前の画像とは少し異なって見えますが、それ以外の動作は似ています。 。
import javafx.application.Application;
import javafx.geometry.*;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class StackedPanes extends Application {
// image license: linkware - backlink to http://www.fasticon.com
private static final Image BLUE_FISH = new Image("http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Blue-Fish-icon.png");
private static final Image RED_FISH = new Image("http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Red-Fish-icon.png");
private static final Image YELLOW_FISH = new Image("http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Yellow-Fish-icon.png");
private static final Image GREEN_FISH = new Image("http://icons.iconarchive.com/icons/fasticon/fish-toys/128/Green-Fish-icon.png");
@Override
public void start(Stage stage) {
VBox stackedTitledPanes = createStackedTitledPanes();
ScrollPane scroll = new ScrollPane(stackedTitledPanes);
scroll.setFitToWidth(true);
scroll.setFitToHeight(true);
scroll.setPrefWidth(410);
scroll.setStyle("-fx-base: cadetblue;");
stage.setTitle("Fishy, fishy");
Scene scene = new Scene(scroll);
stage.setScene(scene);
stage.show();
}
private VBox createStackedTitledPanes() {
final VBox stackedTitledPanes = new VBox();
stackedTitledPanes.getChildren().setAll(
createTitledPane("One Fish", GREEN_FISH),
createTitledPane("Two Fish", YELLOW_FISH, GREEN_FISH),
createTitledPane("Red Fish", RED_FISH),
createTitledPane("Blue Fish", BLUE_FISH)
);
((TitledPane) stackedTitledPanes.getChildren().get(0)).setExpanded(true);
return stackedTitledPanes;
}
public TitledPane createTitledPane(String title, Image... images) {
FlowPane content = new FlowPane();
for (Image image : images) {
ImageView imageView = new ImageView(image);
content.getChildren().add(imageView);
FlowPane.setMargin(imageView, new Insets(10));
}
content.setAlignment(Pos.TOP_CENTER);
TitledPane pane = new TitledPane(title, content);
pane.setExpanded(false);
return pane;
}
public static void main(String[] args) {
Application.launch(args);
}
}
既存の回答の最良のものと単純化を組み合わせて、ScrollPane VBoxで複数のタイトル付きパネルを作成し、max-heightプロパティをリスナーにバインドすることでマルチオープンアコーディオンを複製できます(XMLでそれを行うということは、ペインを意味します折りたたまれてもスペースを確保します)
<ScrollPane fitToHeight="true" fitToWidth="true">
<AnchorPane id="Content">
<VBox AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<!-- Setting maxHeight="Infinity" to all makes them all grow as we want, but then they get spaces between, when collapsed (so we do it in code) -->
<TitledPane fx:id="pane1" animated="false" VBox.vgrow="ALWAYS" expanded="false" text="Pane 1">...</TitledPane>
<TitledPane fx:id="pane2" animated="false" VBox.vgrow="ALWAYS" maxHeight="Infinity" text="Pane 2 (starts expanded)">...</TitledPane>
<TitledPane fx:id="pane3" animated="false" VBox.vgrow="ALWAYS" expanded="false" text="Pane 3">...</TitledPane>
</VBox>
</AnchorPane>
</ScrollPane>
注:ペインごとにこのメソッドを呼び出す必要があります。
pane1.expandedProperty().addListener((observable, oldValue, newValue) -> {
//make it fill space when expanded but not reserve space when collapsed
if (newValue) {
pane1.maxHeightProperty().set(Double.POSITIVE_INFINITY);
} else {
pane1.maxHeightProperty().set(Double.NEGATIVE_INFINITY);
}
});
要件が少し異なりました
- アコーディオンは、埋め込まれたビューのビュースペースを拡張または管理します
- ビュー全体をスクロールビューに入れることができます
- すべてのボックスは、アコーディオンが固定サイズの場合はビュー全体のサイズに完全に拡張され、固定ビューでない場合はコンテンツのサイズに拡張されます。
私の場合、3。とテスト2のすべてを実行することはできませんでしたが、次の修正を思い付くことができました。
1)VBoxを内部に、TitledWindowsを内部に持つScrollPaneを使用します。2)TitledPanesがVBox.grow="SOMETIMES"に設定されていることを確認します。3)最後の要素としてVBoxを追加し、VBox.vgrow = "ALWAYS"を設定します。これにより、TitledPanesが最小サイズにプッシュされます。fxmlを使用したい場合、またはJavaを使用したくない場合は、他のすべての人がコード例を提供しています。要素を直接使用するだけでも同様に機能します(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)これにより、互いに独立して拡大/縮小する積み重ねられたボックスが得られますが、コンテンツに適切にサイズ変更されないボックスがある場合の問題は修正されません(たとえば、リストビューが埋め込まれている場合)上記の例)、画面の領域が十分に残っている場合は、かなりスクロールする必要があります。ソリューション?少しのJavaが必要です。
この修正を実装するには、最初にTitledPanemaxHeightProperty()
を外部VBoxにバインドしheightProperty()
ます。
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());
}
}
各ペインにバインドしexpandedProperty()
、動的にバインドおよびバインド解除し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);
}
});
}
表示されている場合はVBoxと同じ大きさにし、表示されていない場合はできるだけ小さくしてください。この方法の利点は、レイアウトが現在表示されているTitledPanesの数に基づいて利用可能な高さを自動的に計算することです。これにより、希望する動作が正確に得られます。
ここでさらに詳しく説明します。