Qt Quick中的父对象与父对象的ID不同。

3

我正在使用Qt Quick进行一些实验,希望为我的应用程序创建一个标题栏。因此,我继承了QQuickPaintedItem,在其上绘制了一些内容,并希望将其用作Window的标题栏。我使用的是Qt 5.7。这样做成功了,但只有在一定程度上...代码后面我会解释更多;以下是我的方法:

main.cpp

#include <QGuiApplication>
#include <QQmlApplicationEngine>

#include "mycustomtitlebar.h"

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

    qmlRegisterType<MyCustomTitleBar>("my.custom.lib", 1, 0, "MyCustomTitleBar");

    QQmlApplicationEngine engine;
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    return app.exec();
}

main.qml

import QtQuick 2.7
import QtQuick.Window 2.2
import my.custom.lib 1.0

Window {
    id: wnd
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    MyCustomTitleBar {
        id: titleBar
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.right: parent.right
        height: 100
        hostWidget: wnd
    }

    Rectangle {
        color: "beige"
        anchors.top: titleBar.bottom
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
    }
}

mycustomtitlebar.h

#ifndef MYCUSTOMTITLEBAR_H
#define MYCUSTOMTITLEBAR_H

#include <QQuickPaintedItem>
#include <QPoint>

class MyCustomTitleBar : public QQuickPaintedItem
{
    Q_OBJECT

    Q_PROPERTY(QWindow *hostWidget READ hostWidget WRITE setHostWidget)

public:
    MyCustomTitleBar(QQuickItem *parent = 0);

protected:
    virtual void paint(QPainter *pPainter) Q_DECL_OVERRIDE;
    virtual void mousePressEvent(QMouseEvent *pEvent) Q_DECL_OVERRIDE;
    virtual void mouseMoveEvent(QMouseEvent *pEvent) Q_DECL_OVERRIDE;
    virtual void mouseReleaseEvent(QMouseEvent *pEvent) Q_DECL_OVERRIDE;

private:
    QWindow *hostWidget() const;
    void setHostWidget(QWindow *pHostWidget);

private:
    QWindow *m_pHostWidget;
    QPoint m_initialMousePosition;
    bool m_leftMouseButtonPressed;
};

#endif // MYCUSTOMTITLEBAR_H

mycustomtitlebar.cpp

#include "mycustomtitlebar.h"

#include <QPainter>
#include <QDragMoveEvent>
#include <QWindow>

MyCustomTitleBar::MyCustomTitleBar(QQuickItem *parent)
    : QQuickPaintedItem(parent),
      m_leftMouseButtonPressed(false),
      m_pHostWidget(Q_NULLPTR)
{
    setAcceptedMouseButtons(Qt::AllButtons);
}

void MyCustomTitleBar::paint(QPainter *pPainter)
{
    // Dummy drawing...
    const QRect myRect(10, 10, width() - 20, height() - 20);
    qDebug() << myRect;
    pPainter->drawRect(myRect);
}

void MyCustomTitleBar::mousePressEvent(QMouseEvent *pEvent)
{
    m_leftMouseButtonPressed = true;
    m_initialMousePosition = pEvent->pos();
}

void MyCustomTitleBar::mouseMoveEvent(QMouseEvent *pEvent)
{
    if (m_leftMouseButtonPressed) {
        if (!m_pHostWidget) {
            qDebug() << Q_FUNC_INFO << "Host widget not set. Please set host widget";
            return;
        }

        const QPoint newMousePosition = pEvent->pos() - m_initialMousePosition + m_pHostWidget->position();
        m_pHostWidget->setPosition(newMousePosition);
    }

    QQuickPaintedItem::mouseMoveEvent(pEvent);
}

void MyCustomTitleBar::mouseReleaseEvent(QMouseEvent *pEvent)
{
    m_leftMouseButtonPressed = false;
}

QWindow *MyCustomTitleBar::hostWidget() const
{
    return m_pHostWidget;
}

void MyCustomTitleBar::setHostWidget(QWindow *pHostWidget)
{
    m_pHostWidget = pHostWidget;
}

现在这段代码很完美,我运行应用程序后,可以点击标题栏并拖动,整个窗口会移动到我想要的位置。
但是问题在于:如果我将`hostWidget:wnd`更改为`hostWidget:parent`,它就不再起作用了。有人能解释为什么吗?毕竟,`wnd`本来就是`parent`。
附言:
我还从Qt Creator中获得了这个非常奇怪的错误通知,但代码编译和运行都很好: enter image description here
为什么?...

1
可能是重复的问题:https://dev59.com/Lpnga4cB1Zd3GeqPVTeG - selbie
2个回答

2
因���titleBar.parent不是wnd,而是wnd.contentItem。这就是为什么你发现它的parent不是wnd的原因。 为什么是wnd.contentItem而不是wnd 通常,任何项都将成为其包含的所有子项的parent,但这不适用于Window
问题在于parent属性的类型是Item。不幸的是,Window没有继承自Item。因此,Window应该包含一个真正的Item作为其所有子项的parent。这就是Window.contentItem的用途。

1
但是这里的问题在于:如果我将 hostWidget: wnd 改为 hostWidget: parent ,它就不再起作用了。有人能解释一下吗?因为毕竟 wndparent
  1. Window QML类型 实例化 QQuickWindow

  2. QQuickWindow 不继承自 QQuickItem

  3. 相反,它包含一个通过其 contentItem() 函数访问的 QQuickItem 元素。

  4. parent 属性引用一个 QQuickItem 对象。

因此,在你的例子中,titleBar.parent 指的是 wnd 的一个元素,而不是 wnd 本身。
如果在调用 MyCustomTitleBar::setHostWidget() 前尝试将 titleBar.parent 动态转换为 QWindow*,由于上述情况(2),会失败(在这种情况下,您应该在控制台中看到相应的错误)。

你好,感谢回答!我已经尝试过了,但是行为是这样的:http://im2.ezgif.com/tmp/ezgif-1248938156.gif。这也很奇怪。这意味着`parent`不完全是窗口...我不知道它在底层是如何构建的。 - Jacob Krieg
@JacobKrieg 我查阅了Qt文档并修改了我的答案。 - Leon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接