Qt Quick parent,和parent的id不一样
Qt Quick parent, not the same as the id of the parent
我正在尝试 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;
}
现在这段代码完美运行,我 运行 应用程序,我可以单击标题栏并拖动,整个 window 移动到我想要的位置。
但问题是:如果我将 hostWidget: wnd
更改为 hostWidget: parent
,它将不再起作用。 谁能解释一下为什么?因为wnd
毕竟是parent
P.S.
我也从 Qt Creator
收到了这个非常奇怪的错误通知,但是代码编译并且 运行 没问题:
为什么?...
But here is the problem: if I change hostWidget: wnd
to hostWidget: parent
it doesn't work anymore. Can anyone explain why? Because wnd
is the parent
after all.
Window QML type instantiates QQuickWindow
.
QQuickWindow
does not inherit from QQuickItem
.
相反,它包含一个 QQuickItem
element accessible through its contentItem()
函数。
parent
属性 引用了一个 QQuickItem
对象。
因此在您的示例中 titleBar.parent
指的是 wnd
的元素而不是 wnd
本身。
如果在调用 MyCustomTitleBar::setHostWidget()
之前尝试在内部将 titleBar.parent
动态转换为 QWindow*
,则由于上面的 (2) 而失败(在这种情况下,您应该会看到相应的控制台错误)。
因为 titleBar.parent
不是 wnd
,而是 wnd.contentItem
。这就是为什么你发现它的 parent
不是 wnd
.
为什么 wnd.contentItem
而不是 wnd
?
一般来说,任何项目都会成为它包含的所有子项目的 parent
,但 Window
并非如此。
这里的问题是 parent
属性 的类型是 Item
。遗憾的是,Window
没有继承自 Item
。因此,一个 Window
应该包含一个真正的 Item
成为其所有 children 的 parent
。这就是 Window.contentItem
的用途。
我正在尝试 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;
}
现在这段代码完美运行,我 运行 应用程序,我可以单击标题栏并拖动,整个 window 移动到我想要的位置。
但问题是:如果我将 hostWidget: wnd
更改为 hostWidget: parent
,它将不再起作用。 谁能解释一下为什么?因为wnd
毕竟是parent
P.S.
我也从 Qt Creator
收到了这个非常奇怪的错误通知,但是代码编译并且 运行 没问题:
为什么?...
But here is the problem: if I change
hostWidget: wnd
tohostWidget: parent
it doesn't work anymore. Can anyone explain why? Becausewnd
is theparent
after all.
Window QML type instantiates
QQuickWindow
.QQuickWindow
does not inherit fromQQuickItem
.相反,它包含一个
QQuickItem
element accessible through itscontentItem()
函数。parent
属性 引用了一个QQuickItem
对象。
因此在您的示例中 titleBar.parent
指的是 wnd
的元素而不是 wnd
本身。
如果在调用 MyCustomTitleBar::setHostWidget()
之前尝试在内部将 titleBar.parent
动态转换为 QWindow*
,则由于上面的 (2) 而失败(在这种情况下,您应该会看到相应的控制台错误)。
因为 titleBar.parent
不是 wnd
,而是 wnd.contentItem
。这就是为什么你发现它的 parent
不是 wnd
.
为什么 wnd.contentItem
而不是 wnd
?
一般来说,任何项目都会成为它包含的所有子项目的 parent
,但 Window
并非如此。
这里的问题是 parent
属性 的类型是 Item
。遗憾的是,Window
没有继承自 Item
。因此,一个 Window
应该包含一个真正的 Item
成为其所有 children 的 parent
。这就是 Window.contentItem
的用途。