記事一覧ページへ移動

Qt Creatorに頼らずQtソフトウェアを開発する時に躓いた所

2024-10-16
2020-09-28

おおよそ 2 ヶ月ぶりのわたすけです。他のところでブログを書いていたので許してください。

さて,Qt Creator,使いづらいですよね。(諸説あり)
と言うより他のエディタに慣れすぎているだけな気もしますが,やっぱりお気に入りの VSCode を使って開発をしたいところです。

ということで,Qt の勉強も兼ねて,Qt Creator に一切頼らずソフトを開発することにしました。いろいろ躓いたところを書きます。

その前に

正直初心者にもこの書き方をおすすめしたいのですが,もし Qt Creator を使いたいんだ!!!という人がいれば,以下の記事をどうぞ。
超最低限,ラベルとボタンのみが用意されたソフトを作るまでの道のりを書いています。

そもそもどうやって始めればいいんだ

めちゃくちゃざっくり言うと,QtWidgets をインクルードして,QMainWindow を継承したクラスを作り,コンストラクタでウィジェットを追加して,main 関数でその継承したクラスを作成,show()すればなんとかなります。

ちなみに,今から Qt Creator 無しで開発したい場合はおそらくこれ ↓ で解決します。

git clone https://github.com/watasuke102/template
cd template/Qt
cmake -GNinja .
ninja
./qt-test

あとは template/src/main.cpp をいじりましょう。

ボタン押されたときの動作ってどうやって実装するの

サンプルコードはこのとおり。

class widget : public QWidget
{
    private:
        int push_count = 0;
        QLabel      *label1;
        QPushButton *button;
    public slots:
        void onButtonClicked()
        {
            push_count++;
            label1->setText(tr("Widget (button has pushed!)\ncount: ") + QString::number(push_count) );
        }

    public:
        widget(QWidget *parent = nullptr) : QWidget(parent)
        {
            label1 = new QLabel(tr("Widget (button has not pushed)"));
            button = new QPushButton(tr("Let's push"));

            //ここが重要
            QObject::connect(button, &QPushButton::clicked, this, &widget::onButtonClicked);

            QGridLayout *grid = new QGridLayout;
            grid->addWidget(label1, 0, 0);
            grid->addWidget(button, 1, 0);
            setLayout(grid);
        }
};
  1. クラスのメンバとして(用語間違ってるかも)ボタンのポインタを作り,コンストラクタで new 使って button に入れる
  2. public slots:に適当な関数を作る
  3. QObject::connect にこのような記述をする
QObject::connect(button, &QPushButton::clicked, this, &widget::onButtonClicked);

引数は左から順に「押されたかどうかを検知するウィジェットのポインタ,検知するアクションの種類を ”ボタンが押されたら” にする,呼び出す関数があるクラス(?),呼び出す関数」となっています。たぶん。

QtDockWidget の使い方わかんないよ〜〜!!

わかる(やり方がわからないのわかる)

QtDockWidget は,その名の通り(?)MainWindow 内にはめ込んだり分離させたりといったことができるウィジェットです。具体例を挙げたかったのですがこういう感じのウィンドウを採用している身近なソフトが何故か思い浮かばなかったので断念します。

動画だとこんな感じです。

そもそもどうやればいいのかわかんないよ〜

まずは普通に QWidget を継承したクラスを作ります。

class widget : public QWidget
{
    public:
        widget(QWidget *parent = nullptr) : QWidget(parent)
        {
            QGridLayout *grid = new QGridLayout;
            grid->addWidget(new QLabel(tr("Widget B (button has not pushed)")), 0, 0);
            setLayout(grid);
        }
};

そうしたら QMainWindow を継承させたクラスを作ります。

class MainWindow : public QMainWindow
{
    public:
        MainWindow(QWidget *parent = nullptr)
        {
            QDockWidget *dock = new QDockWidget(tr("dock"));
            dock->setWidget(new widget);
            addDockWidget(Qt::BottomDockWidgetArea, dock); //Qt::{Left,Right,Top,Bottom}DockWidgetAreaがあるよ
        }
};

あとは main 関数内で「MainWindow w; w.show()」みたいな感じに書けば OK です。

ドックウィンドウのサイズ変更わかんないよ〜

addDockWidget()の後にこんな感じに書きます。

resizeDocks({widget}, {1000}, Qt::Vertical);

引数は左から順に「リサイズしたい QDockWidget*( {} で囲む),変更後のサイズ( {}で囲む),方向(Qt::Vertical なら高さ,Qt::Horizon なら横幅)」という感じになっています。

例えば widget_A の幅を 150 に,widget_B の幅を 300 にしたい場合は以下のように記述します。

resizeDocks({widget_A, widget_B}, {150, 300}, Qt::Horizon);

その他

困ったら関数名でググりましょう。Qt 公式っぽいドキュメントは機械翻訳にかけても読むべきです(情報揃ってるしわかりやすい)


終わりに

もうちょっと躓いた点があったような気もしますが,思い出せないということは検索してぱぱっと解決したんだろうなと思って諦めました。検索力は大事だなぁと常々感じております。

Qt Creator は Qt に関する細かい知識無しで直感的に開発を行えますが,つまり Qt に対する基礎的な理解をせずに開発ができてしまうというわけであり,いつか躓く可能性があるなぁと前から思っていました。(というより躓きました)
「Qt 理解するためにも 1 から手書きで実装してみたら?(意訳」といった助言を受け,無理に決まってるだろ・・・と思いブチギレつつやってみましたが,結果的には Qt に対するより深い理解を得ることができ,とても満足しています。

この記事がなにかの役に立てばいいな〜と思っています。


Comments

Powered by Giscus