BestMPRBaseVtk-11-Qt交互器QVTKInteractor

Posted DreamLife.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BestMPRBaseVtk-11-Qt交互器QVTKInteractor相关的知识,希望对你有一定的参考价值。

BestMPRBaseVtk 交互

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


关键字: QVTKInteractor交互器Qtvtk关键字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<QVTKInteractor> iren;
      // iren->SetUseTDx(this->UseTDx);
      this->RenderWindow->SetInteractor(iren);
      iren->Initialize();

      // now set the default style
      vtkNew<vtkInteractorStyleTrackballCamera> 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<QVTKInteractor> iren;
      // iren->SetUseTDx(this->UseTDx);
      this->RenderWindow->SetInteractor(iren);
      iren->Initialize();
      // now set the default style
      vtkNew<vtkInteractorStyleTrackballCamera> style;
      iren->SetInteractorStyle(style);
    

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

2 QVTKInteractor

​ 官网给的说明很少,只是说QVTKInteractorQVTKOpenGLNativeWidget和(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 <QtCore/QObject>
#include <vtkCommand.h>
#include <vtkRenderWindowInteractor.h>

#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 QVTKInteractor
 * @brief - an interactor for QVTKOpenGLNativeWidget (and QVTKWiget).
 *
 * QVTKInteractor handles relaying Qt events to VTK.
 * @sa QVTKOpenGLNativeWidget
 */

class VTKGUISUPPORTQT_EXPORT QVTKInteractor : public vtkRenderWindowInteractor

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

  /**
   * Enum for additional event types supported.
   * These events can be picked up by command observers on the interactor.
   */
  enum vtkCustomEvents
  
    ContextMenuEvent = vtkCommand::UserEvent + 100,
    DragEnterEvent,
    DragMoveEvent,
    DragLeaveEvent,
    DropEvent
  ;

  /**
   * Overloaded terminate app, which does nothing in Qt.
   * Use qApp->exit() instead.
   */
  void TerminateApp() override;

  /**
   * Overloaded start method does nothing.
   * Use qApp->exec() instead.
   */
  void Start() override;
  void Initialize() override;

  /**
   * Start listening events on 3DConnexion device.
   */
  virtual void StartListening();

  /**
   * Stop listening events on 3DConnexion device.
   */
  virtual void StopListening();

  /**
   * timer event slot
   */
  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 <QEvent>
#include <QResizeEvent>
#include <QSignalMapper>
#include <QTimer>

#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);


/*! allocation method for Qt/VTK interactor
 */
vtkStandardNewMacro(QVTKInteractor);

/*! constructor for Qt/VTK interactor
 */
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<HWND>(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<vtkTDxUnixDevice*>(device);
  

#endif

/*! start method for interactor
 */
void QVTKInteractor::Start()

  vtkErrorMacro(<< "QVTKInteractor cannot control the event loop.");


/*! terminate the application
 */
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


/*! handle timer event
 */
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
  


/*! constructor
 */
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


/*! create Qt timer with an interval of 10 msec.
 */
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;


/*! destroy timer
 */
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仓库自取

使用方法:☟☟☟

以上是关于BestMPRBaseVtk-11-Qt交互器QVTKInteractor的主要内容,如果未能解决你的问题,请参考以下文章

ionic (webApp)软qv键盘打开时视口高度变小导致样式问题的解决方案

在树莓派上原生构建 qt5.7.1 得到错误:/usr/lib/arm-linux-gnueabihf/libQt5Quick.so.5: 未定义对 `QV8Engine::toVariant 的引用

Android MVP:啥是交互器?

在身份检查器、属性检查器中启用用户交互?

BestMPRBaseVtk-012-vtk交互器vtkRenderWindowInteractor

BestMPRBaseVtk-012-vtk交互器vtkRenderWindowInteractor