这两天折腾了好几个交互方式,但是终究还是没有理解其中的奥,所以决定好好看看vtkQt 的交互。
文章目录
- BestMPRbaseVtk 交互
- 1 源码分析
- 2 QVTKInteractor
- 3 QVTKInteractor 源代码
- QVTKInteractor.h
- QVTKInteractor.cpp
- ☞ 源码
- 源码
1 源码分析关键字: QVTKInteractor、交互器、Qt、vtk、关键字5
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 #includeQVTKInteractor.cpp#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
#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仓库自取
使用方法:☟☟☟



