Вопрос:

Перетаскивание безрамочного окна "покачивания" в qml

c++ qt qml qtquick2

1060 просмотра

2 ответа

1509 Репутация автора

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

Я пытался улучшить его, но безуспешно.

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("WIP")
    id: mainWindow
    flags: Qt.SubWindow | Qt.Tool | Qt.FramelessWindowHint | Qt.WindowSystemMenuHint
    header: ToolBar{

        MouseArea{
            anchors.fill: parent
            onDoubleClicked: mainWindow.visibility!="2"?mainWindow.showNormal():mainWindow.showMaximized()
            id: maMainWindow
            property variant clickPos: "0,0"

            onPressed: {
                clickPos  = Qt.point(mouse.x,mouse.y)
            }

            onPositionChanged: {
                    var delta = Qt.point(mouse.x-clickPos.x, mouse.y-clickPos.y)
                    mainWindow.x += delta.x;
                    mainWindow.y += delta.y;
            }
        }
    }
}

Если я добавлю вкладки и некоторые элементы, это будет еще хуже.

Может ли C ++ улучшить производительность?

Автор: Abdelilah El Aissaoui Источник Размещён: 22.08.2016 09:15

Ответы (2)


1 плюс

36186 Репутация автора

Я не думаю, что есть что-то, что вы можете сделать, это просто побочный эффект использования привязок для построения графического интерфейса, и оценки привязок не синхронизируются с рендерингом. В результате, когда вы перемещаете или изменяете размер окна, все вокруг будет колебаться, как упругое, пока значение не «догонит». Это вещь QML, в виджетах вы не получаете такого поведения, потому что пользовательский интерфейс не построен на привязках. По сути, в оценке каждой цепочки привязок присутствует задержка, и, поскольку графический интерфейс пользователя рисует, он улавливает и отображает задержку распространения цепочки привязки, первые объекты из цепочки уже находятся в своих новых местоположениях, а другие к спине может быть позади на несколько шагов в распространении. И, естественно, то, имеет ли ваше окно рамки, совершенно не имеет отношения к этой проблеме.

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

Естественно, чем больше элементов у вас есть, тем дольше каждое изменение будет каскадно проходить через все из них, делая эффект более выраженным. Это также зависит от того, насколько быстро работает ваша система - так как это определяет задержку в оценке цепочки привязки, например, моя система работает быстро, а ваш пример кода не вызывает колебания. Однако, хотя понятно, что это происходит во время изменения размера, возникает вопрос, почему это происходит, когда вы просто перемещаете окно. В конце концов, это не должно изменять относительные позиции элементов пользовательского интерфейса в окне. Я подозреваю, что это происходит потому, что внутренне эти объекты рисуются в «абсолютном пространстве экрана», поэтому при перемещении окна это приводит к изменению фактических абсолютных положений каждого элемента, даже если они остаются в одном и том же месте относительно окна, в результате этого поведения. Не идеально ... Не только вводит это нежелательное визуальное поведение, но также и множество дополнительных оценок, которые кажутся ненужными накладными расходами.

Обратите внимание, что это всего лишь мои смутные подозрения, я подробно не исследовал этот вопрос, надеюсь, кто-то может предложить быстрый и простой способ справиться с этим. На данный момент я игнорирую эту проблему, надеясь, что это не будет слишком раздражающим, учитывая, что я сосредотачиваюсь на программном обеспечении, которое не связано с непрерывными изменениями положения и геометрии окна;) Кстати, хотя я впервые увидел это в QML, последние несколько лет я заметил это и в других «современных графических оболочках». Это было бы понятно, поскольку такие платформы переходят на медленные языки для быстрого прототипирования в сочетании с «плавным» асинхронным неблокирующим рендерингом.

Автор: dtech Размещён: 26.08.2016 01:26

8 плюса

311 Репутация автора

Решение

У меня была та же проблема, производительность была в порядке, но на Linux она прыгала по всему экрану и «шевелилась». Я решил это, написав вспомогательный класс на C ++, который я представил как свойство контекста QML. Это решение мне очень помогло. У меня очень сложный интерфейс, и он отлично работает, с очень хорошей производительностью. Итак, начнем. 1) Вам понадобится вспомогательный класс примерно так:

class CursorPosProvider : public QObject
{
    Q_OBJECT
public:
    explicit CursorPosProvider(QObject *parent = nullptr) : QObject(parent)
    {
    }
    virtual ~CursorPosProvider() = default;

    Q_INVOKABLE QPointF cursorPos()
    {
        return QCursor::pos();
    }
};

Это действительно простой класс, который просто предоставляет вам позицию курсора со стороны C ++, это странно, но когда вы делаете то же самое в QML, у вас возникают проблемы (по крайней мере, в Linux). 2) Выставить его как свойство контекста движку QML, я сделал это следующим образом:

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QQuickView view;

    CursorPosProvider mousePosProvider;

    view.rootContext()->setContextProperty("mousePosition", &mousePosProvider);

    view.setSource(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

3) Хорошо, теперь мы готовы перейти к части QML. У меня есть компонент Qt Quick, который реализует TitleBar для безрамного окна, например:

Rectangle {
    id: root
    width: parent.width
    color: "#0099d6" // just random one

    property QtObject container

    // extra properties, maybe some signals

    MouseArea {
        id: titleBarMouseRegion
        property var clickPos
        anchors.fill: parent
        onPressed: {
            clickPos = { x: mouse.x, y: mouse.y }
        }
        onPositionChanged: {
            container.x = mousePosition.cursorPos().x - clickPos.x
            container.y = mousePosition.cursorPos().y - clickPos.y
        }
    }
}

4) Теперь вы готовы использовать этот TitleBar в произвольном окне следующим образом:

Window {
    id: root
    visible: true

    flags: Qt.FramelessWindowHint

    TitleBar {
        height: 20
        container: root
    }

    Text {
        text: qsTr("Hello World")
        anchors.centerIn: parent
    }
}

Когда я реализовывал перетаскивание для строки заголовка, основная проблема заключалась в шнурах, которые предоставляет QML, это решение устраняет эту проблему. Пожалуйста, оставьте отзыв, если мое решение поможет вам. Мне действительно интересно :)

Автор: durkmurder Размещён: 01.09.2016 07:30
Вопросы из категории :
32x32