Qt 快速父级,与父级的“id”不同

问题描述 投票:0回答:2

我正在使用

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
收到了这个非常奇怪的错误通知,但代码编译并运行良好:

为什么?...

c++ qt qml qt5 qtquick2
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
它不再起作用了。
谁能解释为什么吗?因为
wnd
就是
parent
毕竟。

  1. Window QML 类型实例化

    QQuickWindow

  2. QQuickWindow
    不继承自
    QQuickItem

  3. 相反,它包含一个

    QQuickItem
    元素,可通过其
    contentItem()
    函数访问。

  4. parent
    属性指的是
    QQuickItem
    对象。

因此,在您的示例中,

titleBar.parent
指的是
wnd
的元素,而不是
wnd
本身。

如果在调用

titleBar.parent
之前在内部尝试将
QWindow*
动态转换为
MyCustomTitleBar::setHostWidget()
,则会因上述 (2) 原因而失败(在这种情况下,您应该在控制台中看到相应的错误)。

© www.soinside.com 2019 - 2024. All rights reserved.