日記

ただの日記

QuaZIPをビルド【Windows】

QuaZIPをビルドする。Windows上のQtを使っている。
QuaZIPでDLLを作成し、DLLを自分のアプリケーションから呼び出すということをやった。

一応動いたが、他のサイトでやってることをいまいち理解できないまま、
こうやったらできるんじゃねという適当な考えで動かしているのが現状。

続きを読む

QtのGUIがなんか重いという問題

Qtを始めてデバッグなんかをしていたら、どうも昔に比べて思いなーと思っていた。それはメニューバーの反応が遅かったり、Windowサイズを調整すると再描画がされなかったり、というような現象でJavaGUIアプリケーションを触っているようなイメージだった。

しかし、サンプルのアプリケーションではさくさく動くし見た目もC#WPFアプリケーションのようなモダンなデザインなのだ。

どうしてだろうとmain.cppやらmain.qmlやら設定ファイルやらを見比べていたら、一つの関数が違っていた。

// #include <QGuiApplication>
#include <QApplication>
#include <QQmlApplicationEngine>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
    // ここを
    // QGuiApplication app(argc, argv);
    // こうする
    QApplication app(argc, argv);
    
    QQmlApplicationEngine engine;
    engine.load(QUrl(QLatin1String("qrc:/main.qml")));

    return app.exec();
}

するとこれが、 f:id:kou_lowenergy:20170219172242p:plain

こうなった。見た目ではあまり変化がないように思うかもしれないが、レスポンスが向上しウィンドウサイズの変更に機敏に反応してくれるようになった。 f:id:kou_lowenergy:20170219172230p:plain

なぜだろうと、調べてみるとQApplicationはQGuiApplicationを継承していて、Wigetsの操作を提供していると書いていた(ここ)

使用しているMenuBarやTreeViewがWidgetsということだろうか?それでも、遅いながらも動いているのはおかしいということにならないだろうか。main関数内のたった1行だけを変更するだけで、このように変化する理由がわからない。

参考

QFileSystemModelを見る(QML)

Qtのモジュールはドキュメントがしっかりしてるけど、
使うとなるといまいちどうやって使えばいいのかわからない……

いちいち日本語にまとめるのは時間がかかりすぎるんだけど
勉強し始めということで、ファイルを扱う"QFileSystemModel"についてだけとりあえず見ていく。

QMLとC++の連携がいまいちわからないから、これを通して学びたいところ。

基本

QFileSystemModelはこのクラスを基底として継承し拡張したクラスを用いることがほとんどあるが、継承せずとも使用することはできる。

main関数内でこのように書く。これメモリ解放してないけどいいんだろうか。QMLのTreeViewでファイル一覧を読み込むために必要なオブジェクトはここで渡す。

//QML側でfilesystemmodelという名前でQFileSystemModelを読み込めるようにバージョン1.0として登録
qmlRegisterUncreatableType<QFileSystemModel>("filesystemmodel", 1, 0,
           "FileSystemModel", "Cannot create a FileSystemModel instance.");
//オブジェクト生成
QFileSystemModel *model = new QFileSystemModel();
//ディレクトリを読み込む これをしないと読み込まれない
model->setRootPath(QDir::homePath());
//任意でファイルのフィルタリングができる(ここでは現ディレクトリ「.」を排除している)
model->setFilter(QDir::NoDot | QDir::AllDirs | QDir::Files);
//QMLで読み込めるように追加
engine.rootContext()->setContextProperty("fileSystemModel", model);
engine.rootContext()->setContextProperty("rootPathIndex", model->index(model->rootPath()));

QMLにて読み込む。setContextPropertyで登録した変数が使用できる。modelはきっとQFileSystemModel以外にもあって、標準化されているんだろうなー。

property alias filelist: filelist
TreeView {
    model: fileSystemModel
    rootIndex: rootPathIndex
}

