Как изменить размер компонента с помощью перетаскивания мышью в JavaFX

Мне интересно, как я могу изменить размер этого компонента с помощью перетаскивания мышью:

VBox stackedTitledPanes = createStackedTitledPanes();

    ScrollPane scroll = makeScrollable(stackedTitledPanes);

    TabPane tabPane = new TabPane();
    BorderPane mainPane = new BorderPane();

    tabPane.setStyle("-fx-font-size: 12pt;"); // Set global size for the font
    // Create Tabs
    Tab tabA = new Tab();
    tabA.setText("Main Component");
    tabA.setStyle("-fx-font-size: 12pt;"); // Set size of the tab name
    // Add something in Tab
    StackPane tabA_stack = new StackPane();
    tabA_stack.setAlignment(Pos.CENTER);
    tabA_stack.getChildren().add(scroll); 
    tabA.setContent(tabA_stack);
    tabPane.getTabs().add(tabA);

    Tab tabB = new Tab();
    tabB.setText("Second Component");
    tabB.setStyle("-fx-font-size: 12pt;"); // Set size of the tab name
    // Add something in Tab
    StackPane tabB_stack = new StackPane();
    tabB_stack.setAlignment(Pos.CENTER);
    tabB_stack.getChildren().add(new Label("Label@Tab B"));
    tabB.setContent(tabB_stack);
    tabPane.getTabs().add(tabB);

    Tab tabC = new Tab();
    tabC.setText("Last Component");
    tabC.setStyle("-fx-font-size: 12pt;"); // Set size of the tab name
    // Add something in Tab
    StackPane tabC_vBox = new StackPane();
    tabC_vBox.setAlignment(Pos.CENTER);
    tabC_vBox.getChildren().add(new Label("Label@Tab C"));
    tabC.setContent(tabC_vBox);
    tabPane.getTabs().add(tabC);

    mainPane.setCenter(tabPane);

    mainPane.setPrefSize(395, 580);
    mainPane.setLayoutX(850);
    mainPane.setLayoutY(32);

    scroll.setPrefSize(395, 580);
    scroll.setLayoutX(850);
    scroll.setLayoutY(32);

    root.getChildren().add(mainPane);

Проблема в том, что у меня на основной сцене размещено несколько компонентов. Когда я изменяю размер одного компонента, например, увеличиваю высоту компонента, я должен уменьшить размер следующего компонента, не переступая через компонент. Как я могу это сделать?


person Peter Penzov    schedule 04.06.2013    source источник


Ответы (2)


Я думаю, что проблема связана с панелью стека, она не поддерживает изменение размера, как VBox или HBox. Я перетаскиваю свою собственную программу, чтобы изменить размер компонентов TextArea или List, чтобы сделать их больше, если это необходимо. Проверьте код здесь:

https://bitbucket.org/atill/estimate/src/22390a2ca034b55f1916e46435b714e5c489b90e/src/main/java/projmon/ui/DragResizer.java?at=master

и использование:

https://bitbucket.org/atill/estimate/src/22390a2ca034b55f1916e46435b714e5c489b90e/src/main/java/projmon/control/TaskFormController.java?at=master

РЕДАКТИРОВАТЬ Я вытащил EstiMate, но в этом смысле инструмент для изменения размера перетаскивания по-прежнему является открытым исходным кодом.

https://gist.github.com/andytill/4369729

Или полный код.

import javafx.event.EventHandler;
import javafx.scene.Cursor;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Region;

/**
 * {@link DragResizer} can be used to add mouse listeners to a {@link Region}
 * and make it resizable by the user by clicking and dragging the border in the
 * same way as a window.
 * <p>
 * Only height resizing is currently implemented. Usage: <pre>DragResizer.makeResizable(myAnchorPane);</pre>
 * 
 * @author atill
 * 
 */
public class DragResizer {

    /**
     * The margin around the control that a user can click in to start resizing
     * the region.
     */
    private static final int RESIZE_MARGIN = 5;

    private final Region region;

    private double y;

    private boolean initMinHeight;

    private boolean dragging;

    private DragResizer(Region aRegion) {
        region = aRegion;
    }

