Qtでの検索ボックスの作成方法
はじめに
Qtに関する情報にどれほどの需要があるか分かりませんが、作る機会が多いであろう検索ボックスの作り方を、備忘録も兼ねて共有しておきます。
対象
ある程度Qtを触ったことがある人。(signal/slotが分かる人。)
一応Qtを知らない方用に、適宜公式ドキュメントへのリンクをはっています。
開発環境
- Qt Creator 4.11.2
- Qt 5.14.2
TL;DR
下の写真のような検索ボックスを実現するにあたり、QGridLayout
を利用して、コンポーネントを重ねることを考えました。ある程度詳しい方はgithubを見ていただく方が速いと思います。
コード
各コンポーネントはQWidget
を継承したSearchBox
クラスのメンバ変数として設定しています。ClickableLabel
に関しても自作クラスなので、後ほど解説します。
SearchBox::SearchBox(QWidget *parent)
: QWidget(parent),
m_layout(new QGridLayout),
m_lineEdit(new QLineEdit),
m_label(new ClickableLabel) // 補足で解説しています。
{
m_label->setPixmap(QIcon(":/magnifying_glass.png").pixmap(QSize(32, 16)));
m_label->setFixedWidth(32);
m_lineEdit->setPlaceholderText("Search");
m_lineEdit->setTextMargins(32, 0, 0, 0);
m_layout->setSpacing(0);
m_layout->addWidget(m_lineEdit, 0, 0);
m_layout->addWidget(m_label, 0, 0);
setLayout(m_layout);
connect(m_label, &ClickableLabel::clicked, this, [&](){ m_lineEdit->setFocus(); });
}
解説
各コンポーネントの詳しい解説は公式ドキュメントを参照してください。QLabel
はClickableLable
の親クラスです。ClickableLable
が何か分からなくて気持ち悪い方は、先に補足をご覧ください。
QGdirLayout / QLineEdit / QLabel
手順
1. ClickableLabel
にアイコンを設置し、幅を調整する。
m_label->setPixmap(QIcon(":/magnifying_glass.png").pixmap(QSize(32, 16)));
m_label->setFixedWidth(32);
一行目は、ClickableLabel
にアイコンを設置するコードです。このコードではQtのresourceシステムを用いてアイコンのパスを設定しているので、見たことがない方は戸惑われるかと思います。詳しくはQt公式をご覧ください。QSize
は用意したアイコンの縦横比に合わせて適宜変更してください。二行目では、ClickableLabel
本体の横幅を設定しています。この設定をしないと、QGridLayout
に設置する際に、QLineEdit
を覆い隠してしまいます。
2. QLineEdit
のプレースホルダーテキストとマージンを設定する。
m_lineEdit->setPlaceholderText("Search");
m_lineEdit->setTextMargins(32, 0, 0, 0);
一行目は、Qiitaの上部にある検索ボックス中の「キーワードを入力」のように薄いグレーで表示される文字(プレースホルダーテキスト)を設定するコードです。二行目は、一行目で設定したプレースホルダーテキストがlabelと重なるのを避けるためのコードです。引数は順に、左、上、右、下です。(cssの順番がmarginとは異なるので注意してください。)左のマージンの値をClickableLabel
の横幅の値に設定することで、ちょうどアイコンの右側にプレースホルダーテキストが表示されるようになります。
3. QGridLayout
のspacingを0に設定し、QLineEdit
とClickableLable
を設置する。
m_layout->setSpacing(0);
m_layout->addWidget(m_lineEdit, 0, 0);
m_layout->addWidget(m_label, 0, 0);
setLayout(m_layout);
最後に、準備したコンポーネントを設置して完成です。QGdidLayout
はその名の通り、グリッド状のレイアウトで、addWidget
メソッドに設置するItem
とrow
およびcolumn
を引数に渡してコンポーネントを追加していきます。
gridLayout->addWidget(Item, row, column);
ここで、あえて二つのコンポーネントのrow
とcolumn
を同じ値に設定することでコンポーネントを重ね合わせることができます。3行目のsetLayout
はQSearchBox
のメソッドで、その名の通り、レイアウトを設定します。
補足
1. フォーカスに関する問題
以上の解説の通りにコードを書けば、見た目は思い通りのものは作ることができます。ですが、ここでユーザーのことを考えて一工夫してみましょう。試しに、Qiita上部の検索ボックスの虫眼鏡アイコンをクリックしてみてくささい。どうでしょう。検索ボックスにフォーカスしないと思います。ユーザーからすれば、虫眼鏡マークをクリックした時にしたいことは、検索だと思うので,
ちょっとしたことですが不便ですね。実はQtでも、アイコンを表示するために、デフォルトのQLabel
を使うと同じ状況に陥ってしまいます。
前置きが長くなりましたが、QLable
にちょっとした細工をして、虫眼鏡アイコンをクリックした時でも、検索ボックスにフォーカスするようにしましょう。
2. ClickableLabel
上記の問題を解決するのがClickableLabel
クラスです。やっていることは簡単で、デフォルトのQLabel
では検知されない、クリックイベントを検知するように変更するだけです。コードは下の3行で済みます。emit
が分からない方は、Qtのsignal/slotという仕組み一度調べてみてください。また、実はこのClickableLable
はQt wikiというQtに関する情報が集まっているサイトに載っています(Qt wiki ClickableLabel)。
void ClickableLabel::mousePressEvent(QMouseEvent*)
{
emit clicked();
}
そして、ClickableLabel
で検知したクリックを、SearchBox
側で検索ボックスのフォーカスと紐付けます。
connect(m_label, &ClickableLabel::clicked, this, [&](){ m_lineEdit->setFocus(); });
こうすることで、虫眼鏡アイコンをクリックしたときにも、検索ボックスにフォーカスするようになります。
以上で、検索ボックスの完成です
参考
stackoverflow - How to place an icon onto a QLineEdit?(リンク先の方法より、この記事で紹介した方法の方が簡潔です)
最後に
まず、初めての投稿なので、どの解説を載せてどの解説をはしょるのかを決めるのに苦労しました。もし、言葉足らずの部分があれば、遠慮なく質問してください!また、間違った情報があれば、指摘していただけると嬉しいです。
QtはちょっとしたGUIを作るのには適しているフレームワークだと思います。興味を持った方は是非トライしてみてください!!
Author And Source
この問題について(Qtでの検索ボックスの作成方法), 我々は、より多くの情報をここで見つけました https://qiita.com/tarao1006/items/d804c23059cca941070c著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .