将QGraphicsScene嵌入QML中
Embedding QGraphicsScene into QML
我正在用qt编写一张纸牌游戏。最初,UI是用QT小部件编写的,但是在移植到Android之后(Qt Widgets App看起来很尴尬,因为设置和颜色选择对话几乎是不可用的)C 。
但是,游戏逻辑的一部分不能与视觉渲染分开(例如,玩家将卡片放在桌子上)是在QGraphicsScene
衍生的类中写的:
class Table : public QGraphicsScene
{
// some code omitted
}
Table::Table(QObject* parent) : QGraphicsScene(parent) { /* ... */ }
我尝试通过qmlRegisterType()
将Table
注册为QML类型,但是对我不起作用 - 将Table
对象放入QML中会导致QGraphicsScene
构造函数中的segfault。这是回溯的一部分:
#0 0x19312fa4 in std::__atomic_base<int>::load (__m=std::memory_order_relaxed, this=0xabababab) at C:/MINGW530/i686-w64-mingw32/include/c++/bits/atomic_base.h:396
__b = std::memory_order_relaxed
#1 QAtomicOps<int>::load<int> (_q_value=...) at ../../include/QtCore/../../src/corelib/arch/qatomic_cxx11.h:227
No locals.
#2 0x193e1780 in QBasicAtomicInteger<int>::load (this=0xabababab) at ../../include/QtCore/../../src/corelib/thread/qbasicatomic.h:102
No locals.
#3 0x1940f7a7 in QtPrivate::RefCount::isShared (this=0xabababab) at ../../include/QtCore/../../src/corelib/tools/qrefcount.h:101
count = 571316634
#4 0x1937f29d in QList<QGraphicsScene*>::append (this=0x139914c, t=@0x112e8cc: 0x362be1a8) at ../../include/QtCore/../../src/corelib/tools/qlist.h:580
No locals.
#5 0x192a1188 in QGraphicsScenePrivate::init (this=0x362be258) at graphicsviewqgraphicsscene.cpp:334
q = 0x362be1a8
#6 0x192a61e9 in QGraphicsScene::QGraphicsScene (this=0x362be1a8, parent=0x0) at graphicsviewqgraphicsscene.cpp:1636
No locals.
#7 0x00402f53 in Table::Table (this=0x362be1a8, parent=0x0) at ..OpenFoolsrctable.cpp:41
No locals.
#8 0x0041239a in QQmlPrivate::QQmlElement<Table>::QQmlElement (this=0x362be1a8) at J:/Qt/Qt5.8.0/5.8/mingw53_32/include/QtQml/qqmlprivate.h:99
No locals.
#9 0x0041235d in QQmlPrivate::createInto<Table> (memory=0x362be1a8) at J:/Qt/Qt5.8.0/5.8/mingw53_32/include/QtQml/qqmlprivate.h:108
No locals.
#10 0x01c7a5d5 in QQmlType::create (this=0x1398550, out=0x112ed70, memory=0x112ed4c, additionalMemory=72) at qmlqqmlmetatype.cpp:761
rv = 0x362be1a8
那么,有没有办法重复使用Table
的代码,而无需重新编写QML?
据我所知,QTwidget和QML的渲染引擎从根本上有所不同,因此很难将Widget
注册为QML Type
。
所以我认为您的两个最佳选择是:
- 将其改编为QML
- 将
QQuickPaintedItem
扩展到与QGraphicsScene
最相似的API,因此您在代码上需要的更改仅是最小的。(*谢谢, @benjamint 将我指向QQuickPaintedItem
而不是Context2D
)
据我所知,您不能将 QWidget
嵌入qt quick 2元素中,但是,如果您可以使用QT Quick 1,则可以使用自定义QDeclarativeItem
和QGraphicsProxyWidget
。
用自定义QPushButton
的示例:
#include <QtDeclarative>
#include <QtGui>
class PushButtonItem : public QDeclarativeItem {
Q_OBJECT
public:
PushButtonItem(QDeclarativeItem *parent =0) : QDeclarativeItem(parent) {
pb = new QPushButton("text");
proxy = new QGraphicsProxyWidget(this);
proxy->setWidget(pb);
proxy->setPos(-pb->sizeHint().width()/2, -pb->sizeHint().height()/2);
}
private:
QPushButton *pb;
QGraphicsProxyWidget *proxy;
};
#include "main.moc"
int main(int argc, char **argv) {
QApplication app(argc, argv);
QDeclarativeView view;
qmlRegisterType<PushButtonItem>("PushButton", 1, 0, "PushButtonItem");
view.setSource(QUrl::fromLocalFile("file.qml"));
view.show();
return app.exec();
};
在您的情况下,您甚至可以直接用QGraphicsScene
替换QGraphicsProxyWidget
,因为QGraphicsScene
是QT Quick 1中的基类(在QT Quick 2中替换为2)。
您需要一个QGraphicsView
窗口小部件才能显示QGraphicsScene
。但是,您不能将小部件嵌入QT Quick 2接口中。(如果您使用QT Quick 1请参阅@xander答案)。
但是,如果您以相反的方式处理问题,请有一个解决方案。您可以制作QT小部件HMI,在Qgraphicsview小部件中显示您的场景,并使用一个或多个Qquickwidget显示QT快速部分。这有一些局限性,但是如果您不重叠QTquick和Qtwidget零件,则可以很好地工作,并且可以非常有效
- 从C++实例化QML
- 使用CMake创建QML插件
- 嵌入方指针压缩已禁用
- QT通过C++添加映射QML项目
- 在静态库中嵌入类方法
- 如何在没有信号的情况下从C++执行QML插槽
- QML按钮点击功能执行顺序
- 在没有Xcode的情况下在Mac捆绑包中嵌入框架
- QML:修改在不同QML文件(而非main.QML)中定义的子对象的属性
- 建议在运行时将带有类实例的列表从c++导入qml
- Qt Quick-如何仅从c++代码与qml属性交互
- 用Visual Studio在C++中嵌入Julia
- 如何将带有自定义对象的容器从C++传递到QML
- 是否可以为 QPixmap 派生类嵌入缩放方法?
- SetDlgItemInt 不会更改嵌入资源的编辑框
- QML 使用带有参数C++函数
- 最佳做法是从另一个线程访问 qml 中的Q_PROPERTY
- Qt Qml,在iOS上将map(OSM Mapbox Mapboxgl)嵌入到QQuickWidget C++对象中
- 将QGraphicsScene嵌入QML中
- 如何将本机窗口嵌入到 QML 组件中