栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

BestMPRBaseVtk-11-Qt交互器QVTKInteractor

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

BestMPRBaseVtk-11-Qt交互器QVTKInteractor

BestMPRbaseVtk 交互

​ 这两天折腾了好几个交互方式,但是终究还是没有理解其中的奥,所以决定好好看看vtkQt 的交互。


文章目录
  • BestMPRbaseVtk 交互
    • 1 源码分析
    • 2 QVTKInteractor
    • 3 QVTKInteractor 源代码
      • QVTKInteractor.h
      • QVTKInteractor.cpp
    • ☞ 源码
    • 源码

关键字: QVTKInteractor、交互器、Qt、vtk、关键字5

1 源码分析
void QVTKOpenGLNativeWidget::setRenderWindow(vtkGenericOpenGLRenderWindow* win)
{
  if (this->RenderWindow == win)
  {
    return;
  }

  // this will release all OpenGL resources associated with the old render
  // window, if any.
  if (this->RenderWindowAdapter)
  {
    this->makeCurrent();
    this->RenderWindowAdapter.reset(nullptr);
  }
  this->RenderWindow = win;
  if (this->RenderWindow)
  {
    this->RenderWindow->SetReadyForRendering(false);

    // if an interactor wasn't provided, we'll make one by default
    if (!this->RenderWindow->GetInteractor())
    {
      // create a default interactor
      vtkNew iren;
      // iren->SetUseTDx(this->UseTDx);
      this->RenderWindow->SetInteractor(iren);
      iren->Initialize();

      // now set the default style
      vtkNew style;
      iren->SetInteractorStyle(style);
    }

    if (this->isValid())
    {
      // this typically means that the render window is being changed after the
      // QVTKOpenGLNativeWidget has initialized itself in a previous update
      // pass, so we emulate the steps to ensure that the new vtkRenderWindow is
      // brought to the same state (minus the actual render).
      this->makeCurrent();
      this->initializeGL();
      this->updateSize();
    }
  }
}

重点

 if (!this->RenderWindow->GetInteractor())
    {
      // create a default interactor
      vtkNew iren;
      // iren->SetUseTDx(this->UseTDx);
      this->RenderWindow->SetInteractor(iren);
      iren->Initialize();
      // now set the default style
      vtkNew style;
      iren->SetInteractorStyle(style);
    }

​ 翻译官方源码注释,这段代码意思就是创建一个默认的交互器QVTKInteractor类型的。并调用当前RenderWindow的SetInteractor()接口,把创建的QVTKInteractor类型的交互器传给RenderWindow,完成后交互器调用自己的Initialize()进行初始化。完后创建一个vtkInteractorStyleTrackballCamera类型的交互器样式,并将这个样式通过交互器的SetInteractorStyle()接口传输给交互器。

2 QVTKInteractor

​ 官网给的说明很少,只是说QVTKInteractor是QVTKOpenGLNativeWidget和(QVTKWiget)的交互器。将Qt 的事件中继到vtk中。

​ 从下图可以看出,QVTKInteractor是直接继承于vtkRenderWindowInteractor的一个分支,而 vtkRenderWindowInteractor是一个独立于平台的渲染窗口交互器,包括拾取和帧速率控制等。详细的后面再扒拉。今天重点还是研究QVTKInteractor.

3 QVTKInteractor 源代码

​ QVTKInteractor 源代码如下,大致看了一下,完全搞不懂事干啥,大致感觉就是分几个平台,来监听硬件信号。不过在代码里面我到时发现了一个能认识的东西QEvent,我们前面使用的wheelEvent时间就是继承他的。所以底层的原理应该一样的吧。

QVTKInteractor.h
#ifndef Q_VTK_INTERACTOR_H
#define Q_VTK_INTERACTOR_H

#include "QVTKWin32Header.h"
#include "vtkGUISupportQtModule.h" // For export macro
#include 
#include 
#include 

#include "vtkTDxConfigure.h" // defines VTK_USE_TDX
#if defined(VTK_USE_TDX) && defined(Q_OS_WIN)
class vtkTDxWinDevice;
#endif
#if defined(VTK_USE_TDX) && defined(Q_OS_MAC)
class vtkTDxMacDevice;
#endif
#if defined(VTK_USE_TDX) && (defined(Q_WS_X11) || defined(Q_OS_LINUX))
class vtkTDxDevice;
class vtkTDxUnixDevice;
#endif

