VTK(2)—— 雙view,顯示並聯動操作
前言:接到一個新的需求
window單視窗程式,雙view,顯示並聯動操作,做了兩種方式進行實現,程式碼思路和原始碼如下:
(一)程式碼思路
一、判定誰動了?
方法1:通過當前事件的視窗位置與視窗大小中心軸進行比對
方法2:通過移動後的相機位置與兩個view中相機的位置進行比對
方法3:獲取當前renderer, 與兩個renderer 做對比
二、如何捕獲事件?
方法1:繼承自vtkCommand重寫回調
Step1: 定義回撥函式,繼承自vtkCommand
Step2: 設定回撥函式
Step3: 為兩個view的相機新增觀察者,通過AddObserver(vtkCommand::ModifiedEvent,callback)
(其中ModifiedEvent可以接收任意發生事件,
當有事件產生時,interactor底層會呼叫ModifiedEvent事件,callback為step1自定義的回撥函式)
方法2:vtkInteractorStyleTrackballCamera 重寫響應事件
Step1: 自定義互動型別,繼承自vtkInteractorStyleTrackballCamera
Step2: 重寫OnMouseMove()等方法
三、如何根據一個view變化設定另一個view?
方法1:將要設定的view中的相機的狀態設定為變化的相機狀態
(因為在vtk中影象變化預設採用的是相機移動方式,在此先不討論actor變化方式)
(注:vtk中的相機,主要由三個因素決定:1.焦點 2.相機位置 3.向上方向)(另外也可以通過直接獲取相機來設定想讓變化的相機狀態)
Step1: 獲取改變的相機的狀態,通過GetPosition(), GetFocalPoint(), GetViewUp() 進行獲得
Step2: 設定要改變的相機的狀態,通過SetPosition(), SetFocalPoint(), SetViewUp() 進行設定
Step3: 使用vtkRenderer的ResetCameraClippingRange()方法重置影象的法向量
Step4: 如果訊號沒有進行同步,需要手動呼叫vtkRendererWindow的Render()方法
方法2:建立一個相機物件,給左右兩個renderer新增同一個相機物件
方法3:通過獲取當前相機,將兩個renderer的相機設定為當前相機
四、同類型問題思考?
一個view中,兩個actor,根據滑鼠指向不同,可挪動不同的物體。(這個實現起來相對簡單一點,vtk有現成的函式)
方法:使用 vtkInteractorStyleTrackballActor 的互動模式即可實現
(二)Demo原始碼
第1種實現方式:
方法說明:
- 實現方式:繼承自vtkCommand重寫回調
- 相機設定:兩個 renderer 公用一個相機(注:當不使用一個 camera 設定兩個 renderer 的時候,如果viewsation不是對稱的 會出現互動最開始兩個相機相對物體的位置進行同步)
- 聯動函式:通過判斷當前相機 與左右兩個相機比對判定哪邊動了,包含兩種判斷方法
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkCallbackCommand.h>
#include <vtkTransform.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCamera.h>
#include <QDateTime>
class myCallbackFunc:public vtkCommand
{
public:
static myCallbackFunc *New()
{
return new myCallbackFunc;
}
void SetLeftRender(vtkRenderer *leftRender)
{
this->m_leftRender = leftRender;
}
void SetRightRender(vtkRenderer *rightRender)
{
this->m_rightRender = rightRender;
}
virtual void Execute(vtkObject *caller, unsigned long eventId, void* callData)
{
vtkCamera *camera = reinterpret_cast<vtkCamera*>(caller);
vtkCamera *leftCamera = m_leftRender->GetActiveCamera();
vtkCamera *rightCamera = m_rightRender->GetActiveCamera();
double *act_position = camera->GetPosition();
double *act_FocalPoint = camera->GetFocalPoint();
double *act_ViewUp = camera->GetViewUp();
//方法一:指標判斷
if (leftCamera == camera)
{
if (rightCamera->GetPosition() != act_position)
{
rightCamera->SetPosition(act_position);
}
if (rightCamera->GetViewUp() != act_ViewUp)
{
rightCamera->SetFocalPoint(act_FocalPoint);
}
if (rightCamera->GetViewUp() != act_ViewUp)
{
rightCamera->SetViewUp(act_ViewUp);
}
}
else if (rightCamera == camera)
{
if (leftCamera->GetPosition() != act_position)
{
leftCamera->SetPosition(act_position);
}
if (leftCamera->GetViewUp() != act_ViewUp)
{
leftCamera->SetFocalPoint(act_FocalPoint);
}
if (leftCamera->GetViewUp() != act_ViewUp)
{
leftCamera->SetViewUp(act_ViewUp);
}
}
//方法二:camera具體細節判斷
// if ( (isSame(act_position, leftCamera->GetPosition()))
// &&(isSame(act_FocalPoint, leftCamera->GetFocalPoint()))
// &&(isSame(act_ViewUp,leftCamera->GetViewUp())))
// {
// rightCamera->SetPosition(act_position);
// rightCamera->SetFocalPoint(act_FocalPoint);
// rightCamera->SetViewUp(act_ViewUp);
// this->m_rightRender->ResetCameraClippingRange();
// }
// else
// {
// leftCamera->SetPosition(act_position);
// leftCamera->SetFocalPoint(act_FocalPoint);
// leftCamera->SetViewUp(act_ViewUp);
// this->m_leftRender->ResetCameraClippingRange();
// }
}
//private:
// //計算獲取到的相機是否為leftRender或rightRender的相機
// static bool isSame(double *value0, double *value1) {
// bool result = true;
// for (int idx = 0; idx != 3; ++idx) {
// result = result && qFuzzyCompare(value0[idx], value1[idx]);
// }
// return result;
// }
private:
//此處為雙view,若為多view,可設定陣列,通過提供引數進行設定
vtkRenderer *m_leftRender;
vtkRenderer *m_rightRender;
};
int main(int, char *[])
{
vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkActor> actor1 = vtkSmartPointer<vtkActor>::New();
vtkSmartPointer<vtkActor> actor2 = vtkSmartPointer<vtkActor>::New();
vtkSmartPointer<vtkRenderer> leftRender = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderer> rightRender = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renwindow = vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<myCallbackFunc> callback = vtkSmartPointer<myCallbackFunc>::New();
vtkSmartPointer<vtkInteractorStyleTrackballCamera> style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
cube->SetCenter(1, 1, 1);
cube->Update();
mapper->SetInputConnection(cube->GetOutputPort());
actor1->SetMapper(mapper);
actor1->GetProperty()->SetColor(.2, .3, .4);
actor2->SetMapper(mapper);
actor2->GetProperty()->SetColor(.4, .5, .6);
double leftViewStation[4] = {0.0, 0.0, 0.4, 1.0};
double rightViewStation[4] = {0.4, 0.0, 1.0, 1.0};
leftRender->AddActor(actor1);
leftRender->SetBackground(.6, .5, .4);
leftRender->SetViewport(leftViewStation);
rightRender->AddActor(actor2);
rightRender->SetBackground(.2, .4, .6);
rightRender->SetViewport(rightViewStation);
camera->SetPosition(4, 4, 4);
rightRender->SetActiveCamera(camera);
leftRender->SetActiveCamera(camera);
renwindow->AddRenderer(leftRender);
renwindow->AddRenderer(rightRender);
renwindow->SetSize(600, 300);
renwindow->Render();
callback->SetLeftRender(leftRender);
callback->SetRightRender(rightRender);
leftRender->GetActiveCamera()->AddObserver(vtkCommand::ModifiedEvent,callback);
rightRender->GetActiveCamera()->AddObserver(vtkCommand::ModifiedEvent,callback);
interactor->SetInteractorStyle(style);//使用者通過控制相機對物體旋轉、放大、縮小等操作。
renwindow->SetInteractor(interactor);
interactor->Initialize();
interactor->Start();
return EXIT_SUCCESS;
}
(棧溢位問題已解決)
第2種實現方式:
方法說明:
- 實現方式:繼承自:vtkInteractorStyleTrackballCamera,過載 Rotate()
- 相機設定:兩個 renderer 公用一個相機(注:當不使用一個 camera 設定兩個 renderer 的時候,如果viewsation不是對稱的 會出現互動最開始兩個相機相對物體的位置進行同步)
- 聯動函式:包含兩種方法 ①通過事件所在視窗位置判斷哪個 render 動 ②獲取當前相機,將兩個相機重置為這個相機的狀態
#include <vtkSmartPointer.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkCallbackCommand.h>
#include <vtkTransform.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCamera.h>
#include <QDateTime>
class myInteractorStyle:public vtkInteractorStyleTrackballCamera
{
public:
static myInteractorStyle* New()
{
return new myInteractorStyle;
}
void SetLeftRender(vtkRenderer *render)
{
this->m_leftRender = render;
}
void SetRightRender(vtkRenderer *render)
{
this->m_rightRender = render;
}
void Rotate()
{
vtkInteractorStyleTrackballCamera::Rotate();
this->CameraSynchronous();
}
//**************** 方法一: 通過事件所在視窗位置判斷哪個 render 動 ************//
void CameraSynchronous()
{
vtkCamera *leftCamera = m_leftRender->GetActiveCamera();
vtkCamera *rightCamera = m_rightRender->GetActiveCamera();
//獲取視窗大小
int *winSize = this->GetInteractor()->GetRenderWindow()->GetSize();
//獲取事件視窗位置
int eventStation[3];
this->GetInteractor()->GetEventPosition(eventStation);
if (eventStation[0] < winSize[0]/2)
{
rightCamera->SetPosition(leftCamera->GetPosition());
rightCamera->SetFocalPoint(leftCamera->GetFocalPoint());
rightCamera->SetViewUp(leftCamera->GetViewUp());
m_rightRender->ResetCameraClippingRange();
}
else
{
leftCamera->SetPosition(rightCamera->GetPosition());
leftCamera->SetViewUp(rightCamera->GetViewUp());
leftCamera->SetFocalPoint(rightCamera->GetFocalPoint());
m_leftRender->ResetCameraClippingRange();
}
this->GetInteractor()->GetRenderWindow()->Render();
}
//**************** 方法二: 獲取當前相機,將兩個相機重置為這個相機的狀態 ************//
// void CameraSynchronous()
// {
// vtkCamera *camera = this->GetCurrentRenderer()->GetActiveCamera();
// this->m_leftRender->SetActiveCamera(camera);
// this->m_rightRender->SetActiveCamera(camera);
// }
private:
vtkRenderer *m_leftRender;
vtkRenderer *m_rightRender;
};
int main(int, char *[])
{
vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
vtkSmartPointer<vtkActor> actor1 = vtkSmartPointer<vtkActor>::New();
vtkSmartPointer<vtkActor> actor2 = vtkSmartPointer<vtkActor>::New();
vtkSmartPointer<vtkRenderer> leftRender = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderer> rightRender = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
vtkSmartPointer<vtkRenderWindow> renwindow = vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
vtkSmartPointer<myInteractorStyle> style = vtkSmartPointer<myInteractorStyle>::New();
cube->SetXLength(1);
cube->SetYLength(1);
cube->SetZLength(1);
cube->Update();
mapper->SetInputConnection(cube->GetOutputPort());
actor1->SetMapper(mapper);
actor1->GetProperty()->SetColor(.2, .3, .4);
actor2->SetMapper(mapper);
actor2->GetProperty()->SetColor(.4, .5, .6);
double leftViewStation[4] = {0.0, 0.0, 0.4, 1.0};
double rightViewStation[4] = {0.4, 0.0, 1.0, 1.0};
leftRender->AddActor(actor1);
leftRender->SetBackground(.6, .5, .4);
leftRender->SetViewport(leftViewStation);
rightRender->AddActor(actor2);
rightRender->SetBackground(.2, .4, .6);
rightRender->SetViewport(rightViewStation);
camera->SetPosition(4, 4, 4);
rightRender->SetActiveCamera(camera);
leftRender->SetActiveCamera(camera);
renwindow->AddRenderer(leftRender);
renwindow->AddRenderer(rightRender);
renwindow->SetSize(600, 300);
renwindow->Render();
style->SetLeftRender(leftRender);
style->SetRightRender(rightRender);
interactor->SetInteractorStyle(style);
renwindow->SetInteractor(interactor);
interactor->Initialize();
interactor->Start();
return EXIT_SUCCESS;
}
(三)完整原始碼(工程中使用)
功能說明:
1. 一個視窗中有4個view,實現兩兩聯動
2. 繼承自 vtkInteractorStyleTrackballCamera , 重寫了 Rotate() 方法
3. 作為介面,提供了增加聯動,刪除聯動的功能
4. 注:下面兩個不聯動是通過刪除方法,刪掉了聯動
原始碼如下:
#include <vtkSmartPointer.h>
#include <vtkCubeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkCallbackCommand.h>
#include <vtkTransform.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCamera.h>
#include <vector>
#include <QMap>
#define vSP vtkSmartPointer
typedef QMap<vSP<vtkRenderer>, vSP<vtkRenderer>> RenderMap;
class myInteractorStyle:public vtkInteractorStyleTrackballCamera
{
public:
static myInteractorStyle* New()
{
return new myInteractorStyle;
}
void SetRenderPair(vSP<vtkRenderer> render1, vSP<vtkRenderer> render2)
{
do
{
if (render1 == nullptr)
{
break;
}
if (render2 == nullptr)
{
break;
}
this->m_renderMap[render1] = render2;
this->m_renderMap[render2] = render1;
}while(false);
}
void RemoveRenderPair(vSP<vtkRenderer> render1, vSP<vtkRenderer> render2)
{
do
{
if (!this->m_renderMap.contains(render1))
{
break;
}
if (!this->m_renderMap.contains(render2))
{
break;
}
if (render1 != this->m_renderMap.value(render2, nullptr))
{
break;
}
if (render1 == nullptr)
{
break;
}
if (render2 == nullptr)
{
break;
}
this->m_renderMap.remove(render1);
this->m_renderMap.remove(render2);
}while(false);
}
void Rotate()
{
vtkInteractorStyleTrackballCamera::Rotate();
this->CameraSynchronous();
}
public:
void CameraSynchronous()
{
vSP<vtkRenderer> curRender = this->GetCurrentRenderer();
vSP<vtkCamera> curCamera = curRender->GetActiveCamera();
if (this->m_renderMap.contains(curRender))
{
vSP<vtkRenderer> linkRender = this->m_renderMap.value(curRender, nullptr);
if (linkRender != nullptr)
{
linkRender->SetActiveCamera(curCamera);
}
}
}
private:
RenderMap m_renderMap;
};
class Client
{
public:
Client()
{
this->Init();
this->setCube();
this->setMapper();
this->setActor();
this->setRender();
this->setRenderWindow();
this->setStyle();
this->setInteractor();
this->start();
}
void Init()
{
this->m_cube = vtkSmartPointer<vtkCubeSource>::New();
this->m_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
this->m_actor1 = vtkSmartPointer<vtkActor>::New();
this->m_actor2 = vtkSmartPointer<vtkActor>::New();
this->m_leftRender = vtkSmartPointer<vtkRenderer>::New();
this->m_rightRender = vtkSmartPointer<vtkRenderer>::New();
this->m_leftRender2 = vtkSmartPointer<vtkRenderer>::New();
this->m_rightRender2 = vtkSmartPointer<vtkRenderer>::New();
this->m_renwindow = vtkSmartPointer<vtkRenderWindow>::New();
this->m_interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
this->m_style = vtkSmartPointer<myInteractorStyle>::New();
}
void setCube()
{
m_cube->SetXLength(1);
m_cube->SetYLength(1);
m_cube->SetZLength(1);
m_cube->Update();
}
void setMapper()
{
m_mapper->SetInputConnection(m_cube->GetOutputPort());
}
void setActor()
{
m_actor1->SetMapper(m_mapper);
m_actor1->GetProperty()->SetColor(.2, .3, .4);
m_actor2->SetMapper(m_mapper);
m_actor2->GetProperty()->SetColor(.4, .5, .6);
}
void setRender()
{
m_leftRender->AddActor(m_actor1);
m_leftRender->SetBackground(.6, .5, .4);
m_leftRender->SetViewport(0.0, 0.5, 0.5, 1.0);
m_leftRender2->AddActor(m_actor1);
m_leftRender2->SetBackground(.6, .5, .4);
m_leftRender2->SetViewport(0.0, 0.0, 0.5, 0.5);
m_rightRender->AddActor(m_actor2);
m_rightRender->SetBackground(.2, .4, .6);
m_rightRender->SetViewport(0.5, 0.5, 1.0, 1.0);
m_rightRender2->AddActor(m_actor2);
m_rightRender2->SetBackground(.2, .4, .6);
m_rightRender2->SetViewport(0.5, 0.0, 1.0, 0.5);
}
void setRenderWindow()
{
m_renwindow->AddRenderer(m_leftRender);
m_renwindow->AddRenderer(m_rightRender);
m_renwindow->AddRenderer(m_leftRender2);
m_renwindow->AddRenderer(m_rightRender2);
m_renwindow->SetSize(600, 600);
m_renwindow->Render();
}
void setStyle()
{
m_style->SetRenderPair(m_leftRender, m_rightRender);
m_style->SetRenderPair(m_leftRender2, m_rightRender2);
m_style->RemoveRenderPair(m_leftRender2, m_rightRender2);
}
void setInteractor()
{
m_interactor->SetInteractorStyle(m_style);
}
void start()
{
m_renwindow->SetInteractor(m_interactor);
m_interactor->Initialize();
m_interactor->Start();
}
private:
vtkSmartPointer<vtkCubeSource> m_cube;
vtkSmartPointer<vtkPolyDataMapper> m_mapper;
vtkSmartPointer<vtkActor> m_actor1;
vtkSmartPointer<vtkActor> m_actor2;
vtkSmartPointer<vtkRenderer> m_leftRender;
vtkSmartPointer<vtkRenderer> m_rightRender;
vtkSmartPointer<vtkRenderer> m_leftRender2;
vtkSmartPointer<vtkRenderer> m_rightRender2;
vtkSmartPointer<vtkRenderWindow> m_renwindow;
vtkSmartPointer<vtkRenderWindowInteractor> m_interactor;
vtkSmartPointer<myInteractorStyle> m_style;
};
int main(int, char *[])
{
Client client;
client.start();
return EXIT_SUCCESS;
}
(其他實現方法與思路歡迎補充)
相關推薦
VTK(2)—— 雙view,顯示並聯動操作
前言:接到一個新的需求 window單視窗程式,雙view,顯示並聯動操作,做了兩種方式進行實現,程式碼思路和原始碼如下: (一)程式碼思路 一、判定誰動了? 方法1:通過當前事件的視窗位置與視窗大小中心軸進行比對 方法2:通過移動後的相機位置與兩個view中相機的
vs2013+qt5.51+vtk 實現的 雙view,顯示並聯動操作
1.首先我們必須將QVTKWidget加入到Qt Designer,只需找到編譯好的vtk的release版本下的QVTKWidgetPlugin.dll,QVTKWidgetPlugin.exp,QVTKWidgetPlugin.lib放入到自己QT下的designer
形態學濾波:(1)腐蝕與膨脹 (2)開運算,閉運算,形態學梯度,頂帽,黑帽
來講 極小值 -h 明顯 基本 極限 元素 腐蝕 黑帽 一、形態學概述 圖像處理中的形態學一般指的是數學形態學。 數學形態學是一門建立在格論和拓撲學基礎之上的圖像分析學科,是數學形態學圖像處理的基本理論。其基本運算包括:二值腐蝕和膨脹,二值開閉運算,骨架抽取,極限腐
Linux日常管理技巧(2):free,ps,netstat命令和抓包工具
情況下 路由器配置 傳輸協議 method ups lis red field 保存 一、free命令 free命令可以顯示當前系統未使用的和已使用的內存數目,還可以顯示被內核使用的內存緩沖區。用法: free [選項] 選項: -b:以Byte為單位顯示內存使用情況;-
《Linux學習並不難》Linux網絡命令(2):ifconfig命令顯示和配置網絡接口
Linux ifconfig 27.2 《Linux學習並不難》Linux網絡命令(2):ifconfig命令顯示和配置網絡接口使用ifconfig命令可以顯示和配置網絡接口,比如設置IP地址、MAC地址、激活或關閉網絡接口。命令語法:ifconfig [接口] [選項| IP地址]命令中各選項的含
伺服器實時通知客戶端方案,伺服器傳送/推送事件方案(2)server event,典型例子,可以用作股票、新聞資訊推送
server event是html5規範的一部分,它相比websocket使用起來更簡單,對伺服器的改動也最小 前端html部分 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&
簡單NLP分析套路(2)----分詞,詞頻,命名實體識別與關鍵詞抽取
文章大綱 中文分詞技術 評測參考 雲服務 哈工大語言云 ltp 基於深度學習方法的中文分詞 資訊檢索與關鍵詞提取 tf-idf TEXTRANK word2vector
WPF進階之介面(2):IDisposable,ICollectionView
原始碼地址:https://www.xuebuyuan.com/892590.html 廢話不多說,進入正題,先來說說IDisposable,看例子(來自MSDN): using System;using System.ComponentModel; // 下面的例子
微信小程式入門(2):web-view的使用
上一篇:簡單介面的實現 web-view是最近微信推出的元件,最開始用的時候對於我來說,就是一個內嵌網頁,相當於HTML裡的a標籤。然而這個元件卻不像想象中的那麼好用,不過困擾我十多天後,終於找到一個小方法來“解決”了,看完勿噴。 首先,你得是用企業賬戶或其它賬戶申請註冊的
資料結構與演算法(2)排序演算法,用Python實現插入,選擇,堆排,冒泡,快排和歸併排序
前段時間鼓起勇氣和老闆說了一下以後想從事機器學習方向的工作,所以最好能有一份不錯的實習,希望如果我有好的機會他可以讓我去,沒想到老闆非常通情達理,說人還是要追尋自己感興趣的東西,忙完這陣你就去吧。所以最
安卓使用記錄筆記(2)UI介面,按鈕響應事件
首先需要知道的是,在UI介面中新增好對應的button元件後,裡面會有對應id名稱,我們就是根據這個id名稱來查詢到對應的元件機器屬性。 private Button loadFile; private Button startFunc; 然後在init函式中:(init根據不同工程具體分析
Knockout學習(2)之observableArray,監控陣列,展示下拉框
ko對於陣列下拉框,監控跟蹤屬性值關鍵字為:observableArray,繫結值關鍵字為:options例子如下:@{ ViewBag.Title = "Index2"; } <h2>Index2</h2> <head>
MySQL 筆記整理(2) --日誌系統,一條SQL查詢語句如何執行
發生 重要 表示 優勢 兩層 一秒 正在 引擎 http 筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》 2) --日誌系統,一條SQL查詢語句如何執行 MySQL可以恢復到半個月內任意一秒的狀態,它的實現和日誌系統有關。上一篇中記錄了一條查詢語句是如何執行
MySQL 筆記整理(2) --事務隔離,為什麽你改了我還看不見?
ble 優勢 控制 nod 讀寫 為什麽 數據操作 src 保持 筆記記錄自林曉斌(丁奇)老師的《MySQL實戰45講》 3) --事務隔離,為什麽你改了我還看不見? 簡單來說,事務就是要保證一組數據操作,要麽全部成功,要麽全部失敗。在MySQL中,事務支持是在引擎
Python 影象處理 OpenCV (2):畫素處理與 Numpy 操作以及 Matplotlib 顯示影象
![](https://cdn.geekdigging.com/opencv/opencv_header.png) 前文傳送門: [「Python 影象處理 OpenCV (1):入門」](https://www.geekdigging.com/2020/05/17/5513454552/) ## 普通
ESP8266 WIFI模組學習之路(2)——模組與微控制器連線進行遠端操作
上一個部落格:ESP8266 WIFI模組學習之路(1)是關於對串列埠連線的,簡單驗證ESP8266是怎麼樣連線及其功能驗證,下面將通過微控制器連線,和手機進行遠端操作。 ESP8266和微控制器的連線,我這裡的微控制器型號為:STC12C5A60S2 ESP8266
OpenStack Neutron(2):建立私有網路並與公網相連
在OpenStack中,建立instance之前必須建立網路。這裡通過Dashbord建立私有網路並且通過虛擬路由器與公網相連。私有網路即Tenant network。1. 建立私有網路及其子網登入Dashbord->Project->Network->Ne
redis進化五(2):redis槽道與補充操作
一、redis的叢集槽道 槽道原理丟擲2個問題: 1、節點接收資料計算槽道號後,如何判斷當前槽道號是否歸我管? 2、判斷不歸本節點管時,如何獲取正確管理者的資訊? 槽道邏輯結構
新手學python(2):C語言呼叫完成資料庫操作
繼續介紹本人的python學習過程。本節介紹如何利用python呼叫c程式碼。內容還是基於音樂資訊提取的過程,架構如圖一。Python呼叫c實現的功能是利用python訪問c語言完成mysql資料庫操作。 在利用python呼叫c語言之前,我們需要首先完成c語言功能程式
MVVM Light 新手入門(2) :ViewModel / Model 中定義屬性 ,並在View中呼叫 利刃 MVVMLight
今天學習MVVM架構中“屬性”的新增並呼叫,特記錄如下,學習資料均來自於網路,特別感謝翁智華的利刃 MVVMLight系列。 一個視窗的基本模型如下: View(檢視) -> ViewModel (檢視模型)-> 多個Model(模型) 注: 檢視是使用者在螢幕上看到