如何在选项卡窗格之间拖放选项卡节点 [英] How to drag and drop tab nodes between tab panes

查看:190
本文介绍了如何在选项卡窗格之间拖放选项卡节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从这个教程。根据教程,我想在两个标签之间拖动标签。到目前为止,我设法创建了此代码,但我需要一些帮助才能完成代码。

I'm working on example from this tutorial. Based on the tutorial I want to drag tabs between two tabs. So far I managed to create this code but I need some help in order to finish the code.

来源

Source

tabPane = new TabPane();

        Tab tabA = new Tab();
        Label tabALabel = new Label("Main Component");

        tabPane.setOnDragDetected(new EventHandler<MouseEvent>()
        {
            @Override
            public void handle(MouseEvent event)
            {
                /* drag was detected, start drag-and-drop gesture*/
                System.out.println("onDragDetected");

                /* allow any transfer mode */
                Dragboard db = tabPane.startDragAndDrop(TransferMode.ANY);

                /* put a string on dragboard */
                ClipboardContent content = new ClipboardContent();
                content.put(DataFormat.PLAIN_TEXT, tabPane);
                db.setContent(content);

                event.consume();
            }
        });

将标签内容作为对象插入的正确方法是什么?进入教程简单文本被传输。我必须如何修改这一行 content.put(DataFormat.PLAIN_TEXT,tabPane);

What is the proper way to insert the content of the tab as object? Into the tutorial simple text is transferred. How I must modify this line content.put(DataFormat.PLAIN_TEXT, tabPane);?

什么是拖动标签后插入标签的正确方法:

And what is the proper way to insert the tab after I drag the tab:

目的地

Destination

tabPane.setOnDragDropped(new EventHandler<DragEvent>()
        {
            @Override
            public void handle(DragEvent event)
            {
                /* data dropped */
                /* if there is a string data on dragboard, read it and use it */
                Dragboard db = event.getDragboard();
                boolean success = false;
                if (db.hasString())
                {
                    //tabPane.setText(db.getString());
                    Tab tabC = new Tab();
                    tabPane.getTabs().add(tabC);
                    success = true;
                }
                /* let the source know whether the string was successfully
                 * transferred and used */
                event.setDropCompleted(success);

                event.consume();
            }
        });

我想这次转账可以完成吗?

I suppose that this transfer can be accomplished?

工作解决方案:

The working solution:

import java.util.Random;
import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DragEvent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class client extends Application
{

    private static final String TAB_DRAG_KEY = "tab";
    private ObjectProperty<Tab> draggingTab;

    @Override
    public void start(Stage primaryStage)
    {
        draggingTab = new SimpleObjectProperty<>();
        TabPane tabPane1 = createTabPane();
        TabPane tabPane2 = createTabPane();
        VBox root = new VBox(10);
        root.getChildren().addAll(tabPane1, tabPane2);
        final Random rng = new Random();
        for (int i = 1; i <= 8; i++)
        {
            final Tab tab = createTab("Tab " + i);
            final StackPane pane = new StackPane();
            int red = rng.nextInt(256);
            int green = rng.nextInt(256);
            int blue = rng.nextInt(256);
            String style = String.format("-fx-background-color: rgb(%d, %d, %d);", red, green, blue);
            pane.setStyle(style);
            final Label label = new Label("This is tab " + i);
            label.setStyle(String.format("-fx-text-fill: rgb(%d, %d, %d);", 256 - red, 256 - green, 256 - blue));
            pane.getChildren().add(label);
            pane.setMinWidth(600);
            pane.setMinHeight(250);
            tab.setContent(pane);
            if (i <= 4)
            {
                tabPane1.getTabs().add(tab);
            }
            else
            {
                tabPane2.getTabs().add(tab);
            }
        }
        primaryStage.setScene(new Scene(root, 600, 600));
        primaryStage.show();
    }

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

    private TabPane createTabPane()
    {
        final TabPane tabPane = new TabPane();
        tabPane.setOnDragOver(new EventHandler<DragEvent>()
        {
            @Override
            public void handle(DragEvent event)
            {
                final Dragboard dragboard = event.getDragboard();
                if (dragboard.hasString()
                        && TAB_DRAG_KEY.equals(dragboard.getString())
                        && draggingTab.get() != null
                        && draggingTab.get().getTabPane() != tabPane)
                {
                    event.acceptTransferModes(TransferMode.MOVE);
                    event.consume();
                }
            }
        });
        tabPane.setOnDragDropped(new EventHandler<DragEvent>()
        {
            @Override
            public void handle(DragEvent event)
            {
                final Dragboard dragboard = event.getDragboard();
                if (dragboard.hasString()
                        && TAB_DRAG_KEY.equals(dragboard.getString())
                        && draggingTab.get() != null
                        && draggingTab.get().getTabPane() != tabPane)
                {
                    final Tab tab = draggingTab.get();
                    tab.getTabPane().getTabs().remove(tab);
                    tabPane.getTabs().add(tab);
                    tabPane.getSelectionModel().select(tab);
                    event.setDropCompleted(true);
                    draggingTab.set(null);
                    event.consume();
                }
            }
        });
        return tabPane;
    }

    private Tab createTab(String text)
    {
        final Tab tab = new Tab();
        final Label label = new Label(text);
        tab.setGraphic(label);
        label.setOnDragDetected(new EventHandler<MouseEvent>()
        {
            @Override
            public void handle(MouseEvent event)
            {
                Dragboard dragboard = label.startDragAndDrop(TransferMode.MOVE);
                ClipboardContent clipboardContent = new ClipboardContent();
                clipboardContent.putString(TAB_DRAG_KEY);
                dragboard.setContent(clipboardContent);
                draggingTab.set(tab);
                event.consume();
            }
        });
        return tab;
    }
}


推荐答案

谢谢你非常喜欢这个,它基本上运作良好。但是,当从第二个选项卡拖动到第一个/上部tabpane时,选项卡的内容不会刷新,您需要更改选项卡或移动拆分分隔符。第二个/更低的tabpane始终正确刷新。到目前为止,我还没有找到解决方法,要求tabpane进行刷新不起作用。如果我能找到解决方案,我真的很感激。

Thank you very much for this, it works basically well. However, when dragging to the first / upper tabpane from the second one, the content of the tab does not get refreshed, you need to change the tab or move the split divider. The second / lower tabpane does always refresh correctly. I have not found a remedy for this so far, asking the tabpane to do a refresh does not work. I would really appreciated if I could find a solution for this.

编辑:找到了可行的解决方案

found a working solution

在setOnDragDropped事件处理程序中,我发表了评论选择添加的选项卡的行,然后添加以下代码:

In the setOnDragDropped event handler I commented the line that selects the added tab, then added the following code:

Platform.runLater(new Runnable() {
   @Override
   public void run() {
       tabPane.getSelectionModel().select(tab) ;
   }
});

现在可行。再次感谢

编辑2 :对不起,我必须报告它有时/大部分时间有效,但并非总是如此。仍在调查如何真正解决它。

Edit 2: I'm sorry that I have to report that it works sometimes / most of the time, but not always.. still investigating on how to fix it for real.

编辑3:至少现在我知道导致问题的原因:当一个标签被移除并添加到另一个窗格时,从旧的tabpane不是即时的,然后旧窗格禁用该选项卡的上下文的更新,该选项卡现在已经在另一个tabpane中。这就是为什么它根本没有被绘制出来的原因。当我在删除和添加的调用之间放置一个Thread.sleep(500)(较短的睡眠时间不起作用)时,一切正常。如果我设法找到解决方案,将在以后更新。

Edit 3: At least now i know what causes the problem: when one tab is removed and added to the other pane, the removal from the old tabpane is not instant, and then the old pane disable the update of the context of that tab which is now already in the other tabpane. that's why it does not get drawn at all. When I put a Thread.sleep(500) (shorter sleep time is not working) between the calls to remove and add, everything works fine. Will update later if I manage to find a solution.

这篇关于如何在选项卡窗格之间拖放选项卡节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