支援科學記號的 QSpinBox

Qt 本身有提供 QDoubleSpinBox 這個元件(官網),可以提供使用者來輸入浮點數(小數),不過他基本上並不支援「科學記號」(科學記數法、Scientific notation、維基百科),所以如果要輸入極大的數字、或是相當接近 0 的小數時,都會相當麻煩。

查了一下,Qt 似乎沒有特別針對科學記號設計類似的元件,所以如果有這樣的需求,就得自己來了。

針對這個問題,網路上可以找到一些討論,也有一些實作,但是看起來好像都很複雜?

後來 Heresy 自己玩了一下,發現其實只要繼承 QDoubleSpinBox 並搭配 QDoubleValidator官網)的話,其實可以相對簡單地建立出一個支援科學記號的版本。

下面這個 QScientificSpinBox,就是一個簡單的實作:

閱讀全文

廣告

自行使用 VisualStudio 建置 QtAV

之前在《使用 Qt 撰寫影片播放程式的一些紀錄》一文,Heresy 有大概紀錄一下使用 Qt 5.x 內建的 QMediaPlayer 來撥放影片的方法;不過當時也碰到了一些問題,所以 Heresy 後來也有試著找一些替代方案來用。

後來是發現 QtAV 這個整合了 Qt 和 FFmpeg(官網)的這個專案似乎還算不錯,所以就認真研究看看了。

QtAV 的官方網站是:http://www.qtav.org/,原始碼則是在 https://github.com/wang-bin/QtAVhttps://sourceforge.net/projects/qtav/

他基本上包含了 C++ 函式庫、對應的範例,以及兩個功能算是完整的播放軟體(C++ 與 QML)。

而由於他提供的預先編譯好的版本選擇有限,所以 Heresy 後來就開始研究怎麼自己編譯了。這篇基本上就是怎麼在 Windows 環境下,使用 Visual C++ 來進行建置的紀錄:

閱讀全文

QWizard 傳遞自訂變數

之前有大概介紹過一下使用 Qt 的 QWizard 的使用經驗了。

而當時也有提到,在不同的 QWizardPage 之間,要交換資料的話,基本上是要靠「field」的機制來進行的,這部分的說明主要是官方的《Registering and Using Fields》這份文件(頁面)。

Qt 在這邊的設計,主要是靠 Qt 類別的預設「屬性」(property)、以及該屬性對應的存取子來做存取的。所以,當一個類別沒有指定預設要使用的屬性時,就需要透過 QWizardsetDefaultProperty() 這個函式(文件),來登記要使用的屬性名稱、以及對應的存取子。

像是之前也有提過,如果是以 QDoubleSpinBox 來說,如果想要在 QWizard 的架構下登記成 field 的話,就需要先執行下面的指令:

setDefaultProperty("QDoubleSpinBox", "value", "valueChanged");

他的第一個參數是類別的名稱,第二個參數則是要使用的屬性名稱(value),最後則是這個類別用來告知該屬性有變化的 signal(valueChanged)。

閱讀全文

Qt 的精靈模式:QWizard

這篇算是簡單紀錄一下,怎麼用 Qt(官網)來寫出「一步一步進行下去」的精靈模式(Wizard mode)的程式。

Qt 的精靈模式,是從 Qt 4.3 開始引進的,基本上主要是兩個類別:QWizard官方文件)和 QWizardPage官方文件)來實作。

其中,QWizard 是提供精靈模式的一個大的框架(framework)、來處理整個精靈的流程;在一個精靈中,會有許多個 QWizardPage 的物件、個別代表精靈模式中的每一個頁面。

基本範例

下面就是官方給的一個極簡單的範例:

QWizard wizard;
wizard.addPage(createIntroPage());
wizard.addPage(createRegistrationPage());
wizard.addPage(createConclusionPage());

wizard.setWindowTitle("Trivial Wizard");
wizard.show();

閱讀全文

使用 Qt 撰寫影片播放程式的一些紀錄

要使用 Qt 5 寫出一個撥放影片的程式,其實滿簡單的;因為 Qt 本身已經提供了一個「Qt Multimedia」的模組(文件),提供了以 QMediaPlayer文件)為主的類別、讓使用者可以快速地撰寫出一個撥放軟體了。

這邊 Heresy 則是記錄一下,最近使用他的一些紀錄。


基本使用

他最簡單的寫法,大概可以按照官方範例、寫成:

player = new QMediaPlayer;

playlist = new QMediaPlaylist(player);
playlist->addMedia(QUrl("http://example.com/myclip1.mp4"));
playlist->addMedia(QUrl("http://example.com/myclip2.mp4"));

