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

WatasukeRoom Qt

おおよそ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に対するより深い理解を得ることができ,とても満足しています。

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

コメント

タイトルとURLをコピーしました