首页 > 解决方案 > 如何在 buttonClick 上的 Accordion 中选择特定的 TitlePane?

问题描述

我一直在使用 JavaFX(使用 SceneBuilder)来构建文件共享系统。我的 GUI 在旁边使用 TitledPane 显示所有上传的文件,所有这些文件都组织在手风琴中。

图形用户界面

单击Remove File按钮时,我想删除“已选择”的任何 TitledPane,我假设它是打开的(扩展的属性),但是当我单击它时它不会更改为被视为已扩展。通常,当您在这种情况下单击 TitledPane 时,栏会向下打开并显示其子节点。我认为这种状态会被认为是扩展的,但我想事实并非如此。

onClick 方法:

    public void removeFileClicked(){
        ObservableList<TitledPane> children = peersAccordion.getPanes();
        TitledPane removed = null;
        for(TitledPane p : children){
            if (p.isExpanded()) {
                TextArea a = (TextArea) p.getChildrenUnmodifiable().get(0);
                removeFileFromShared(a.getText().split("\n")[0]);
                removed = p;
                break;
            }
        }
        children.remove(removed);
    }

我能做些什么来解决这个问题?有替代解决方案吗?

标签: javajavafx

解决方案


这是一个示例解决方案。

它在滚动窗格中显示手风琴。

可以使用按钮添加和删除手风琴中的项目。在添加或删除时,手风琴中下一个最相关的标题窗格会自动展开。

添加发生在列表的末尾。列表中新添加的窗格是新扩展的窗格。

对于删除,新扩展的项目是列表中的前一个元素(如果存在),或者如果删除的元素是列表中的第一个元素,则为下一个元素。如果删除了最后一个窗格,则手风琴中没有展开的窗格。

如果没有展开标题窗格,则“删除”按钮被禁用,并且无法删除,但“添加”仍然是可能的,并且功能如上所述。

图片

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;

import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class AccordionModification extends Application {

    private static final Lorem lorem = new Lorem();

    private static final double SPACING = 10;

    private static final int N_INITIAL_PANES = 5;
    private static final int N_WORDS_PER_PANE = 10;

    public void start(Stage stage) {
        Accordion accordion = new Accordion();
        IntStream.range(0, N_INITIAL_PANES).forEach(i ->
                accordion.getPanes().add(createTitledPane())
        );
        accordion.setExpandedPane(accordion.getPanes().get(0));

        ScrollPane scrollPane = new ScrollPane(accordion);
        scrollPane.setFitToWidth(true);

        Button add = new Button("Add");
        add.setOnAction(e -> addPane(accordion, scrollPane));

        Button remove = new Button("Remove");
        remove.setOnAction(e -> removePane(accordion));
        remove.disableProperty().bind(
                accordion.expandedPaneProperty().isNull()
        );

        HBox controls = new HBox(SPACING, add, remove);

        VBox layout = new VBox(SPACING, controls, scrollPane);
        layout.setPadding(new Insets(SPACING));

        stage.setScene(new Scene(layout));
        stage.show();
    }

    private void addPane(Accordion accordion, ScrollPane scrollPane) {
        TitledPane newPane = createTitledPane();
        accordion.getPanes().add(newPane);
        accordion.setExpandedPane(newPane);
        newPane.requestFocus();

        scrollPane.applyCss();
        scrollPane.layout();

        scrollPane.setVvalue(scrollPane.getVmax());
    }

    private void removePane(Accordion accordion) {
        TitledPane expandedPane = accordion.getExpandedPane();

        if (expandedPane != null) {
            int expandedIndex = accordion.getPanes().indexOf(expandedPane);
            accordion.getPanes().remove(expandedPane);

            int nPanes = accordion.getPanes().size();

            if (nPanes > 0) {
                TitledPane nextPane = accordion.getPanes().get(
                        Math.max(0, expandedIndex - 1)
                );

                accordion.setExpandedPane(
                        nextPane
                );

                nextPane.requestFocus();
            }
        }
    }

    private TitledPane createTitledPane() {
        return new TitledPane(
                lorem.nextWord(),
                createTitledPaneContent()
        );
    }

    private Parent createTitledPaneContent() {
        Label content = new Label(lorem.nextText(N_WORDS_PER_PANE));
        content.setWrapText(true);
        StackPane container = new StackPane(content);
        container.setAlignment(Pos.BASELINE_LEFT);

        return container;
    }

    // class for generating example text for test data, not integral to the solution.
    private static final class Lorem {
        private static final String[] lorem = "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua".split(" ");
        private int idx = 0;

        public String nextWord() {
            return lorem[getAndIncrementIdx()];
        }

        public String nextText(int nWords) {
            return IntStream.range(0, nWords)
                    .mapToObj(i -> nextWord())
                    .collect(Collectors.joining(" "));
        }

        private int getAndIncrementIdx() {
            int retVal = idx;

            idx = (idx + 1) % lorem.length;

            return retVal;
        }
    }

}

推荐阅读