    public static void makeResizable(Region region) {
        final DragResizer resizer = new DragResizer(region);

        region.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                resizer.mousePressed(event);
            }});
        region.setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                resizer.mouseDragged(event);
            }});
        region.setOnMouseMoved(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                resizer.mouseOver(event);
            }});
        region.setOnMouseReleased(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                resizer.mouseReleased(event);
            }});
    }

    protected void mouseReleased(MouseEvent event) {
        dragging = false;
        region.setCursor(Cursor.DEFAULT);
    }

    protected void mouseOver(MouseEvent event) {
        if(isInDraggableZone(event) || dragging) {
            region.setCursor(Cursor.S_RESIZE);
        }
        else {
            region.setCursor(Cursor.DEFAULT);
        }
    }

    protected boolean isInDraggableZone(MouseEvent event) {
        return event.getY() > (region.getHeight() - RESIZE_MARGIN);
    }

    protected void mouseDragged(MouseEvent event) {
        if(!dragging) {
            return;
        }

        double mousey = event.getY();

        double newHeight = region.getMinHeight() + (mousey - y);

        region.setMinHeight(newHeight);

        y = mousey;
    }

    protected void mousePressed(MouseEvent event) {

        // ignore clicks outside of the draggable margin
        if(!isInDraggableZone(event)) {
            return;
        }

        dragging = true;

        // make sure that the minimum height is set to the current height once,
        // setting a min height that is smaller than the current height will
        // have no effect
        if (!initMinHeight) {
            region.setMinHeight(region.getHeight());
            initMinHeight = true;
        }

        y = event.getY();
    }
}
person Andy Till    schedule 04.06.2013
comment
Есть ли простой пример, как я могу реализовать изменение размера компонента мышью? - person Peter Penzov; 05.06.2013
comment
Это настолько просто, насколько это возможно, используйте DragResizer и посмотрите строки 174 и 175 TaskFormController. - person Andy Till; 05.06.2013
comment
На данный момент эти ссылки не работают. Прямое включение контента в пост позволяет избежать этой ловушки. - person OYRM; 05.05.2016

Вот модифицированная версия для случая верхней и нижней области. Если один регион растет, другой становится меньше.

public class DragResizer {

    /**
     * The margin around the control that a user can click in to start resizing
     * the region.
     */
    private static final int RESIZE_MARGIN = 5;

    private final Region top, bottom;

    private double y;

    private boolean initMinHeight;

    private boolean dragging;

    private double ySum;

    private DragResizer(Region top, Region bottom) {
        this.top = top;
        this.bottom = bottom;
        ySum = top.getPrefHeight() + bottom.getPrefHeight();
    }

    public static void makeResizable(Region top, Region bottom) {
        final DragResizer resizer = new DragResizer(top, bottom);

        top.setOnMousePressed(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                resizer.mousePressed(event);
            }});
        top.setOnMouseDragged(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                resizer.mouseDragged(event);
            }});
        top.setOnMouseMoved(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                resizer.mouseOver(event);
            }});
        top.setOnMouseReleased(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                resizer.mouseReleased(event);
            }});
    }

    protected void mouseReleased(MouseEvent event) {
        dragging = false;
        top.setCursor(Cursor.DEFAULT);
    }

    protected void mouseOver(MouseEvent event) {
        if(isInDraggableZone(event) || dragging) {
            top.setCursor(Cursor.S_RESIZE);
        }
        else {
            top.setCursor(Cursor.DEFAULT);
        }
    }

    protected boolean isInDraggableZone(MouseEvent event) {
        return event.getY() > (top.getHeight() - RESIZE_MARGIN);
    }

    protected void mouseDragged(MouseEvent event) {
        if(!dragging) {
            return;
        }

        double mousey = event.getY();

        double dy = (mousey - y);

        if(top.getMinHeight() + dy >= ySum || bottom.getPrefHeight() - dy >= ySum)
            return;

        top.setMinHeight(top.getMinHeight() + dy);
        top.setPrefHeight(top.getPrefHeight() + dy);

        bottom.setMinHeight(bottom.getMinHeight() - dy);
        bottom.setPrefHeight(bottom.getPrefHeight() - dy);

        y = mousey;
    }

    protected void mousePressed(MouseEvent event) {

        // ignore clicks outside of the draggable margin
        if(!isInDraggableZone(event)) {
            return;
        }

        dragging = true;

        // make sure that the minimum height is set to the current height once,
        // setting a min height that is smaller than the current height will
        // have no effect
        if (!initMinHeight) {
            top.setMinHeight(top.getHeight());
            initMinHeight = true;
        }

        y = event.getY();
    }
}
person user12551103    schedule 17.12.2019
comment
Не могли бы вы просто использовать SplitPane сделать это? - person jewelsea; 17.12.2019