Qt 勉強会 @ Tokyo #63 参加報告 | Qt Widgetsでのタブページの実装に挑戦

概要
項目 | 内容 |
---|---|
イベント名 | Qt 勉強会 @ Tokyo #63 |
URL | https://qt-users.connpass.com/event/101062/ |
ハッシュタグ | #qtjp |
主催者 | 日本Qtユーザー会 |
開催地 | 東京都新宿区新宿1-23-1 新宿マルネビル9F |
開催日時 | 2018-09-15 13:00~18:00 |
参加人数 | 6 |
SNS |
今回の勉強会は名古屋と同じ開催日だった。また,いつもは10人くらいの参加者だったが,今回は6人とこじんまりとした集まりになった。
作業
前回と前々回の勉強会でQt Quickでのタブページの実装に挑戦し,Qt Quickだと実装が困難なことがわかった。
そこで,今回からはQt Widgetsでのタブページの実装に挑戦した。具体的には,以下のページを参考に,QTabWidgetsの使い方を調べ,今回行き詰まった[タブの追加]ボタンの実装した。
その他,当日Atsuhi4さんに相談したところ,サンプルコードを教えてもらった。自分の実装と違う方法なので,参考になった。
成果
当日Qt 5.11で作成したQt Widgetsでのタブページの実装動作例は以下のとおりとなった。
ソースコード一式を「QtExample/TabPage at b7f30aecc9b20fa71d144cd74db1f86e20e0d4d7 · senooken/QtExample」に格納している。長くないので,全文を以下にも掲載する。
///////////////////////////////////////////////////////////////////////////////
/// \file main.cpp
/// \author SENOO, Ken
///////////////////////////////////////////////////////////////////////////////
#include <QApplication>
#include <QLabel>
#include <QTabBar>
#include <QTabWidget>
#include <QTextEdit>
#include <QToolButton>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
// 1. Create QTabWidget instance.
QTabWidget widget;
// 2. Create page widget instance.
QTextEdit editor1{"EDITOR1", &widget};
QTextEdit editor2{"EDITOR2", &widget};
// 3. Insert page widget into tab widget by addTab() or insertTab().
widget.insertTab(0, &editor1, "TAB1");
widget.addTab(&editor2, "TAB2");
// Enable close and drag.c
widget.setTabsClosable(true);
widget.setMovable(true);
// Handle tab close.
widget.connect(&widget, &QTabWidget::tabCloseRequested,
[&](int index) {widget.removeTab(index);}
);
// Add new tab button.
QToolButton tb;
tb.setText("+");
tb.setAutoRaise(true);
tb.connect(&tb, &QToolButton::clicked,
[&]() {widget.insertTab(widget.count()-1, new QTextEdit(), "New Tab");}
);
widget.addTab(new QLabel("You can add tabs by pressing +"), QString());
widget.setTabEnabled(widget.count()-1, false);
widget.tabBar()->setTabButton(widget.count()-1, QTabBar::RightSide, &tb);
widget.show();
return app.exec();
}
QTabWidgetには,tabsClosableとmovableのプロパティがあり,これらを有効にすることで,Qt Quickでは自分で実装が必要だったタブのクローズと,ドラッグを実装できる。タブのクローズは,SetTabsClosable()
で有効にするだけでは不十分で,このシグナルを捕捉して,removeTab()
で削除する。
どちらにしても,たった数行のコードでQt Quickで1か月かけても実装しきれなかった,タブのクローズとドラッグを実装できた。いったい自分は何をやっていたんだと拍子抜けしてしまった。
しかし,QTabWidgetにも課題はあった。それは,タブ追加ボタンの実装だ。
今回の実装では,StackOverFlowでの回答を参考にして,ダミーのタブを用意し,それをQToolButtonに差し替えて実装している。これにより,タブバーと同じように配置がされる。ただし,タブバーと同じように扱われるため,ドラッグで移動できてしまう (デモ動画の最後参照)。
Atsushi4さんの実装では,setCornerWidget()
でタブの角にQPushButtonを配置して実装している。この実装だと,ドラッグの対象にはならないが,代わりに常に端にボタンが配置されるため,画面を最大化したときに,現在のタブとタブの追加ボタンの位置が大きく離れてしまう。
解決方法はいくつか考えれる。今のところ以下の3点を考えている。
- Chromium系のWebブラウザーでは,ドラッグ中はタブ追加ボタンは無効になっている。これを参考にして,ドラッグ中は一番端のタブを非表示にして無効にする。
- StackOverFlowでは,「QTabBarのmousePressEventをオーバーライドして独自のTabBarで上書きする」という回答があった。この方法だと,いちいち自分でオーバーライドしないといけないので手間だと感じた。
- Qtで作られたWebブラウザーであるfalkonのソースコードを参考にする。
Webブラウザーでのタブページの実装が一つのお手本だと思っている。この中の方法を検討して,うまく実装していきたい。
また,今回の勉強会では,「タブバーをダブルクリックで編集」機能も実装していない。この機能自体がおまけみたいなものだが,こちらも挑戦していきたい。
結論
今回の勉強会では,Qt Widgetsでのタブページの実装に挑戦した。今まではQt QuickでのQMLでのアプリ開発しかほぼ勉強していなかったので,またいろいろ発見があった。感触としては,Qt自体がC++で作られているのもあり,Qt Widgetsはデスクトップアプリで長い実績もあり安定していて,QMLよりも応用が効くように感じた。
前回の勉強会で,Qt Quickでのタブページの実装について発表したように,この1か月でQt Widgetsでのタブページを完成させて,また成果を発表したい。
なお,今回は4月から勉強会に参加し始めて,初めて懇親会に参加した。今月で半年,6回目の勉強会参加であり,今回は参加人数が少ないのもあり,一つの区切りとしていいかと思って参加した。話の内容はあまりよくわからなかったが,一つの経験になった。また常連が少ないときに参加してみたいと思う。