由于我项目开始使用Widgets,换公司后直接使用QML开发,没有了解过如何实现widget到qml过渡,恰逢面试时遇到一家公司希望从widget迁移到qml开发,询问相关实现,一时语塞,很尴尬,粗略研究并总结下。
对qwidget嵌入qml的操作,qt提供了两种方式,(1) QQuickView 和 QWidget::createWindowContainer ()结合使用,但存在堆栈限制问题被放弃;(2) QQuickWidget,但是使用该种方式也存在如下问题需要注意;
对于qquickwidget,qt官方也提供了相应例子quickwidget,简单如下所示。
// main.cpp
MainWindow::MainWindow()
: m_quickWidget(new QQuickWidget)
{
...
QUrl source("qrc:quickwidget/rotatingsquare.qml");
connect(m_quickWidget, &QQuickWidget::statusChanged,
this, &MainWindow::quickWidgetStatusChanged);
connect(m_quickWidget, &QQuickWidget::sceneGraphError,
this, &MainWindow::sceneGraphError);
m_quickWidget->resize(300,300);
m_quickWidget->setResizeMode(QQuickWidget::SizeRootObjectToView );
m_quickWidget->setSource(source);
centralWidget->addSubWindow(m_quickWidget);
...
}
void MainWindow::quickWidgetStatusChanged(QQuickWidget::Status status)
{
if (status == QQuickWidget::Error) {
QStringList errors;
const auto widgetErrors = m_quickWidget->errors();
for (const QQmlError &error : widgetErrors)
errors.append(error.toString());
}
}
void MainWindow::grabToImage()
{
QFileDialog fd(this);
fd.setAcceptMode(QFileDialog::AcceptSave);
fd.setDefaultSuffix("png");
fd.selectFile("test_grabToImage.png");
if (fd.exec() == QDialog::Accepted) {
// 这里C++层使用invokeMethod调用rotatingsquare.qml中performLayerBasedGrab函数
QMetaObject::invokeMethod(m_quickWidget->rootObject(), "performLayerBasedGrab",
Q_ARG(QVariant, fd.selectedFiles().first()));
}
}
// rotatingsquare.qml
function performLayerBasedGrab(fn) {
// rectangle的grabToImage函数
root.grabToImage(function(result) {
result.saveToFile(fn);
});
}
对于网上反应的某些信号获取不到,测试后没发现问题,不知道是不是版本问题,我测试版本为Qt5.12.12
https://blog.csdn.net/u011283226/article/details/117398629