class QVTKInteractorInternal;



class VTKGUISUPPORTQT_EXPORT QVTKInteractor : public vtkRenderWindowInteractor
{
public:
  static QVTKInteractor* New();
  vtkTypeMacro(QVTKInteractor, vtkRenderWindowInteractor);

  
  enum vtkCustomEvents
  {
    ContextMenuEvent = vtkCommand::UserEvent + 100,
    DragEnterEvent,
    DragMoveEvent,
    DragLeaveEvent,
    DropEvent
  };

  
  void TerminateApp() override;

  
  void Start() override;
  void Initialize() override;

  
  virtual void StartListening();

  
  virtual void StopListening();

  
  virtual void TimerEvent(int timerId);

#if defined(VTK_USE_TDX) && (defined(Q_WS_X11) || defined(Q_OS_LINUX))
  virtual vtkTDxUnixDevice* GetDevice();
  virtual void SetDevice(vtkTDxDevice* device);
#endif

protected:
  // constructor
  QVTKInteractor();
  // destructor
  ~QVTKInteractor() override;

  // create a Qt Timer
  int InternalCreateTimer(int timerId, int timerType, unsigned long duration) override;
  // destroy a Qt Timer
  int InternalDestroyTimer(int platformTimerId) override;
#if defined(VTK_USE_TDX) && defined(Q_OS_WIN)
  vtkTDxWinDevice* Device;
#endif
#if defined(VTK_USE_TDX) && defined(Q_OS_MAC)
  vtkTDxMacDevice* Device;
#endif
#if defined(VTK_USE_TDX) && (defined(Q_WS_X11) || defined(Q_OS_LINUX))
  vtkTDxUnixDevice* Device;
#endif

private:
  QVTKInteractorInternal* Internal;

  QVTKInteractor(const QVTKInteractor&) = delete;
  void operator=(const QVTKInteractor&) = delete;
};

#endif
QVTKInteractor.cpp
#ifdef _MSC_VER
// Disable warnings that Qt headers give.
#pragma warning(disable : 4127)
#pragma warning(disable : 4512)
#endif

#include "QVTKInteractor.h"
#include "QVTKInteractorInternal.h"

#if defined(VTK_USE_TDX) && defined(Q_OS_WIN)
#include "vtkTDxWinDevice.h"
#endif

#if defined(VTK_USE_TDX) && defined(Q_OS_MAC)
#include "vtkTDxMacDevice.h"
#endif

#if defined(VTK_USE_TDX) && (defined(Q_WS_X11) || defined(Q_OS_LINUX))
#include "vtkTDxUnixDevice.h"
#endif

#include 
#include 
#include 
#include 

#include "vtkCommand.h"
#include "vtkObjectFactory.h"
#include "vtkRenderWindow.h"

QVTKInteractorInternal::QVTKInteractorInternal(QVTKInteractor* p)
  : Parent(p)
{
  this->SignalMapper = new QSignalMapper(this);
  QObject::connect(this->SignalMapper, SIGNAL(mapped(int)), this, SLOT(TimerEvent(int)));
}

QVTKInteractorInternal::~QVTKInteractorInternal() {}

void QVTKInteractorInternal::TimerEvent(int id)
{
  Parent->TimerEvent(id);
}


vtkStandardNewMacro(QVTKInteractor);


QVTKInteractor::QVTKInteractor()
{
  this->Internal = new QVTKInteractorInternal(this);

#if defined(VTK_USE_TDX) && defined(Q_OS_WIN)
  this->Device = vtkTDxWinDevice::New();
#endif
#if defined(VTK_USE_TDX) && defined(Q_OS_MAC)
  this->Device = vtkTDxMacDevice::New();
#endif
#if defined(VTK_USE_TDX) && (defined(Q_WS_X11) || defined(Q_OS_LINUX))
  this->Device = 0;
#endif
}

void QVTKInteractor::Initialize()
{
#if defined(VTK_USE_TDX) && defined(Q_OS_WIN)
  if (this->UseTDx)
  {
    // this is QWidget::winId();
    HWND hWnd = static_cast(this->GetRenderWindow()->GetGenericWindowId());
    if (!this->Device->GetInitialized())
    {
      this->Device->SetInteractor(this);
      this->Device->SetWindowHandle(hWnd);
      this->Device->Initialize();
    }
  }
#endif
#if defined(VTK_USE_TDX) && defined(Q_OS_MAC)
  if (this->UseTDx)
  {
    if (!this->Device->GetInitialized())
    {
      this->Device->SetInteractor(this);
      // Do not initialize the device here.
    }
  }
#endif
  this->Initialized = 1;
  this->Enable();
}

