1 创建QT QUICK项目
这次我们不在主程中加载VTK的几何;
在qml建立的控件,创建MyVtkObject类的单例,main中将指针和单例挂钩;
在MyVtkObject实例中操作 QQuickVTKRenderItem 类即可;
由于VTK的opengl显示是状态机,所以无需进行MVVM的通知动作(类MVVM模式);
这里再次采用按钮触发修改动作;
2 构建类 MyVtkObject
myvtkobject.h
#ifndef MYVTKOBJECT_H
#define MYVTKOBJECT_H#include <QObject>#include <QQuickVTKRenderWindow.h>
#include <QQuickVTKRenderItem.h>
#include <vtkPolyDataMapper.h>
#include <vtkCylinderSource.h>
#include <vtkCubeSource.h>class MyVtkObject : public QObject
{Q_OBJECT
public:explicit MyVtkObject(QObject *parent = nullptr);Q_INVOKABLE void initVtkView();Q_INVOKABLE QString addMsg(QString str);Q_INVOKABLE QString changeVtkItem( );void setRenderItem( QQuickVTKRenderItem* _item){this->m_vRenItem=_item ;};void setRenderWin(QQuickVTKRenderWindow* _win){this->m_vRenWin=_win ;}//单例static MyVtkObject* getInstance( ){static MyVtkObject* myobj = new MyVtkObject() ;return myobj;};const QString &sString() const;void setSString(const QString &newSString);private:QString m_sString="init";QQuickVTKRenderItem* m_vRenItem;QQuickVTKRenderWindow* m_vRenWin;Q_PROPERTY(QString sString READ sString WRITE setSString NOTIFY sStringChanged)signals:void sStringChanged();
};#endif // MYVTKOBJECT_H
myvtkobject.cpp
#include "myvtkobject.h"MyVtkObject::MyVtkObject(QObject *parent): QObject{parent}
{}void MyVtkObject::initVtkView()
{vtkNew<vtkCylinderSource> cylinder;cylinder->SetResolution(8);// The mapper is responsible for pushing the geometry into the graphics// library. It may also do color mapping, if scalars or other attributes are// defined.vtkNew<vtkPolyDataMapper> cylinderMapper;cylinderMapper->SetInputConnection(cylinder->GetOutputPort());// The actor is a grouping mechanism: besides the geometry (mapper), it// also has a property, transformation matrix, and/or texture map.// Here we set its color and rotate it around the X and Y axes.vtkSmartPointer<vtkActor> cylinderActor=vtkSmartPointer<vtkActor>::New();cylinderActor->SetMapper(cylinderMapper);// cylinderActor->GetProperty()->SetColor( colors->GetColor4d("Tomato").GetData());cylinderActor->RotateX(30.0);cylinderActor->RotateY(-45.0);auto main_render_3d = m_vRenItem->renderer();main_render_3d->AddActor(cylinderActor);main_render_3d->ResetCamera();// QQuickVTKRenderWindow* ren_win_3d = engine.rootObjects().first()
// ->findChild< QQuickVTKRenderWindow* >( "vtkRenWin" );m_vRenWin->render();}QString MyVtkObject::addMsg(QString str)
{setSString(sString()+ str + '#' ) ;// m_sString = str+"@";qDebug()<< __FUNCTION__ <<" === "<<str;return sString();
}QString MyVtkObject::changeVtkItem()
{vtkNew<vtkCylinderSource> cylinder;cylinder->SetResolution(8);vtkNew<vtkPolyDataMapper> cylinderMapper;cylinderMapper->SetInputConnection(cylinder->GetOutputPort());vtkSmartPointer<vtkActor> cylinderActor=vtkSmartPointer<vtkActor>::New();cylinderActor->SetMapper(cylinderMapper);cylinderActor->RotateX(-30.0);cylinderActor->RotateY(-95.0);// auto qquickvtkItem =m_vRenItem; // vtkSmartPointer<QQuickVTKRenderItem> ::New() ;auto main_render_3d = m_vRenItem->renderer();// main_render_3d->Clear();main_render_3d->AddActor(cylinderActor);main_render_3d->ResetCamera();vtkActorCollection* actors =main_render_3d->GetActors();qDebug()<< __FUNCTION__ <<" actors count: "<< actors->GetReferenceCount();return "OK";
}const QString &MyVtkObject::sString() const
{return m_sString;
}void MyVtkObject::setSString(const QString &newSString)
{if (m_sString == newSString)return;m_sString = newSString;emit sStringChanged();
}
3 主程中连接qml中vtk控件的指针
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>#include "myvtkobject.h"int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif//定义app之前调用一次,别问我为啥,问就是官方文档上写的,我也不知道QQuickVTKRenderWindow::setupGraphicsBackend();QGuiApplication app(argc, argv);QQmlApplicationEngine engine;//=====注册给qml=======qmlRegisterSingletonInstance("VTKOBJ",9,2,"VtkObj",MyVtkObject::getInstance());qmlRegisterType<QQuickVTKRenderWindow>("VTK", 9, 2, "VTKRenderWindow");qmlRegisterType<QQuickVTKRenderItem>("VTK", 9, 2, "VTKRenderItem");//====================const QUrl url(QStringLiteral("qrc:/main.qml"));QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,&app, [url](QObject *obj, const QUrl &objUrl) {if (!obj && url == objUrl)QCoreApplication::exit(-1);}, Qt::QueuedConnection);engine.load(url);//------------------------------------auto vtkItem = engine.rootObjects().first()->findChild< QQuickVTKRenderItem* >( "vtkRenItem" );auto vtkWin = engine.rootObjects().first()->findChild< QQuickVTKRenderWindow* >( "vtkRenWin" );MyVtkObject::getInstance()->setRenderItem(vtkItem);MyVtkObject::getInstance()->setRenderWin(vtkWin);MyVtkObject::getInstance()->initVtkView();//------------------------------------return app.exec();
}
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.5import VTKOBJ 9.2
import VTK 9.2Window {width: 640height: 480visible: truetitle: qsTr("Hello World")onWidthChanged: { console.log(width) }//---------------------------------------//ref动态绑定 由于iValue定义了通知动作;//一个改变 会通知另一个改变property string sstring: VtkObj.sStringText {id: txttext: sstring}Button {objectName: "myButton"width:100height:100y:100onClicked: {VtkObj.addMsg("ee")VtkObj.changeVtkItem( )console.log ( VtkObj.sString)console.log (txt.text)console.log (sstring)}}//---------------------------------------VTKRenderWindow{id: vtkRenWindowz: 10//注意这个objectName, 等会要用到!!!!! x1objectName: "vtkRenWin"width: parent.width * 0.9height: widthanchors.centerIn: parent}VTKRenderItem{id: vtkRenItemz: 10//注意这个objectName, 等会要用到!!!!! x2objectName: "vtkRenItem"anchors.fill: vtkRenWindowrenderWindow: vtkRenWindowfocus: true}}
效果