Как переключать TabPanes местами с помощью перетаскивания мышью

Я хотел бы расширить этот post реализации TabPanes.

Мне интересно, можно ли каким-то образом перетаскивать TabPane мышью, чтобы изменить положение TabPane с помощью перетаскивания мышью. Основное объяснение того, как это можно реализовать, будет высоко оценено.

import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.SplitPane;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;


public class FXSplitTabs extends Application{

    @Override
    public void start(Stage stage) throws Exception {
        stage.setTitle("SplitTabs");
        stage.setWidth(700);
        stage.setHeight(500);

        //Setup Center and Right
        TabPaneWrapper wrapper = new TabPaneWrapper(Orientation.HORIZONTAL, .9);
        TabPane centerPane = new TabPane();
        centerPane.getTabs().addAll(generateTab("Tab 1"),generateTab("Tab 2"), generateTab("Tab 3"), generateTab("Tab N"));

        TabPane rightPane = new TabPane();
        rightPane.getTabs().addAll(generateTab("Tab 1"),generateTab("Tab 2"), generateTab("Tab 3"), generateTab("Tab N"));
        SplitPane.setResizableWithParent(rightPane, false);
        wrapper.addNodes(centerPane, rightPane);

        //Add bottom
        TabPane bottomPane = new TabPane();
        bottomPane.getTabs().addAll(generateTab("Tab 1"),generateTab("Tab 2"), generateTab("Tab 3"), generateTab("Tab N"));
        TabPaneWrapper wrapperBottom = new TabPaneWrapper(Orientation.VERTICAL, .7);
        wrapperBottom.addNodes(wrapper.getNode(), bottomPane);

        //Add left
        TabPane leftPane = new TabPane();
        leftPane.getTabs().addAll(generateTab("Tab 1"),generateTab("Tab 2"), generateTab("Tab 3"), generateTab("Tab N"));
        TabPaneWrapper wrapperleft = new TabPaneWrapper(Orientation.HORIZONTAL, .1);
        wrapperleft.addNodes(leftPane, wrapperBottom.getNode());

        Scene myScene = new Scene(wrapperleft.getNode());
        stage.setScene(myScene);
        stage.sizeToScene();
        stage.show();
    }

    public Tab generateTab(String name){
        Tab result = new Tab(name);
        BorderPane content = new BorderPane();
        TextArea text = new TextArea();
        content.setCenter(text);
        result.setContent(content);
        return result;
    }

    public static void main(String[] args){
        FXSplitTabs.launch(args);
    }

    public static class TabPaneWrapper{
        SplitPane split;

        public TabPaneWrapper(Orientation o, double splitLocation){
            split = new SplitPane();

            //Change the CSS (uncomment if using an external css)
            //split.getStylesheets().add("test.css");

            split.setOrientation(o);
            split.setDividerPosition(0, splitLocation);
        }

        public void addNodes(final Node node1, final Node node2){
            //Add to the split pane
            split.getItems().addAll(node1, node2);
        }

        public Parent getNode(){
            return split;
        }
    }

}

введите здесь описание изображения


person Peter Penzov    schedule 15.07.2013    source источник
comment
Пожалуйста, прочитайте это, это может помочь вам в вашей задаче: forums.oracle.com/thread/2387524   -  person Lajos Arpad    schedule 16.07.2013


Ответы (1)


Я бы рекомендовал добавить слушателя onDragDetected и слушателя onMouseDragReleased ко всем вашим TabPanes.

    TabPaneDrag drag = new TabPaneDrag();
    ...
    centerPane.setOnDragDetected(drag);
    centerPane.setOnMouseDragReleased(drag);
    ...
    rightPane.setOnDragDetected(drag);
    rightPane.setOnMouseDragReleased(drag);

В вашем слушателе вы можете отслеживать, какая панель начала перетаскивание и какая панель закончила перетаскивание (затем при необходимости переключите их). Вот быстрый пример (имейте в виду, что есть некоторые особые случаи и перегибы и тому подобное, с которыми я не беспокоился - И findWrapper() - это метод, который возвращает TabPaneWrapper, содержащий TabPane):

public class TabPaneDrag implements EventHandler<MouseEvent>{
    Node start;
    Node end;

    @Override
    public void handle(MouseEvent arg0) {
        if(arg0.getEventType().equals(MouseEvent.DRAG_DETECTED)){
            start = (Node)arg0.getSource();
            start.startFullDrag(); //allows events to fire on nodes besides source
        } else if(arg0.getEventType().equals(MouseDragEvent.MOUSE_DRAG_RELEASED)){
            end = (Node)arg0.getSource();
            if(end != start){
                ObservableList<Node> startWrapper = findWrapper(start).split.getItems();
                ObservableList<Node> endWrapper = findWrapper(end).split.getItems();
                int startIndex = startWrapper.indexOf(start);
                int endIndex = endWrapper.indexOf(end);

                // Remove/Add  the TabbedPanes to the new order
                endWrapper.remove(endIndex);
                startWrapper.remove(startIndex);

                startWrapper.add(startIndex, end);
                endWrapper.add(endIndex, start);

            }
            start = null;
            end = null;
        }
    }
}
person Nick Rippe    schedule 16.07.2013
comment
Еще один вопрос: где я могу найти расширенные руководства по JavaFX для таких тем? Каждый учебник, который я нахожу, предназначен для очень простого примера? - person Peter Penzov; 17.07.2013
comment
Материалы для перетаскивания: я не нашел для этого очень хорошего ресурса. И я не нашел много окончательных ресурсов в целом (извините!). Пока что Oracle действительно лидирует — я видел несколько отличных видеороликов с конференции Java One, которые мне очень помогли. В основном я использую: docs.oracle.com/ javafx/2/api/javafx/scene/doc-files/cssref.html и документы JavaDocs в режиме кадра: docs.oracle.com/javafx/2/api/index.html?overview-summary.html - person Nick Rippe; 17.07.2013
comment
Я пытался реализовать это, но не знаю, как реализовать метод Java findWrapper(). Каково содержание этого метода? - person Peter Penzov; 25.07.2013
comment
Подсказка: if(wrapper.split.getItems().contains(toFind)), где toFind — это узел, переданный в функцию, а wrapper — экземпляр TaskPaneWrapper. - person Nick Rippe; 31.07.2013