#if defined(VTK_USE_TDX) && (defined(Q_WS_X11) || defined(Q_OS_LINUX))
// ----------------------------------------------------------------------------
vtkTDxUnixDevice* QVTKInteractor::GetDevice()
{
  return this->Device;
}

// ----------------------------------------------------------------------------
void QVTKInteractor::SetDevice(vtkTDxDevice* device)
{
  if (this->Device != device)
  {
    this->Device = static_cast(device);
  }
}
#endif


void QVTKInteractor::Start()
{
  vtkErrorMacro(<< "QVTKInteractor cannot control the event loop.");
}


void QVTKInteractor::TerminateApp()
{
  // we are in a GUI so let's terminate the GUI the normal way
  // qApp->exit();
}

// ----------------------------------------------------------------------------
void QVTKInteractor::StartListening()
{
#if defined(VTK_USE_TDX) && defined(Q_OS_WIN)
  if (this->Device->GetInitialized() && !this->Device->GetIsListening())
  {
    this->Device->StartListening();
  }
#endif
#if defined(VTK_USE_TDX) && defined(Q_OS_MAC)
  if (this->UseTDx && !this->Device->GetInitialized())
  {
    this->Device->Initialize();
  }
#endif
#if defined(VTK_USE_TDX) && (defined(Q_WS_X11) || defined(Q_OS_LINUX))
  if (this->UseTDx && this->Device != 0)
  {
    this->Device->SetInteractor(this);
  }
#endif
}

// ----------------------------------------------------------------------------
void QVTKInteractor::StopListening()
{
#if defined(VTK_USE_TDX) && defined(Q_OS_WIN)
  if (this->Device->GetInitialized() && this->Device->GetIsListening())
  {
    this->Device->StopListening();
  }
#endif
#if defined(VTK_USE_TDX) && defined(Q_OS_MAC)
  if (this->UseTDx && this->Device->GetInitialized())
  {
    this->Device->Close();
  }
#endif
#if defined(VTK_USE_TDX) && (defined(Q_WS_X11) || defined(Q_OS_LINUX))
  if (this->UseTDx && this->Device != 0)
  {
    // this assumes that a outfocus event is emitted prior
    // a infocus event on another widget.
    this->Device->SetInteractor(0);
  }
#endif
}


void QVTKInteractor::TimerEvent(int timerId)
{
  if (!this->GetEnabled())
  {
    return;
  }
  this->InvokeEvent(vtkCommand::TimerEvent, (void*)&timerId);

  if (this->IsoneShotTimer(timerId))
  {
    this->DestroyTimer(timerId); // 'cause our Qt timers are always repeating
  }
}


QVTKInteractor::~QVTKInteractor()
{
  delete this->Internal;
#if defined(VTK_USE_TDX) && defined(Q_OS_WIN)
  this->Device->Delete();
#endif
#if defined(VTK_USE_TDX) && defined(Q_OS_MAC)
  this->Device->Delete();
#endif
#if defined(VTK_USE_TDX) && (defined(Q_WS_X11) || defined(Q_OS_LINUX))
  this->Device = 0;
#endif
}


int QVTKInteractor::InternalCreateTimer(
  int timerId, int vtkNotUsed(timerType), unsigned long duration)
{
  QTimer* timer = new QTimer(this->Internal);
  timer->start(duration);
  this->Internal->SignalMapper->setMapping(timer, timerId);
  QObject::connect(timer, SIGNAL(timeout()), this->Internal->SignalMapper, SLOT(map()));
  int platformTimerId = timer->timerId();
  this->Internal->Timers.insert(
    QVTKInteractorInternal::TimerMap::value_type(platformTimerId, timer));
  return platformTimerId;
}


int QVTKInteractor::InternalDestroyTimer(int platformTimerId)
{
  QVTKInteractorInternal::TimerMap::iterator iter = this->Internal->Timers.find(platformTimerId);
  if (iter != this->Internal->Timers.end())
  {
    iter->second->stop();
    iter->second->deleteLater();
    this->Internal->Timers.erase(iter);
    return 1;
  }
  return 0;
}
☞ 源码

源码链接:GitHub仓库自取

使用方法:☟☟☟

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/689909.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号