4

我正在研究本教程中的示例。根据教程,我想在两个选项卡之间拖动选项卡。到目前为止,我设法创建了这段代码,但我需要一些帮助才能完成代码。

资源

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);

拖动选项卡后插入选项卡的正确方法是什么:

目的地

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();
            }
        });

我想这个转移可以完成吗?

工作解决方案:

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;
    }
}
4

2 回答 2

3

非常感谢您,它基本上工作得很好。但是,当从第二个拖到第一个/上部的 tabpane 时,tab 的内容没有得到刷新,您需要更改 tab 或移动分割分隔线。第二个/下部选项卡总是正确刷新。到目前为止,我还没有找到解决方法,要求 tabpane 进行刷新不起作用。如果我能找到解决方案,我将不胜感激。

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

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

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

现在它可以工作了。再次感谢

编辑2:很抱歉,我不得不报告它有时/大部分时间都有效,但并非总是如此......仍在研究如何真正修复它。

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

于 2013-10-29T16:45:23.070 回答
0

这是我为此编写的代码。包括实现拖拽移动机制的驱动和监听。

  import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTree;

public class MovableTabbedPane extends JTabbedPane {

    private MovableTabbedPane  movableTabbedPane;
    public MovableTabbedPane() {
        super();
        movableTabbedPane = this;
        TabDragListener tabDragger = new TabDragListener();
        this.addMouseListener(tabDragger);
        this.addMouseMotionListener(tabDragger);        
    }

    private class TabDragListener implements MouseListener, MouseMotionListener {

        Point p0;
        double y0, y;
        Component current;
        String title;

        public void mousePressed(MouseEvent e) {
            p0 = e.getPoint();
            y0=p0.getY();

            for (int i = 0; i < getTabCount(); i++) {
                Rectangle bounds = getBoundsAt(i);
                if (bounds.contains(p0)) {
                    current = MovableTabbedPane.this.getComponentAt(i);   
                    title =MovableTabbedPane.this.getTitleAt(i);
                }
            }
        };

        public void mouseDragged(MouseEvent e) {
            Point p = e.getPoint();
            y=p.getY();

            if (current != null) {
                // check for a significant horizontal drag
                if(Math.abs(y-y0)< 40 && p.distance(p0)>5){
                    int targetIndex = MovableTabbedPane.this.getUI().tabForCoordinate(MovableTabbedPane.this,
                            e.getX(), e.getY());
                    // target index should be valid and also not be same as original tab's index
                    if(targetIndex!=-1 && targetIndex!=getSelectedIndex()){         
                        movableTabbedPane.remove(current);
                        movableTabbedPane.insertTab(title, null, current, null, targetIndex);
                        setSelectedIndex(targetIndex);
                    }
                }
            } 
        }

        public void mouseMoved(MouseEvent arg0) {}

        public void mouseClicked(MouseEvent arg0) {}

        public void mouseEntered(MouseEvent arg0) {}

        public void mouseExited(MouseEvent arg0) {}

        public void mouseReleased(MouseEvent arg0) {
            current=null;
            title =null;
        }
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        MovableTabbedPane pane = new MovableTabbedPane();
        pane.add(new JTree(), "Tree 0");
        pane.add(new JTextArea(" Hello"), "Tree 1");
        pane.add(new JFileChooser(), "Tree 2");
        pane.add(new JSpinner(), "Tree 3");
        pane.add(new JSlider(),"Tree 4");
        frame.getContentPane().add(pane);
        frame.setBounds(100, 100, 400, 400);
        frame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        frame.setVisible(true);
    }
}
于 2015-03-26T20:42:24.167 回答