videoWidget = new QVideoWidget;
player->setVideoOutput(videoWidget);

videoWidget->show();
playlist->setCurrentIndex(1);
player->play();

閱讀全文

Boost 與 Qt 的 Signal / Slot 效能測試

Qt 這個圖形介面的開發套件(官網),基本上算是目前數一數二的跨平台圖形介面開發方案了。

在 Qt 的架構中,要在不同的物件之間傳遞資訊、觸發事件,所使用的是其創造的「Signals & Slots」架構(官方文件)。

而目前除了 Qt 之外,還有許多函式庫,也有提供 Signals & Slots 的功能,像是 Boost C++ Libraries 裡面,就有 boost::signal 和 boost::signal2 這兩個函式庫可以使用;其中,Heresy 也有針對 boost::signal2 做過介紹(參考)。

在 Heresy 來看,Qt 的 signal & slot 的架構比較麻煩的地方,是他必須要使用許多非標準的語法,所撰寫的程式還需要經過 Qt Meta-Object Compiler(moc)來做前處理,才能讓一般的 C++ 編譯器編譯。相較之下,Boost 的 Signal2 在撰寫上的彈性就比較大、也比較方便了。

不過,這兩者個效能怎麼樣呢?這邊 Heresy 就是打算來做個簡單的效能評估。

閱讀全文

OpenNI 2 VideoStream 與 Device 的設定與使用

之前的《OpenNI 2 基本程式範例》一文,基本上是一個最簡單、OpenNI 2 讀取深度的範例;而之後的《OpenNI 2 的錯誤處理》,則是針對 OpenNI 2 所採用的錯誤處理方法,做一個補充。接下來這一篇呢,則是在《OpenNI 2 基本程式範例》中,讀取深度的範例程式的基礎上,加上彩色影像的讀取,並說明如何針對建立出來的 VideoStream 做進一步的參數設定。

而最後,也會稍微帶一下,要怎樣把 OpenNI 2 讀到的影像資料,轉換成其他函式庫,例如 OpenCV 或 Qt 專用的格式。

閱讀全文

在 OpenNI 環境同時使用多個 Kinect

這一篇基本上是延續上一篇《在 OpenNI 管理多個裝置》,繼續來研究怎麼在 OpenNI 的環境裡,同時使用一台電腦上的多個裝置了~由於開始要寫的時候,Heresy 才發現自己也有不確定的地方,所以索性就到 OpenNI 官方論壇去發問了;而結果,也有 PrimeSense 的人幫忙給了段範例,有興趣的人可以參考《Problem with using multiple device》這篇的回應。

根據這邊的範例程式,可以看的出來,這邊的基本概念,是使用同一個 xn::Context先透過列舉出來的 xn::NodeInfo 個別建立出 xn::Device 後,再以 device 的 instance name 作為 query 的條件(xn::Query)、以此來建立對應特定 device 的其他 production node 了~

閱讀全文

建立一個不被 View 影響線條寬度 Graphics Item

之前在《建立自己的 QGraphicsItem》一篇文章裡,已經有大概提過要怎麼建立一個屬於自己、可以在 Qt 的 Graphics View 裡面使用的 QGraphicsItem 了。而這一篇,則算是一種延伸的特殊需要,主要是希望可以透過在 paint() 這個函式裡面做額外的控制,避免使用 QPainter 進行繪製的時候,會有畫筆(QPen)和筆刷(QBrush)一起受到 Graphics view 的 transformation(主要是放大和縮小)影響的問題。

下面是一個受到影響、簡單的例子:

閱讀全文

程式設計雜記

  • 以往 Heresy 在寫 class 的 header file 的時候的寫法,都是把 Class 的定義和他的 inline function 寫在同一個 header 檔裡;但是當 inline function 多的時候,其實在看程式碼的時候還滿麻煩的…(這邊是指把 inline function 的 definition 寫在 class 外的狀況)

    現在在想要不要把 inline function 都丟到另一個 header 裡,有用到的檔案另外去 include?或者直接在本來的 header 檔最後去 include 它… 雖然在程式的意義上完全相同,但是在 IDE 內的程式可讀性應該會好一點。
    (附註:VC 的 #pragma region / endregion 會讓裡面的程式不能摺疊…參考

  • 這一陣子查資料才發現,原來 C++ 的 class member function 要 inline,只需要把 inline 加在 function definition 的地方就好了,在 declaration 可以不用加?下面是個範例:(參考

    class Foo
    {
    public:
      void method();
    };
     
    inline void Foo::method()
    { ... }

    Heresy 之前都是兩個地方都加…不過仔細想想,這樣好像滿合理的?

閱讀全文