Эдуард Неткачёв
25 березня 2022 р. 00:29

Выделение нескольких объектов

QML, выделение нескольких элементов мышкой

Приветствую всех.
Не могу разобраться как сделать выделение нескольких элементов с помощью удержания клавиши мыши. Уже разные способы пробовал, но каждый раз какой-то затык.

Вот кусок основной программы main.qml:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5

ApplicationWindow {
    visible:    true
    title:      qsTr("Selection and Scaling")
    width:      Screen.desktopAvailableWidth*50/100
    height:     Screen.desktopAvailableHeight*80/100
    color:      "whitesmoke"

    property double my_scale: 1.0

    Flickable {
        id:             _scrollSetup
        anchors.fill:   parent
        boundsMovement: Flickable.StopAtBounds    // если контент больше видимой области, то при перемещении контента он останавливается на границе контента с видимой областью
        contentWidth:   _сolumn.width*my_scale >parent.width ? (_сolumn.width*my_scale):parent.width
        contentHeight:  _сolumn.height*my_scale >parent.height ? (_сolumn.height*my_scale):parent.height
        MouseArea {
            id: _mouseFlickable
            anchors.fill: parent
            property point clickPos: "0,0"
            onWheel:    if (wheel.angleDelta.y>0) { my_scale*=1.05; } else { my_scale*=0.95; } // реакция на скролл
            onClicked:  console.log("_mouseFlickable.onClicked");
            onPressed:  { console.log("_mouseFlickable.onPressed");
                clickPos  = Qt.point(mouse.x,mouse.y)
                _rect_select.x=clickPos.x; _rect_select.y=clickPos.y;
                _rect_select.width=0; _rect_select.height=0;
                _rect_select.visible=true;
            }
            onReleased: { console.log("_mouseFlickable.onReleased");
                _rect_select.visible=false;
            }
            onEntered:  console.log("_mouseFlickable.onEntered");
            onExited:   console.log("_mouseFlickable.onExited");
            onPositionChanged: {
                _rect_select.x=Math.min(mouse.x,clickPos.x)
                _rect_select.y=Math.min(mouse.y,clickPos.y)
                _rect_select.width=Math.abs(clickPos.x-mouse.x)
                _rect_select.height=Math.abs(clickPos.y-mouse.y)
            }
            Column {
                id: _сolumn
                anchors.verticalCenter: parent.verticalCenter
                anchors.horizontalCenter: parent.horizontalCenter
                scale: my_scale

                Row {
                    id: _rowUpper
                    MyElement {
                        id: element_1
                        number: 1
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_2
                        number: 2
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_3
                        number: 3
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_4
                        number: 4
                        height: 160
                        width:  160
                    }
                }
                Rectangle {
                    anchors.horizontalCenter:   parent.horizontalCenter
                    height:                     4
                    color:                      "lightsteelblue"
                    width:                      parent.width
                }
                Row {
                    id: _rowLower
                    MyElement {
                        id: element_5
                        number: 5
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_6
                        number: 6
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_7
                        number: 7
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_8
                        number: 8
                        height: 160
                        width:  160
                    }
                }
            }
        }
    }

    Rectangle {
        id: _rect_select
        visible: false
        color: "blue"
        opacity : 0.3
    }
}

Вот код элемента MyElement.qml:

import QtQuick 2.0

Item {
    property int number: 0
    property bool select: false

    MouseArea {
        id: _mouseArea
        anchors.fill: parent
        hoverEnabled: true      // это для работы функции containsMouse (наведение курсора мыши на область)
        propagateComposedEvents: true
        onClicked: { console.log("_mouse_" + number + ".onClicked");    mouse.accepted = false; }
        onPressed: { console.log("_mouse_" + number + ".onPressed");    mouse.accepted = false; }
        onReleased:{ console.log("_mouse_" + number + ".onReleased");   mouse.accepted = false; }
        onEntered: { console.log("_mouse_" + number + ".onEntered");  }
        onExited:  { console.log("_mouse_" + number + ".onExited");   }

        Rectangle {
            id: _rect
            anchors.fill: parent
            color:  "green"
            scale:  select ? 1.0 : _mouseArea.containsMouse ? 0.95 : 0.90
        }
    }
}

Может есть мысли как это сделать.

2

Вам це подобається? Поділіться в соціальних мережах!

1
P
  • 28 березня 2022 р. 01:29
  • Відповідь була позначена як рішення.

Как вариант, считать пересечение объектов с прямоугольником выделения,
примерный код набрасал:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5

