gpt4 book ai didi

java - 如何拖放同一标签面板的标签?

转载 作者:行者123 更新时间:2023-11-29 09:59:29 25 4
gpt4 key购买 nike

我已经看到很多关于如何将标签面板的标签拖到另一个标签面板的方法,顺便说一下,我不明白这一点,我想它在某种程度上可能有用,但最自然的应用应该是重新排序同一个标签面板的标签,似乎没有人在互联网上谈论这个问题。

我想要几乎所有浏览器都实现的行为。

我已经尝试了一些方法,但它没有按照我的意愿进行。主要问题是 Tab 不能与 setOnDragDetectedsetOnDragOver 等方法绑定(bind)(出于某种原因,我逃避了方式 ...) 这导致算法过于复杂来弥补库的这一弱点。

所以这是我的代码,它没有做我想做的事情,因为(这只是一种解决方法)我只在放置完成后检测到“放置目标”,因此使其无用。是的,出于某种原因,在按住单击按钮的同时悬停对象不会导致 mouseover 事件 ...

import javafx.application.Application;
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.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class DragAndDrop extends Application
{
public void start(Stage primaryStage)
{
TabPane tabPane = new TabPane();

final int[] target = {0};

for(int i = 0 ; i < 2 ; i ++)
{
Tab tab = new Tab();
tab.setClosable(false);

int index[] = {i};

tabPane.getTabs().add(tab);

Label label = new Label("Tab " + (i + 1), new Rectangle(16, 16, Color.TRANSPARENT));
tab.setGraphic(label);

tab.getGraphic().setOnMouseEntered(event ->
{
target[0] = index[0];
System.out.println("target : " + target[0]);
});
}

tabPane.setOnDragDetected(event ->
{
Dragboard dragboard = tabPane.startDragAndDrop(TransferMode.ANY);

ClipboardContent clipboardContent = new ClipboardContent();
clipboardContent.putString(Integer.toString(tabPane.getSelectionModel().getSelectedIndex()));
System.out.println("source : " + tabPane.getSelectionModel().getSelectedIndex());
dragboard.setContent(clipboardContent);

event.consume();
});

tabPane.setOnDragOver(event ->
{
if(event.getDragboard().hasString())
{
event.acceptTransferModes(TransferMode.COPY_OR_MOVE);
}

event.consume();
});

tabPane.setOnDragDropped(event ->
{
Dragboard dragboard = event.getDragboard();
boolean success = false;

if(dragboard.hasString())
{
System.out.println("from " + dragboard.getString() + " to " + target[0]);

success = true;
}

event.setDropCompleted(success);
event.consume();
});

tabPane.setOnDragDone(event ->
{
if(event.getTransferMode() == TransferMode.MOVE)
{
// tabPane.setText("");
}
event.consume();
});

primaryStage.setScene(new Scene(tabPane, 300, 200));
primaryStage.show();
}

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

最佳答案

我认为解决这个问题的最简单方法是将拖动处理程序注册到与选项卡关联的图形,而不是注册到选项卡 Pane 。这使得管理选项卡的索引等变得更容易一些,并且您不依赖于鼠标拖动操作和选择之间的相互作用(您真的不知道它们将以什么顺序发生)。这种方法的缺点是您必须以某种方式确保每个选项卡都有一个图形(您可以使用标签作为图形来显示文本)。

这是一个通用的“选项卡 Pane 拖动支持”类。无论如何,这并不意味着生产质量,但基础似乎有效。这里的想法是您创建一个 DraggingTabPaneSupport 实例,并使用它为一个或多个 TabPane 添加拖动支持。然后可以在任何这些 Pane 内或之间拖动选项卡。如果您希望只能在每个选项卡 Pane 内拖动,请为每个选项卡 Pane 创建一个 DraggingTabPaneSupport 实例。

import java.util.concurrent.atomic.AtomicLong;

import javafx.collections.ListChangeListener.Change;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;

public class DraggingTabPaneSupport {

private Tab currentDraggingTab ;

private static final AtomicLong idGenerator = new AtomicLong();

private final String draggingID = "DraggingTabPaneSupport-"+idGenerator.incrementAndGet() ;

public void addSupport(TabPane tabPane) {
tabPane.getTabs().forEach(this::addDragHandlers);
tabPane.getTabs().addListener((Change<? extends Tab> c) -> {
while (c.next()) {
if (c.wasAdded()) {
c.getAddedSubList().forEach(this::addDragHandlers);
}
if (c.wasRemoved()) {
c.getRemoved().forEach(this::removeDragHandlers);
}
}
});

// if we drag onto a tab pane (but not onto the tab graphic), add the tab to the end of the list of tabs:
tabPane.setOnDragOver(e -> {
if (draggingID.equals(e.getDragboard().getString()) &&
currentDraggingTab != null &&
currentDraggingTab.getTabPane() != tabPane) {
e.acceptTransferModes(TransferMode.MOVE);
}
});
tabPane.setOnDragDropped(e -> {
if (draggingID.equals(e.getDragboard().getString()) &&
currentDraggingTab != null &&
currentDraggingTab.getTabPane() != tabPane) {

currentDraggingTab.getTabPane().getTabs().remove(currentDraggingTab);
tabPane.getTabs().add(currentDraggingTab);
currentDraggingTab.getTabPane().getSelectionModel().select(currentDraggingTab);
}
});
}

private void addDragHandlers(Tab tab) {

// move text to label graphic:
if (tab.getText() != null && ! tab.getText().isEmpty()) {
Label label = new Label(tab.getText(), tab.getGraphic());
tab.setText(null);
tab.setGraphic(label);
}

Node graphic = tab.getGraphic();
graphic.setOnDragDetected(e -> {
Dragboard dragboard = graphic.startDragAndDrop(TransferMode.MOVE);
ClipboardContent content = new ClipboardContent();
// dragboard must have some content, but we need it to be a Tab, which isn't supported
// So we store it in a local variable and just put arbitrary content in the dragbaord:
content.putString(draggingID);
dragboard.setContent(content);
dragboard.setDragView(graphic.snapshot(null, null));
currentDraggingTab = tab ;
});
graphic.setOnDragOver(e -> {
if (draggingID.equals(e.getDragboard().getString()) &&
currentDraggingTab != null &&
currentDraggingTab.getGraphic() != graphic) {
e.acceptTransferModes(TransferMode.MOVE);
}
});
graphic.setOnDragDropped(e -> {
if (draggingID.equals(e.getDragboard().getString()) &&
currentDraggingTab != null &&
currentDraggingTab.getGraphic() != graphic) {

int index = tab.getTabPane().getTabs().indexOf(tab) ;
currentDraggingTab.getTabPane().getTabs().remove(currentDraggingTab);
tab.getTabPane().getTabs().add(index, currentDraggingTab);
currentDraggingTab.getTabPane().getSelectionModel().select(currentDraggingTab);
}
});
graphic.setOnDragDone(e -> currentDraggingTab = null);
}

private void removeDragHandlers(Tab tab) {
tab.getGraphic().setOnDragDetected(null);
tab.getGraphic().setOnDragOver(null);
tab.getGraphic().setOnDragDropped(null);
tab.getGraphic().setOnDragDone(null);
}
}

这是一个使用它的简单示例。在此示例中,我创建了三个选项卡 Pane 。我为前两个 Pane 创建了一个拖动支持实例,因此可以在这两个 Pane 之间拖动选项卡,并为第三个 Pane 创建了第二个拖动支持实例,因此在第三个 Pane 中选项卡可以通过拖动重新排序但不能拖动到其他两个 Pane 。

import java.util.Random;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class DraggingTabPaneExample extends Application {

private final Random rng = new Random();

@Override
public void start(Stage primaryStage) {
TabPane[] panes = new TabPane[] {new TabPane(), new TabPane(), new TabPane() };
VBox root = new VBox(10, panes);
for (int i = 1 ; i <= 15; i++) {
Tab tab = new Tab("Tab "+i);
tab.setGraphic(new Rectangle(16, 16, randomColor()));
Region region = new Region();
region.setMinSize(100, 150);
tab.setContent(region);
panes[(i-1) % panes.length].getTabs().add(tab);
}

DraggingTabPaneSupport support1 = new DraggingTabPaneSupport();
support1.addSupport(panes[0]);
support1.addSupport(panes[1]);
DraggingTabPaneSupport support2 = new DraggingTabPaneSupport();
support2.addSupport(panes[2]);

Scene scene = new Scene(root, 600, 600);
primaryStage.setScene(scene);
primaryStage.show();
}

private Color randomColor() {
return Color.rgb(rng.nextInt(256), rng.nextInt(256), rng.nextInt(256));
}

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

初始截图:

enter image description here

在 Pane 内拖动后: enter image description here

您还可以在前两个 Pane 之间拖动(但不能在第三个 Pane 和任何其他 Pane 之间拖动):

enter image description here

关于java - 如何拖放同一标签面板的标签?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41473987/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com