QML及VTK配合构建类MVVM模式DEMO

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.5

import VTKOBJ 9.2
import VTK 9.2

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    onWidthChanged: { console.log(width) }

    //---------------------------------------
    //ref动态绑定 由于iValue定义了通知动作;
    //一个改变 会通知另一个改变
    property string sstring: VtkObj.sString

    Text {
        id: txt
        text: sstring
    }

    Button {
        objectName: "myButton"
        width:100
        height:100
        y:100
        onClicked: {
            VtkObj.addMsg("ee")
            VtkObj.changeVtkItem( )
            console.log ( VtkObj.sString)
            console.log (txt.text)
            console.log (sstring)
        }
    }
    //---------------------------------------

    VTKRenderWindow{
        id: vtkRenWindow
        z: 10

        //注意这个objectName, 等会要用到!!!!! x1
        objectName: "vtkRenWin"

        width: parent.width * 0.9
        height: width
        anchors.centerIn: parent
    }

    VTKRenderItem{
        id: vtkRenItem
        z: 10

        //注意这个objectName, 等会要用到!!!!! x2
        objectName: "vtkRenItem"

        anchors.fill: vtkRenWindow
        renderWindow: vtkRenWindow
        focus: true
    }

}

效果

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值