ApplicationWindow {
    visible:    true
    title:      qsTr("Selection and Scaling")
    width:      Screen.desktopAvailableWidth*50/100
    height:     Screen.desktopAvailableHeight*80/100
    color:      "whitesmoke"

    property double my_scale: 1.0

    Flickable {
        id:             _scrollSetup
        anchors.fill:   parent
        boundsMovement: Flickable.StopAtBounds    // если контент больше видимой области, то при перемещении контента он останавливается на границе контента с видимой областью
        contentWidth:   _сolumn.width*my_scale >parent.width ? (_сolumn.width*my_scale):parent.width
        contentHeight:  _сolumn.height*my_scale >parent.height ? (_сolumn.height*my_scale):parent.height
        MouseArea {
            id: _mouseFlickable
            anchors.fill: parent
            property point clickPos: "0,0"
            onWheel:    if (wheel.angleDelta.y>0) { my_scale*=1.05; } else { my_scale*=0.95; } // реакция на скролл
            onClicked:  console.log("_mouseFlickable.onClicked");
            onPressed:  { console.log("_mouseFlickable.onPressed");
                clickPos  = Qt.point(mouse.x,mouse.y)
                _rect_select.x=clickPos.x; _rect_select.y=clickPos.y;
                _rect_select.width=0; _rect_select.height=0;
                _rect_select.visible=true;
            }
            onReleased: { console.log("_mouseFlickable.onReleased");
                _rect_select.visible=false;
            }
            onEntered:  console.log("_mouseFlickable.onEntered");
            onExited:   console.log("_mouseFlickable.onExited");
            onPositionChanged: {
                _rect_select.x=Math.min(mouse.x,clickPos.x)
                _rect_select.y=Math.min(mouse.y,clickPos.y)
                _rect_select.width=Math.abs(clickPos.x-mouse.x)
                _rect_select.height=Math.abs(clickPos.y-mouse.y)
            }
            Column {
                id: _сolumn
                anchors.verticalCenter: parent.verticalCenter
                anchors.horizontalCenter: parent.horizontalCenter
                scale: my_scale

                Row {
                    id: _rowUpper
                    MyElement {
                        id: element_1
                        selectionRectangle: _rect_select
                        number: 1
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_2
                        selectionRectangle: _rect_select
                        number: 2
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_3
                        selectionRectangle: _rect_select
                        number: 3
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_4
                        selectionRectangle: _rect_select
                        number: 4
                        height: 160
                        width:  160
                    }
                }
                Rectangle {
                    anchors.horizontalCenter:   parent.horizontalCenter
                    height:                     4
                    color:                      "lightsteelblue"
                    width:                      parent.width
                }
                Row {
                    id: _rowLower
                    MyElement {
                        id: element_5
                        selectionRectangle: _rect_select
                        number: 5
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_6
                        selectionRectangle: _rect_select
                        number: 6
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_7
                        selectionRectangle: _rect_select
                        number: 7
                        height: 160
                        width:  160
                    }
                    MyElement {
                        id: element_8
                        selectionRectangle: _rect_select
                        number: 8
                        height: 160
                        width:  160
                    }
                }
            }
        }
    }

    Rectangle {
        id: _rect_select
        visible: false
        color: "blue"
        opacity : 0.3
    }
}

import QtQuick 2.0

Item {
    id: _item
    property int number: 0
    property bool select: false
    property QtObject selectionRectangle

    MouseArea {
        id: _mouseArea
        anchors.fill: parent
        hoverEnabled: true      // это для работы функции containsMouse (наведение курсора мыши на область)
        propagateComposedEvents: true
        onClicked: { console.log("_mouse_" + number + ".onClicked");    mouse.accepted = false; }
        onPressed: { console.log("_mouse_" + number + ".onPressed");    mouse.accepted = false; }
        onReleased:{ console.log("_mouse_" + number + ".onReleased");   mouse.accepted = false; }
        onEntered: { console.log("_mouse_" + number + ".onEntered");  }
        onExited:  { console.log("_mouse_" + number + ".onExited");   }

        Rectangle {
            id: _rect
            anchors.fill: parent
            color:  "green"
            scale:  select ? 1.0 : _mouseArea.containsMouse ? 0.95 : 0.90

        }
    }

    Connections {
        target: selectionRectangle
        function onHeightChanged() {
            intersect(_rect, selectionRectangle)
        }
    }

    Connections {
        target: selectionRectangle
        function onWidthChanged() {
            intersect(_rect, selectionRectangle)
        }
    }


    function intersect(rect1, rect2) {
        var r1 = rect1.mapToItem(null, 0, 0, rect1.width, rect1.height)
        var r2 = rect2.mapToItem(null, 0, 0, rect2.width, rect2.height)

        var xOverlap = Math.min(r1.x + r1.width, r2.x + r2.width) - Math.max(r1.x, r2.x);
        var yOverlap = Math.min(r1.y + r1.height, r2.y + r2.height) - Math.max(r1.y, r2.y);

        if (xOverlap >= 0 && yOverlap >= 0) {
            _item.select = true
        } else {
            _item.select = false
        }
    }

}

    Коментарі

    Only authorized users can post comments.
    Please, Log in or Sign up