qmlRegisterUncreatableTypeで登録したクラスを使うときは、このように指定した名前、バージョンでimportする。 関係ないけど、onActivatedで急にindex変数が使えることに違和感を覚える。TreeViewのドキュメント見ると書いてあるんだけどさ。

import filesystemmodel 1.0

filelist.onActivated : {
    var url = fileSystemModel.data(index, FileSystemModel.~~~~~~~)
    Qt.openUrlExternally(url)
}

これで最低限のファイル一覧を読み込むことができる。

機能拡張

しかし、これではファイルリストが表示されるだけで、ファイルサイズや最終更新日などの情報は得られない。そこで、QFileSystemModelを継承して独自の機能を追加する。

もちろん継承したクラスで実装した公開メソッドはqmlRegisterUncreatableTypeによってQMLから使えるから、それを活用して情報を得るようにする。

これについては、Qtの公式サンプルを見れば良いと思う。というかほとんどここの情報から学んだから必見。main.cppに継承したクラスが実装されていて、まとまっている。

Qt Quick Controls - File System Browser Example

まとめ

QMLとC++のクラスを紐付けることによってデータの受け渡しをするみたいだ。これはRubyの拡張ライブラリみたいなバインディングと同じなんだね。

C++ではQMLで欲しい情報を得るために継承によって公開メソッドを作り、QML側でメソッドによりset,getをするというのが基本。QML側ではidをコンポーネントごとに割り当てられるからオブジェクト間の連携は楽にできそう。

Qtはバージョンによる違いとかQML前後の情報で混乱しがちだなあ。

参考

Qtでの".ui.qml"と".qml"

Qt CreatorではQMLを記述するためにファイルを新規作成すると、
.ui.qmlと.qmlが自動生成される。

.ui.qml

動作ではなくUI部分だけを作成するものである。
自動生成すると「main.qml」なら「MainForm.ui.qml」というような名前になる。 ここにスクリプト(onClicked {}とか)を書くとエラーは吐くがビルドは通る。 しかし、GUIによるデザインができなくなる。

いずれにせよ赤い下線が表示されるのは気持ち悪いし、デザインと動作がひとつになるのはメンテナンスに欠ける気もするので、ここには書かない。

.qml

動作部分を記述するファイルである。ここに主にスクリプトを書いていくことになる。

いままで、この辺をまったく知らないので、全部.ui.qmlに書いてしまっていた。
しかもわざわざ.qmlを削除してまで…… 馬鹿だ。

参考

QObjectを継承するとエラーでビルドできない [undefined reference to vtable for ~]

これで一日が潰れたorz

vtableというのはQt特有のものではなく、
仮想関数テーブル(virtual method table)というものであるらしい。
調べると(wikipeida)ポリモーフィズムを実現するために内部で実装されていることだけわかった。

コンストラクタのオーバライドの際にエラーが発生しているので、元々のクラスが認識されていないのだろうか???

原因がよくわからないが、解決方法はわかった。
一度、qmakeをすることだ。

ビルド(B) -> qmakeの実行

この作業を一度行うと、その後はエラーが出てこなかった。

Qtについての理解が薄いから何が何だかわからないよ。
参考サイトを見ると、この現象についての詳細が書かれている。

参考

Qtについて調べる

ElectronもいいけどQtもいい。

Qtを始めようとするとまず、Qtがなんなのかよくわからなくなる。

プログラムだけで動かしているようなサンプルもあるしQMLとかいう謎の言語を使っているものもある。それにQt QuickとかQt Widgetとかよくわからない!開発環境であるQt Creatorを入れてみても、DesignerとかAssistantとかいろいろインストールされて何が何だか…

といわけでQtについて調べてみる。

続きを読む

純粋仮想関数に関するサンプル

純粋仮想関数とはオーバーライドされることを前提とした関数である。
だから基底クラスでインスタンス化できない。

基底クラスの型に継承したクラスの実態を代入できる。
この場合、基底クラスのメソッド及び、基底クラスで宣言した仮想関数を オーバーライドした関数を使用できる。

続きを読む