バックアップツール [NetWalker]
手書きのメモをタラタラやっているうちに、NetWalkerに入っているデータが増えてきたので、バックアップツールが欲しくなってきました。Ubuntu用にもいろいろある様ですが、せっかくなので、単純なツールを作ってみることにしました。と言うことで、手書きメモは一旦置いて、寄り道です・・。
大まかな仕様は下記の通り。
いずれ、実装したいのは下記の通り。
バックアップ先はネットワーク越し(SMBサーバ)を考えているので、SMBのクライアント機能は最初から実装したいんですが、どの程度の手間がかかるんですかねぇ・・。とりあえず、バックアップ先が接続されているかどうかは前回バックアップ日時の存在と、指定ディレクトリの存在を見て判断することにします。後、単純なコピーで考えているので、リストア機能はつけません。
画面案は下記の通り。
コピー元はリストで表示して、横の「+」「-」ボタンで追加、削除するようにしたいと思います。追加が可能なことでコピー元のディレクトリが増えるので、スクロールも必要になりますね。また、削除の対象を選択するためにも、少なくとも一つの項目を選択できるようにしなければいけませんね・・。これにはQListViewを利用したいと思います。ボタンはQPushButtonですね。
コピー先は一つのみ指定できることにします。コピー時には「コピー先」のディレクトリをルートとし、「コピー元」として選択したディレクトリのパスをそのまま作成することにします。コピー元に同じディレクトリパスが存在した場合は、追加時にはじくことにしましょうか・・。この領域にはQLineEditを、ボタンは上と同じQPushButtonを利用したいと思います。
また、それぞれのディレクトリの指定にはQFileDialogが使えると思います。
で、両領域の間にある下矢印のボタンをバックアップ開始のボタンとしたいと思います。これもQPushButtonですね。
その下の領域の「進捗」のところはバックアップの進捗状況を表示したいと思います。いずれは、ログとして保存できるようにしてもいいですかね・・。ここはQTextEditでいいですかねぇ・・。
*
と言う感じで、作ろうかとまずは Qt Designer で部品を配置しました。・・が、よく考えたらレイアウトを使わないと・・・。
つづく。
大まかな仕様は下記の通り。
- バックアップは単純なディレクトリのミラーリング
- バックアップは手動で開始
- ミラー先にはフルパスでコピー
いずれ、実装したいのは下記の通り。
- タイマによる自動バックアップ
- SMBクライアント機能
バックアップ先はネットワーク越し(SMBサーバ)を考えているので、SMBのクライアント機能は最初から実装したいんですが、どの程度の手間がかかるんですかねぇ・・。とりあえず、バックアップ先が接続されているかどうかは前回バックアップ日時の存在と、指定ディレクトリの存在を見て判断することにします。後、単純なコピーで考えているので、リストア機能はつけません。
画面案は下記の通り。
コピー元はリストで表示して、横の「+」「-」ボタンで追加、削除するようにしたいと思います。追加が可能なことでコピー元のディレクトリが増えるので、スクロールも必要になりますね。また、削除の対象を選択するためにも、少なくとも一つの項目を選択できるようにしなければいけませんね・・。これにはQListViewを利用したいと思います。ボタンはQPushButtonですね。
コピー先は一つのみ指定できることにします。コピー時には「コピー先」のディレクトリをルートとし、「コピー元」として選択したディレクトリのパスをそのまま作成することにします。コピー元に同じディレクトリパスが存在した場合は、追加時にはじくことにしましょうか・・。この領域にはQLineEditを、ボタンは上と同じQPushButtonを利用したいと思います。
また、それぞれのディレクトリの指定にはQFileDialogが使えると思います。
で、両領域の間にある下矢印のボタンをバックアップ開始のボタンとしたいと思います。これもQPushButtonですね。
その下の領域の「進捗」のところはバックアップの進捗状況を表示したいと思います。いずれは、ログとして保存できるようにしてもいいですかね・・。ここはQTextEditでいいですかねぇ・・。
*
と言う感じで、作ろうかとまずは Qt Designer で部品を配置しました。・・が、よく考えたらレイアウトを使わないと・・・。
つづく。
ペンの追随の実装 [NetWalker]
さて、めちゃくちゃ長かったですが、ようやく実際の実装を行っていきたいと思います。とりあえずは、「qtlcanvas.h」と「qtlcanvas.cpp」に残りのマウス関連のイベント(「mouseMoveEvent()」と「mouseReleaseEvent()」)を追加します。
だいぶ慣れてきたと思ってましたが、コードを入力し始めると、NetWalkerのキーボードの悪さが目立ちますねぇ・・・。また、慣れるかなぁ・・。また、Qt Creator のエディタが遅い上に、ときどきフリーズしてしまいます。なので、前回設定した通り外部エディタを使っていますが、この外部エディタの立ち上げがいちいち面倒ですね・・。やっぱり、Qt Creator のエディタを使いたいです・・。
ちなみに、追加したコードはこんな感じ。
とりあえず、デバグコードのみ
で、ビルド&実行。・・・無事、動作しました。
ちゃんとログが出てます
さて、ちゃんと実装しますか・・。QPainterの使い方は以前大雑把に触れましたが、実際に実装してみると、ちゃんと線が引けませんね・・。一瞬、線が出てきてるんですが、すぐに消えてしまっています。しかも、やたらと実行時エラーが出ています。
実行エラーについては、painterをend()させ忘れていたので、それをすることで解決。一方、一瞬出て、すぐ消えると言うのは、描画をするたびにQWidgetが一から書き直されているための様ですね・・。これ、どうすればよかったですかねぇ・・。昔書いたソースを見てみたら、paintEvent()では、全ての描画をやり直してます・・。描画についてはこんな感じかな・・。
多分こんな感じ
ちなみに、たしか、レイアウトなども paintEvent() のタイミングで動作したと思うので、QWidget のサイズをレイアウトに任せている場合は、レイアウト後にサイズを取るために、resizeEvent()でサイズを取得する必要があります。
ちょっと、考えなおしが必要ですね・・。データを保持するクラスを作成して、widgetからはそちらにペンの位置などを指示するだけにします。
さて、編集します。NetWalker画面が広いので便利です。エディタが2枚開けます。
ヘッダを見ながらコーディング
オフスクリーンにQPixmapを使って、いろいろとRubyとC++の違いに戸惑いつつ、ビルドエラーを取っていったところ、何とかペンの軌跡の追随はできるようになりました。
まあ、描けましたが・・。
でも、遅いですね。イベントが発生するたびに全画面を描き直ししているので、仕方ないところでしょうか・・。更新された部分のみの描き直しで高速化できるのか・・。それとも根本的にやり方を変える必要があるのか・・。ま、最適化はおいおいやっていきましょうか・・・。
だいぶ慣れてきたと思ってましたが、コードを入力し始めると、NetWalkerのキーボードの悪さが目立ちますねぇ・・・。また、慣れるかなぁ・・。また、Qt Creator のエディタが遅い上に、ときどきフリーズしてしまいます。なので、前回設定した通り外部エディタを使っていますが、この外部エディタの立ち上げがいちいち面倒ですね・・。やっぱり、Qt Creator のエディタを使いたいです・・。
ちなみに、追加したコードはこんな感じ。
とりあえず、デバグコードのみ
で、ビルド&実行。・・・無事、動作しました。
ちゃんとログが出てます
さて、ちゃんと実装しますか・・。QPainterの使い方は以前大雑把に触れましたが、実際に実装してみると、ちゃんと線が引けませんね・・。一瞬、線が出てきてるんですが、すぐに消えてしまっています。しかも、やたらと実行時エラーが出ています。
実行エラーについては、painterをend()させ忘れていたので、それをすることで解決。一方、一瞬出て、すぐ消えると言うのは、描画をするたびにQWidgetが一から書き直されているための様ですね・・。これ、どうすればよかったですかねぇ・・。昔書いたソースを見てみたら、paintEvent()では、全ての描画をやり直してます・・。描画についてはこんな感じかな・・。
多分こんな感じ
ちなみに、たしか、レイアウトなども paintEvent() のタイミングで動作したと思うので、QWidget のサイズをレイアウトに任せている場合は、レイアウト後にサイズを取るために、resizeEvent()でサイズを取得する必要があります。
ちょっと、考えなおしが必要ですね・・。データを保持するクラスを作成して、widgetからはそちらにペンの位置などを指示するだけにします。
さて、編集します。NetWalker画面が広いので便利です。エディタが2枚開けます。
ヘッダを見ながらコーディング
オフスクリーンにQPixmapを使って、いろいろとRubyとC++の違いに戸惑いつつ、ビルドエラーを取っていったところ、何とかペンの軌跡の追随はできるようになりました。
まあ、描けましたが・・。
でも、遅いですね。イベントが発生するたびに全画面を描き直ししているので、仕方ないところでしょうか・・。更新された部分のみの描き直しで高速化できるのか・・。それとも根本的にやり方を変える必要があるのか・・。ま、最適化はおいおいやっていきましょうか・・・。
Qt Creatorでの外部エディタの設定 [NetWalker]
Qt Creator でファイルを外部のエディタで開くことはできないのかなぁ・・?とメニューを眺めていたところ、「Edit」→「Advanced」→「Open in External Editor」と言うメニューから開くことができる様です。
やっぱりありますね
さっそく試してみたところ、viが立ち上がりました・・。
viはちょっと・・
さて、他のエディタに変更できないかと「Tools」→「Options...」でオプション設定のウィンドウを立ち上げてみたところ、ありますね。「External editor」と言う項目です。
ありました
デフォルトでは、viが設定されていますが、色々とオプション項目が設定されています。とりあえずは、geditにしたいと思いますが、起動オプションにはどんなものがあるんでしょうか・・?
Qt Creator 側から得られる情報は、エディタのコマンドを書く欄の横にある「?」のボタンを押して確認したところ、下記の様な感じです。ファイル名、行番号の指定はしたいですね。
ファイル名(%f)と行番号(%l)がほしい
一方、geditのヘルプを見てみたところ、とりあえずファイルの指定は「gedit file1 file2」の様な感じでいいようです。行番号指定は見当たりませんね・・。
ヘルプ
見つからないので、一応「gedit %f -l %l」で設定しておきました。ま、おいおい探しましょう。
行番号指定はてきとう
さっそく、メニューに書かれていたショートカット「Alt+V」を押してみたところ、反応がありません。その横にある「Alt+I」でもそのまま・・。メニューから選択してみましたが、反応なし・・。フルスクリーンを解除して確認したところ、やっぱり立ち上がっていません。それどころか、Qt Creatorに戻ったところ、真っ白に・・。
なんで?
色々触ってみたところ、「Window」→「Show Sidebar」で元に戻りました・・。ショートカットが「Alt+O」ですね・・。「Alt+I」をするつもりが、こっちをしてしまったのかも知れません・・。それにしても全部消えるのもおかしい気もするんですけどねぇ・・。
よかった
それにしてもショートカットが利きません・・。仕方がないので、メニューで実行・・・。あれ?起動しませんね・・。
ためしに端末で試してみたところ…。適当に設定した「-l」オプションが悪さをしていたようです・・。
不明なオプションだそうです
改めて、ヘルプを読んでみたところ、行数指定のオプションは「+」だそうです。「gedit +%l %f」と指定しなおすことで、問題なく行指定ができました。でも、立ち上がりましたが、Qt Creatorで表示されているファイルが開かれますね・・。Projectペインで選択しているファイルを開いてくれるとうれしいんですが・・。まあ、ええか。
後、外部エディタ起動用のキーバインドも変えたい気がしますね・・。
つづく・・・。
やっぱりありますね
さっそく試してみたところ、viが立ち上がりました・・。
viはちょっと・・
さて、他のエディタに変更できないかと「Tools」→「Options...」でオプション設定のウィンドウを立ち上げてみたところ、ありますね。「External editor」と言う項目です。
ありました
デフォルトでは、viが設定されていますが、色々とオプション項目が設定されています。とりあえずは、geditにしたいと思いますが、起動オプションにはどんなものがあるんでしょうか・・?
Qt Creator 側から得られる情報は、エディタのコマンドを書く欄の横にある「?」のボタンを押して確認したところ、下記の様な感じです。ファイル名、行番号の指定はしたいですね。
ファイル名(%f)と行番号(%l)がほしい
一方、geditのヘルプを見てみたところ、とりあえずファイルの指定は「gedit file1 file2」の様な感じでいいようです。行番号指定は見当たりませんね・・。
ヘルプ
見つからないので、一応「gedit %f -l %l」で設定しておきました。ま、おいおい探しましょう。
行番号指定はてきとう
さっそく、メニューに書かれていたショートカット「Alt+V」を押してみたところ、反応がありません。その横にある「Alt+I」でもそのまま・・。メニューから選択してみましたが、反応なし・・。フルスクリーンを解除して確認したところ、やっぱり立ち上がっていません。それどころか、Qt Creatorに戻ったところ、真っ白に・・。
なんで?
色々触ってみたところ、「Window」→「Show Sidebar」で元に戻りました・・。ショートカットが「Alt+O」ですね・・。「Alt+I」をするつもりが、こっちをしてしまったのかも知れません・・。それにしても全部消えるのもおかしい気もするんですけどねぇ・・。
よかった
それにしてもショートカットが利きません・・。仕方がないので、メニューで実行・・・。あれ?起動しませんね・・。
ためしに端末で試してみたところ…。適当に設定した「-l」オプションが悪さをしていたようです・・。
不明なオプションだそうです
改めて、ヘルプを読んでみたところ、行数指定のオプションは「+」だそうです。「gedit +%l %f」と指定しなおすことで、問題なく行指定ができました。でも、立ち上がりましたが、Qt Creatorで表示されているファイルが開かれますね・・。Projectペインで選択しているファイルを開いてくれるとうれしいんですが・・。まあ、ええか。
後、外部エディタ起動用のキーバインドも変えたい気がしますね・・。
つづく・・・。
やっと、ペン動作の捕捉 [NetWalker]
前回、「Qt Creatorのエディタが遅いので、カスタマイズできないか」と書きましたが、メニューの「Tools」→「Options」で設定はできる様です。が、速度を改善できる様な項目は無さげですねぇ・・。とりあえず、「Text Editor」→「Completion」の項目はすべてチェックをはずしましたが、特に改善されていない様です・・。カーソルキーを押しっぱなしにしてると、カーソルキーのキーイベントがたまる様で、鬱陶しいです・・。
それはさておき、やっと追加コードを書いていくことにしましょう。できれば、エディタでの編集はアルゴリズムのみで、関数の追加などはできる限り Qt Creator 上から行いたいんですが、可能なのでしょうか・・?
Objectの欄にある「widget」を右クリックしたところ、該当しそうなメニューは「Change signals/slots...」と「Go to slot...」でしょうか・・。SignalとSlotは編集できるが、他は無理なようですね。まあ、それは仕方がないか・・。
Morphも気になる
両方見てみたところ、「Change signals/slots...」でSlotの追加が可能な様です。継承元のQWidgetのpublicなスロットはデフォルトで表示されている様です。ですが、まずは、protectedなQWidgetのSlotの中からmousePressEvent()を追加してみます。
「Change signals/slots...」で表示された「Signals/Slots of QtlCanvas」のダイアログでSlots側の「+」ボタンを押し、Slot名を入力して「OK」。
publicのものがグレーアウトされているのも気になる
「qtlcanvas.cpp」「qtlcanvs.h」を確認しましたが、特にコードは追加されていませんね・・。何か必要なんでしょうか・・?Qt Designer上でのSignal/Slot関連の説明ページを見てみると、このメニューは、Qt Designer上で追加した要素同士のコネクト用で、マウスのイベントはこのメニューで追加するのはおかしいんですかね・・・。と言うか、マウスのイベント関連はスロットと言うより、単純なイベントハンドラと考えた方が良さげです。そして、イベントハンドラを追加する手段はQt Designer上ではなさそうですね。やっぱり、これは削除しました。
*
仕方がないので、手動で追加していくことにします。まずは、「mousePressEvent()」。・・・エディタ、使いにくいですね・・。遅い上に思い通りに動いてくれません・・。それはさておき、とりあえず、この関数に来ることだけを確認したいので、何か出力したいんですが、標準出力に文字列を出せば、どこかコンソールみたいなところに出てくるんですかね・・。と思って、クラス一覧を眺めていたら、「QDebug」と言うクラスが用意されていました。これを使ってみることにします。
・・・入力してたら、固まりました・・。なんで??ファイルを切り替えて、戻ってきたら動くように・・。何か変なコマンドでも入れたんでしょうか・・?
ともかく、「qtlcanvas.h」に関数を追加し、「qtlcanvas.cpp」に次の行を入力してビルドします。
エディタが使いにくい・・
エラーが出ましたね・・。「invalid use of incomplete type 'struct QDebug'」「forward declaration of 'struct QDebug'」の二つです。
QDebugが使えないらしい
ん~・・。警告はともかくエラーの方はあれですね・・。何かヘッダとかでも読まないいけないんでしょうか・・?色々読んでいたところ、<QDebug>と言うヘッダファイルを読み必要がある様です。「qtlcanvas.h」でそのヘッダを読むようにします。
QDebugを読み込む
で、ビルド。
警告は出ますが、ビルドは通った様です。
引数はまだ使ってません
実行します。
おぉ~!タッチするたびに期待してた文字列が出るようになりました。
楽にデバグできそう
長かったですが、やっとプログラミングし始めるところまで来れましたねぇ・・。
エディタを何とかしたいな・・。つづく。
【参考】
・Qt Designer's Signals and Slots Editing Mode
・Debugging Techniques
それはさておき、やっと追加コードを書いていくことにしましょう。できれば、エディタでの編集はアルゴリズムのみで、関数の追加などはできる限り Qt Creator 上から行いたいんですが、可能なのでしょうか・・?
Objectの欄にある「widget」を右クリックしたところ、該当しそうなメニューは「Change signals/slots...」と「Go to slot...」でしょうか・・。SignalとSlotは編集できるが、他は無理なようですね。まあ、それは仕方がないか・・。
Morphも気になる
両方見てみたところ、「Change signals/slots...」でSlotの追加が可能な様です。継承元のQWidgetのpublicなスロットはデフォルトで表示されている様です。ですが、まずは、protectedなQWidgetのSlotの中からmousePressEvent()を追加してみます。
「Change signals/slots...」で表示された「Signals/Slots of QtlCanvas」のダイアログでSlots側の「+」ボタンを押し、Slot名を入力して「OK」。
publicのものがグレーアウトされているのも気になる
「qtlcanvas.cpp」「qtlcanvs.h」を確認しましたが、特にコードは追加されていませんね・・。何か必要なんでしょうか・・?Qt Designer上でのSignal/Slot関連の説明ページを見てみると、このメニューは、Qt Designer上で追加した要素同士のコネクト用で、マウスのイベントはこのメニューで追加するのはおかしいんですかね・・・。と言うか、マウスのイベント関連はスロットと言うより、単純なイベントハンドラと考えた方が良さげです。そして、イベントハンドラを追加する手段はQt Designer上ではなさそうですね。やっぱり、これは削除しました。
*
仕方がないので、手動で追加していくことにします。まずは、「mousePressEvent()」。・・・エディタ、使いにくいですね・・。遅い上に思い通りに動いてくれません・・。それはさておき、とりあえず、この関数に来ることだけを確認したいので、何か出力したいんですが、標準出力に文字列を出せば、どこかコンソールみたいなところに出てくるんですかね・・。と思って、クラス一覧を眺めていたら、「QDebug」と言うクラスが用意されていました。これを使ってみることにします。
・・・入力してたら、固まりました・・。なんで??ファイルを切り替えて、戻ってきたら動くように・・。何か変なコマンドでも入れたんでしょうか・・?
ともかく、「qtlcanvas.h」に関数を追加し、「qtlcanvas.cpp」に次の行を入力してビルドします。
エディタが使いにくい・・
エラーが出ましたね・・。「invalid use of incomplete type 'struct QDebug'」「forward declaration of 'struct QDebug'」の二つです。
QDebugが使えないらしい
ん~・・。警告はともかくエラーの方はあれですね・・。何かヘッダとかでも読まないいけないんでしょうか・・?色々読んでいたところ、<QDebug>と言うヘッダファイルを読み必要がある様です。「qtlcanvas.h」でそのヘッダを読むようにします。
QDebugを読み込む
で、ビルド。
警告は出ますが、ビルドは通った様です。
引数はまだ使ってません
実行します。
おぉ~!タッチするたびに期待してた文字列が出るようになりました。
楽にデバグできそう
長かったですが、やっとプログラミングし始めるところまで来れましたねぇ・・。
エディタを何とかしたいな・・。つづく。
【参考】
・Qt Designer's Signals and Slots Editing Mode
・Debugging Techniques
Qt Creatorでの独自クラスの追加・・ [NetWalker]
前回の結果から、どうもQtl_Canvasにテキストラベルを貼る時点でおかしくなるような雰囲気です。と言うか、テキストラベルを貼った時点で、ビルド対象になってるのかもしれません・・。前々回の記事で読み飛ばしたドキュメントをちゃんと読むことにしましょう。・・・遠回りしただけですかね。
*
なんか、pluginという仕組みを使って、かなり回りくどそうなやり方が必要なみたいですね・・。ここの手法が私の意図しているものと同じなのかどうかが判断できないんですが、とりあえず習ってみることにします。大回りして、元に戻ってしまうようなことがないといいんですけどねぇ・・。
こちらを読んでいたら、前回出てきた「ui_mainwindow.h」の正体がわかりました。これはuic(User Interface Compiler)で.uiファイル(この場合は「mainwindow.ui」ですね)から生成されたヘッダファイルだそうです。
う~ん、このpluginの仕組みはもっとちゃんとしたカスタムウィジェットの利用に使うような気がしますね。今回、ペンの軌跡を取って、線を描くだけなのでこれは当たらない様な気がしました。そして、目的のクラスはいちいち.uiファイルを作成する必要がない様な気がします・・。
*
再度、仕切り直しです。まず、QWidgetのサブクラスとして、QtlCanvasクラスを作成します。前回、コンテクストメニューから「Add New」で、「Qt Designer Form Class」を作成しましたが、普通に「C++ Class」を選択して作成します。
ベースクラスにQtのクラスが指定出来ます
ベースにQWidgetを指定します。これで、「qtlcanvas.cpp」と「qtlcanvas.h」が生成されました。
続いて、Qt Designer から widget を右クリックで「promote to」で、QtlCanvasを設定します。で、「Promote」。
プロモートします
とりあえず、これでビルドを試します。
エラーが出ましたね。QtlCanvasのコンストラクタがないと怒られています。無事、「qtlcanvas.cpp」もビルド対象に組み込まれてるみたいですね。
まあ、実装してないですからね
コンストラクタくらい自動で作成してくれんのかいなと思ってソースを確認しましたら、作成してくれていました。でも、引数が違います。QWidgetのコンストラクタの引数になっていないんですね・・。まあ、これは仕方がないか・・。
なるほど・・・
「qtlcanvas.h」「qtlcanvas.cpp」の引数を修正して、ビルドしたところ、引数が使われていないとの警告が出ましたが、問題なくビルドは通りました。実行してもOK。
修正
とりあえず、これで、やっとコーディングしていく環境が整いましたねぇ。今回、ソースをちょっとだけ編集したのですが、動作が重いです・・。処理が追い付かず、キーイベントが貯まる様で、ちょっと耐えられないレベルですね・・。処理が追い付かないのならば、カラーリングとかいらないんで、切ることはできないんでしょうか・・?
【参考】
・Customizing Qt Designer Forms
・Using Custom Widgets with Qt Designer
・Creating Custom Widgets for Qt Designer
・Using a Designer .ui File in Your Application
*
なんか、pluginという仕組みを使って、かなり回りくどそうなやり方が必要なみたいですね・・。ここの手法が私の意図しているものと同じなのかどうかが判断できないんですが、とりあえず習ってみることにします。大回りして、元に戻ってしまうようなことがないといいんですけどねぇ・・。
こちらを読んでいたら、前回出てきた「ui_mainwindow.h」の正体がわかりました。これはuic(User Interface Compiler)で.uiファイル(この場合は「mainwindow.ui」ですね)から生成されたヘッダファイルだそうです。
う~ん、このpluginの仕組みはもっとちゃんとしたカスタムウィジェットの利用に使うような気がしますね。今回、ペンの軌跡を取って、線を描くだけなのでこれは当たらない様な気がしました。そして、目的のクラスはいちいち.uiファイルを作成する必要がない様な気がします・・。
*
再度、仕切り直しです。まず、QWidgetのサブクラスとして、QtlCanvasクラスを作成します。前回、コンテクストメニューから「Add New」で、「Qt Designer Form Class」を作成しましたが、普通に「C++ Class」を選択して作成します。
ベースクラスにQtのクラスが指定出来ます
ベースにQWidgetを指定します。これで、「qtlcanvas.cpp」と「qtlcanvas.h」が生成されました。
続いて、Qt Designer から widget を右クリックで「promote to」で、QtlCanvasを設定します。で、「Promote」。
プロモートします
とりあえず、これでビルドを試します。
エラーが出ましたね。QtlCanvasのコンストラクタがないと怒られています。無事、「qtlcanvas.cpp」もビルド対象に組み込まれてるみたいですね。
まあ、実装してないですからね
コンストラクタくらい自動で作成してくれんのかいなと思ってソースを確認しましたら、作成してくれていました。でも、引数が違います。QWidgetのコンストラクタの引数になっていないんですね・・。まあ、これは仕方がないか・・。
なるほど・・・
「qtlcanvas.h」「qtlcanvas.cpp」の引数を修正して、ビルドしたところ、引数が使われていないとの警告が出ましたが、問題なくビルドは通りました。実行してもOK。
修正
とりあえず、これで、やっとコーディングしていく環境が整いましたねぇ。今回、ソースをちょっとだけ編集したのですが、動作が重いです・・。処理が追い付かず、キーイベントが貯まる様で、ちょっと耐えられないレベルですね・・。処理が追い付かないのならば、カラーリングとかいらないんで、切ることはできないんでしょうか・・?
【参考】
・Customizing Qt Designer Forms
・Using Custom Widgets with Qt Designer
・Creating Custom Widgets for Qt Designer
・Using a Designer .ui File in Your Application
Qt Creatorでのファイルの削除 [NetWalker]
エラーの原因がよくわからないので、一旦元に戻ることにしました。追加したQtl_Canvas関連のファイルを「Projects」の項目から削除、MainWindowClassのwidgetをQtl_Canvasから「Demote」。前回、これだけじゃあファイルが削除されていなかったので、「ファイル・ブラウザ」で該当ファイルを手動で削除。これで「Build」→「Clean Project」、「Build Project」をしてみましたが、エラーが出てしまいます。「`ui_mainwindow.h'に必要なターゲット`qtl_canvas.h'をmakeするルールがありません」とか・・。
何が残ってんの・・?
う〜ん、まだなんか残ってるんですかねぇ〜。「Rebuild Project」とか「Clean All」とかいろいろ試してみましたが、駄目ですね・・。そもそもこの「ui_mainwindow.h」と言うファイルはQt Creator上に見えていません…。
プロジェクトのディレクトリで「canvas」でgrepをかけたところ、「Makefile.Debug」と言うファイルと「Makefile.Release」と言うファイルに残っているみたいです・・。
残ってますね・・
ファイルを確認したところ、確かに残っている様です・・・。これ、どうやったら消せるんでしょうねぇ・・。
足したファイルを消せないということはないと思うので、何か削除の作業に不備があったんでしょう・・。試しに Qt Creator で「mainwindow.ui」を右クリックして「Remove File...」を選択したところ、出てきたダイアログに「Delete file permanently」と言うチェックボックスがありました・・。これのチェックが必要なのか・・? 前、チェックしてなかったのか・・?
わからないですねぇ・・。
これ?
もう一回、フォームを作成して、Promoteして、その後、削除してみることにします・・。作成して、追加して、念のため、ビルド・・・。
あれっ?なんかエラーが出ないですね・・。よくわからないので、再度Qtl_Canvasの方にテキストラベルを貼り付けます・・。再度、ビルド。
おぉ~、今度は前回と同じエラーが出ました。テキストラベルの貼り付けが問題だったんでしょうか・・。テキストラベルをはがしてみましょう。
同じエラーが出ました。最初はビルドされていなくて、テキストラベルを張り付けることで、プロジェクトのビルド項目に付け加えられたというような感じなんでしょうか・・? どうもファイルの削除がそのままその前の状態に戻るという動作になっていないようですね・・。
今度は、「Delete file permanently」のチェックボックスにチェックを入れて、削除していきます。「ファイル・ブラウザ」で確認すると、Qt Creator上で削除指定したファイルは消えていますが、Projectsの欄に出ていなかった「ui_qtl_canvas.h」が残ってますね・・。
これが残ってしまう・・
仕方がないので、プロジェクトのトップを右クリック「Add Existing Files...」で強制的に「ui_qtl_canvas.h」を追加します。
間違ってる気もしますが・・
で、削除。ファイルが消えました。これで、Clean Project をして、再度ビルド。・・・・エラーが出ます。よく見たら、Objectの画面で、widgetからQtl_CanvasをDemoteするのを忘れてました…。Demoteして、Clean Projectをして、再度ビルド・・・。やっと、元の状態に戻りました。さっきの強制的にプロジェクトに追加する行為は不要かもしれませんね・・。と言うか、たぶん不要。
まったく、進捗してませんが、長くなったので、つづく・・・。
何が残ってんの・・?
う〜ん、まだなんか残ってるんですかねぇ〜。「Rebuild Project」とか「Clean All」とかいろいろ試してみましたが、駄目ですね・・。そもそもこの「ui_mainwindow.h」と言うファイルはQt Creator上に見えていません…。
プロジェクトのディレクトリで「canvas」でgrepをかけたところ、「Makefile.Debug」と言うファイルと「Makefile.Release」と言うファイルに残っているみたいです・・。
残ってますね・・
ファイルを確認したところ、確かに残っている様です・・・。これ、どうやったら消せるんでしょうねぇ・・。
足したファイルを消せないということはないと思うので、何か削除の作業に不備があったんでしょう・・。試しに Qt Creator で「mainwindow.ui」を右クリックして「Remove File...」を選択したところ、出てきたダイアログに「Delete file permanently」と言うチェックボックスがありました・・。これのチェックが必要なのか・・? 前、チェックしてなかったのか・・?
わからないですねぇ・・。
これ?
もう一回、フォームを作成して、Promoteして、その後、削除してみることにします・・。作成して、追加して、念のため、ビルド・・・。
あれっ?なんかエラーが出ないですね・・。よくわからないので、再度Qtl_Canvasの方にテキストラベルを貼り付けます・・。再度、ビルド。
おぉ~、今度は前回と同じエラーが出ました。テキストラベルの貼り付けが問題だったんでしょうか・・。テキストラベルをはがしてみましょう。
同じエラーが出ました。最初はビルドされていなくて、テキストラベルを張り付けることで、プロジェクトのビルド項目に付け加えられたというような感じなんでしょうか・・? どうもファイルの削除がそのままその前の状態に戻るという動作になっていないようですね・・。
今度は、「Delete file permanently」のチェックボックスにチェックを入れて、削除していきます。「ファイル・ブラウザ」で確認すると、Qt Creator上で削除指定したファイルは消えていますが、Projectsの欄に出ていなかった「ui_qtl_canvas.h」が残ってますね・・。
これが残ってしまう・・
仕方がないので、プロジェクトのトップを右クリック「Add Existing Files...」で強制的に「ui_qtl_canvas.h」を追加します。
間違ってる気もしますが・・
で、削除。ファイルが消えました。これで、Clean Project をして、再度ビルド。・・・・エラーが出ます。よく見たら、Objectの画面で、widgetからQtl_CanvasをDemoteするのを忘れてました…。Demoteして、Clean Projectをして、再度ビルド・・・。やっと、元の状態に戻りました。さっきの強制的にプロジェクトに追加する行為は不要かもしれませんね・・。と言うか、たぶん不要。
まったく、進捗してませんが、長くなったので、つづく・・・。
Qtクラスの継承 - その2 [NetWalker]
前回の記事では、試行錯誤で多少混乱した感じになったので、いったん前回の作業をリセットすることにします。Objectペインのwidgetを右クリックし「Demote」、これだけでは、Promoteダイアログに前回設定した内容が残っているので、それも削除。そして、Projectsペインにあった作成したフォームに関する.h、.cpp、.uiファイルを削除、メニューから「Build」→「Clean All」で念のため掃除。そしてもいちど実行をかけてみました。
*
たぶん、これで元に戻っただろうということで、あらためてObjectペインのwidgetを右クリックして「Promote to」・・・。「Promote to」になってますね・・。「Promote」じゃなかったっけ・・?
最初からこうか・・?
ま、気にせずに前回書いたのと同じクラスを再度設定することにします。そして「Add」して「Promote」。・・・「Global Include」と言う項目の意味がよくわかりませんね・・。ちゃんとドキュメントを読んだ方がいいかもしれません。
*
ドキュメントを読んでみたところ、この promote の仕組みは、外部で提供されているソースを見ることができない Widget にも活用できる様で、その場合は、親クラスとなっているQtで提供されているクラスを指定して place holder として使うようです。で、自分で作成する際は、なんか特殊な事をする必要がある様子。plug-in として、プロジェクトを一個作る必要があるような感じもありますが、よくわかりませんね・・。と言うか、面倒ですね・・。とりあえず、このまま突っ走って、詰まったら戻ってくることにします。
ちなみに、「Global Include」に関する記載は見当たりません。デフォルトでチェックが入っていなかったので、とりあえず、そのままにしておきます。なんとなく、プロジェクト外にあるファイルの場合にチェックするような気がしていますが、どうでしょうかねぇ・・。
さて、promote しただけでは、特にヘッダファイルは作成されていません。と言うことで、再度、以前の通り、「Qt Designer Form Class」を作成しなおします。作成したところ、「qtl_canvas.h と qtl_canvas.cpp はファイルが既にある」とか言う警告が出てきました(キャプチャできない・・)。さっき削除したつもりが、ファイルの実体は削除されていなかった様ですね。ここは、上書きしときます。
ちなみに、作成した物のオブジェクト名が「Form」になってますね・・。
う~ん
この作成した Qtl_Canvas と MainWindow はちゃんと結びついているんでしょうか(たぶん結びついていない)? それを確かめるために、Qtl_Canvas に適当なラベルを貼り付けます。
うまく結びつけばいいですが・・
これで、ビルドしてみます。「Build」→「Build Project」。
おぉ・・・。エラーがいっぱい出てきました・・。エラー6、警告4ですね。
それ以前…
先頭が、「qtl_canvas.cpp」での「invalid use of incomplete type 'struct Ui::QtlCanvas'」となってます。一応このソースでは、「qtl_canvas.h」を読み込んでいて、そこでちゃんと宣言されている様な気もするんですが・・。
何が問題?
と思ったら、次のエラーメッセージで「qtl_canvas.h」での「forward declaration of 'struct Ui::Qtl_Canvas'」と出てますね・・。
namespaceの宣言って正確には知らないんですよねぇ・・
namespace の宣言のところで、エラーが出てますね。
別に、自分でコードを足したわけでもなし・・、どうしようかな・・。
【参考】
・Using Custom Widgets with Qt Designer
・Creating Custom Widgets for Qt Designer
・Custom Widget Plugin Example
・How to Create Qt Plugins
*
たぶん、これで元に戻っただろうということで、あらためてObjectペインのwidgetを右クリックして「Promote to」・・・。「Promote to」になってますね・・。「Promote」じゃなかったっけ・・?
最初からこうか・・?
ま、気にせずに前回書いたのと同じクラスを再度設定することにします。そして「Add」して「Promote」。・・・「Global Include」と言う項目の意味がよくわかりませんね・・。ちゃんとドキュメントを読んだ方がいいかもしれません。
*
ドキュメントを読んでみたところ、この promote の仕組みは、外部で提供されているソースを見ることができない Widget にも活用できる様で、その場合は、親クラスとなっているQtで提供されているクラスを指定して place holder として使うようです。で、自分で作成する際は、なんか特殊な事をする必要がある様子。plug-in として、プロジェクトを一個作る必要があるような感じもありますが、よくわかりませんね・・。と言うか、面倒ですね・・。とりあえず、このまま突っ走って、詰まったら戻ってくることにします。
ちなみに、「Global Include」に関する記載は見当たりません。デフォルトでチェックが入っていなかったので、とりあえず、そのままにしておきます。なんとなく、プロジェクト外にあるファイルの場合にチェックするような気がしていますが、どうでしょうかねぇ・・。
さて、promote しただけでは、特にヘッダファイルは作成されていません。と言うことで、再度、以前の通り、「Qt Designer Form Class」を作成しなおします。作成したところ、「qtl_canvas.h と qtl_canvas.cpp はファイルが既にある」とか言う警告が出てきました(キャプチャできない・・)。さっき削除したつもりが、ファイルの実体は削除されていなかった様ですね。ここは、上書きしときます。
ちなみに、作成した物のオブジェクト名が「Form」になってますね・・。
う~ん
この作成した Qtl_Canvas と MainWindow はちゃんと結びついているんでしょうか(たぶん結びついていない)? それを確かめるために、Qtl_Canvas に適当なラベルを貼り付けます。
うまく結びつけばいいですが・・
これで、ビルドしてみます。「Build」→「Build Project」。
おぉ・・・。エラーがいっぱい出てきました・・。エラー6、警告4ですね。
それ以前…
先頭が、「qtl_canvas.cpp」での「invalid use of incomplete type 'struct Ui::QtlCanvas'」となってます。一応このソースでは、「qtl_canvas.h」を読み込んでいて、そこでちゃんと宣言されている様な気もするんですが・・。
何が問題?
と思ったら、次のエラーメッセージで「qtl_canvas.h」での「forward declaration of 'struct Ui::Qtl_Canvas'」と出てますね・・。
namespaceの宣言って正確には知らないんですよねぇ・・
namespace の宣言のところで、エラーが出てますね。
別に、自分でコードを足したわけでもなし・・、どうしようかな・・。
【参考】
・Using Custom Widgets with Qt Designer
・Creating Custom Widgets for Qt Designer
・Custom Widget Plugin Example
・How to Create Qt Plugins
Qtクラスの継承 [NetWalker]
さて、実装していきましょう。
QPainterで描画を行うわけですが、ペンでタッチされてからリリースされるまでは同じQPainterのオブジェクトを使用したいと思っています。なので、まずQPainterを保持するメンバ変数を用意しましょう。と言うことで、QWidgetにメンバ変数追加!・・・と思いましたが、Qtで用意されているクラスにそんなことできませんね・・。これを継承して新しいクラスを作らないといけませんが、Qt Designer上でそんなことができるんでしょうか・・?
ドキュメントを眺めていると「Using a Designer .ui File in Your Application」というページがあったので、見てみましたが、特にそのような記載はなし。よくわからないので、とりあえず、メニューから「File」→「New」を選択してみると「Qt Designer Form Class」という項目がありました。
これでできるかな・・?
「OK」で選択して次に進むと、「templates/forms」の項目に「Widget」と言うのがあるので選択してみます。で、「Next >」。
いろいろありますねぇ・・
続いて、クラス名、ヘッダファイル名、ソースファイル名、.uiファイル名の設定です。クラス名を入れるとその他のファイル名も追随してくれますね。便利。ま、設定して「Next >」。
クラス名に追随してくれます
で、プロジェクトに追加ですね「Finish」。
フォームとソースが追加されます
これで、プロジェクトにフォームが一つ追加されました。
クラスの名前は「Qtl_Canvas」にしたんですが、追加した「qtl_canvas.h」を見てみると、QWidgetクラスを継承したクラスとなっています。ソースはいじれる様なので、これで好きに動作を記述できるような気がしますが、元のmainwindowへの追加はできますでしょうか・・?
簡単にサブクラスが作れますね
色々試していたところ、下記でできそうな感じです。まずは、既にフォームに追加しているwidgetを右クリック。「Promote」というメニューを選択すると、ベースクラスを選択し、クラス名等を入力して「Add」すれば、継承したクラスとして扱えるようになるようです。
追加した後です
メニューにあるなら、どこかに説明があるのでは?と思って、あらためてドキュメントを眺めていたところ、ありました。と言うことで、カスタムウィジェットもQt Designer で扱える雰囲気ですね。でも、先程作ったフォームと同じ名前のクラスを追加したんですが、追加は手書きで行いましたし、今のところ作成したフォームとこの継承したクラスとが関連付けされていないような気がしています・・。ちなみに、今回作成したフォームは上に何か置くわけでもないので、いちいちフォームを作成する必要もないですね・・。
さて、どうしましょうかね・・。つづく。
【参考】
・Using a Designer .ui File in Your Application
・Calculator Form Example
・Using Custom Widgets with Qt Designer
QPainterで描画を行うわけですが、ペンでタッチされてからリリースされるまでは同じQPainterのオブジェクトを使用したいと思っています。なので、まずQPainterを保持するメンバ変数を用意しましょう。と言うことで、QWidgetにメンバ変数追加!・・・と思いましたが、Qtで用意されているクラスにそんなことできませんね・・。これを継承して新しいクラスを作らないといけませんが、Qt Designer上でそんなことができるんでしょうか・・?
ドキュメントを眺めていると「Using a Designer .ui File in Your Application」というページがあったので、見てみましたが、特にそのような記載はなし。よくわからないので、とりあえず、メニューから「File」→「New」を選択してみると「Qt Designer Form Class」という項目がありました。
これでできるかな・・?
「OK」で選択して次に進むと、「templates/forms」の項目に「Widget」と言うのがあるので選択してみます。で、「Next >」。
いろいろありますねぇ・・
続いて、クラス名、ヘッダファイル名、ソースファイル名、.uiファイル名の設定です。クラス名を入れるとその他のファイル名も追随してくれますね。便利。ま、設定して「Next >」。
クラス名に追随してくれます
で、プロジェクトに追加ですね「Finish」。
フォームとソースが追加されます
これで、プロジェクトにフォームが一つ追加されました。
クラスの名前は「Qtl_Canvas」にしたんですが、追加した「qtl_canvas.h」を見てみると、QWidgetクラスを継承したクラスとなっています。ソースはいじれる様なので、これで好きに動作を記述できるような気がしますが、元のmainwindowへの追加はできますでしょうか・・?
簡単にサブクラスが作れますね
色々試していたところ、下記でできそうな感じです。まずは、既にフォームに追加しているwidgetを右クリック。「Promote」というメニューを選択すると、ベースクラスを選択し、クラス名等を入力して「Add」すれば、継承したクラスとして扱えるようになるようです。
追加した後です
メニューにあるなら、どこかに説明があるのでは?と思って、あらためてドキュメントを眺めていたところ、ありました。と言うことで、カスタムウィジェットもQt Designer で扱える雰囲気ですね。でも、先程作ったフォームと同じ名前のクラスを追加したんですが、追加は手書きで行いましたし、今のところ作成したフォームとこの継承したクラスとが関連付けされていないような気がしています・・。ちなみに、今回作成したフォームは上に何か置くわけでもないので、いちいちフォームを作成する必要もないですね・・。
さて、どうしましょうかね・・。つづく。
【参考】
・Using a Designer .ui File in Your Application
・Calculator Form Example
・Using Custom Widgets with Qt Designer
Qtでのペン操作の追随と描画への準備 [NetWalker]
さて、「まず線でも引こうか」と書きましたが、いい加減まどろっこしいので、やっぱりペンの補足と線の描画を一気にやって行きたいと思います。
どこから見ればいいかなぁとドキュメントを眺めていましたが、ペン(と言うか、マウス)のイベント捕捉についての項目はなさそうですね・・。仕方がないので、QWidgetの説明を見ていたところ、まさに該当しそうなところがありました。そこによると、関連ありそうなのは以下の三つのイベントですね。
と、これはいいんですが、実はQtでこれらのイベントを補足する際はSignalとSlotと言うQt独特の仕組みを理解しておく必要があります。上記は全てイベントハンドラ関数になるんですが、この仕組みの中では「Slot」に該当します。まあ、詳しくはこちらをご覧ください。
・・と思いましたが、用意されているSlotを使うだけなら、理解は不要かもしれませんね・・。Ruby/Qteの時はSignalを補足するために事前に準備(と言うほどのものでもありませんが・・)が必要でしたが、今回ドキュメントを読んでいてもそのような記載がありませんね。C++の場合はそのあたりは、意識せずに使えるのかもしれません。
以上でペンの捕捉についてはたぶん問題ないと思います。次は描画について。以前にちらっと見てたんですが、描画の手順については書かれていないんですよね。Zaurusでのプログラミングの経験とQPainterの詳細の説明から、だいたい下記のような手順で描画が可能と思われます。
これらを、先程のマウスイベントの処理のところにあてこめば描画できると思われます。一応、見直そうと思ってドキュメントを見てみたんですが、昔とあんまり変わっていませんね。
次回から実際の作業に移りたいと思います。スムーズに行けばいいんですけどねぇ・・。
どこから見ればいいかなぁとドキュメントを眺めていましたが、ペン(と言うか、マウス)のイベント捕捉についての項目はなさそうですね・・。仕方がないので、QWidgetの説明を見ていたところ、まさに該当しそうなところがありました。そこによると、関連ありそうなのは以下の三つのイベントですね。
mousePressEvent() | widget内でマウスボタンが押された(ペンでタッチされた)時に呼ばれる。描画の開始ポイントになりますね。 |
mouseMoveEvent() | マウスボタンが押されたままマウスが動いている(ペンでなぞっている)時に呼ばれる。線の描画を行うのに使えます。 |
mouseReleaseEvent() | マウスボタンが離された(ペンが離された)時に呼ばれる。描画の終了ポイントですね。 |
と、これはいいんですが、実はQtでこれらのイベントを補足する際はSignalとSlotと言うQt独特の仕組みを理解しておく必要があります。上記は全てイベントハンドラ関数になるんですが、この仕組みの中では「Slot」に該当します。まあ、詳しくはこちらをご覧ください。
・・と思いましたが、用意されているSlotを使うだけなら、理解は不要かもしれませんね・・。Ruby/Qteの時はSignalを補足するために事前に準備(と言うほどのものでもありませんが・・)が必要でしたが、今回ドキュメントを読んでいてもそのような記載がありませんね。C++の場合はそのあたりは、意識せずに使えるのかもしれません。
以上でペンの捕捉についてはたぶん問題ないと思います。次は描画について。以前にちらっと見てたんですが、描画の手順については書かれていないんですよね。Zaurusでのプログラミングの経験とQPainterの詳細の説明から、だいたい下記のような手順で描画が可能と思われます。
これらを、先程のマウスイベントの処理のところにあてこめば描画できると思われます。一応、見直そうと思ってドキュメントを見てみたんですが、昔とあんまり変わっていませんね。
次回から実際の作業に移りたいと思います。スムーズに行けばいいんですけどねぇ・・。
QMainWindowのcentralWidgetへのレイアウトについて [NetWalker]
さて、前回で一応、メインウィンドウ上へのウィジェットの展開ができましたが、一見、ウィンドウにフィットしたものの、枠を見る限り周りにある程度、スペースがありますし、そもそもあの「AdjustSize」と言うメニューがどういう意味を持つのかが良くわかっていません。今回、ドキュメントを読んで、大体の対応付けを確認したいと思います。
ですが、まずはソースを確認してみたいと思います。今プロジェクト中にあるファイルは次の通りです。特に自分で追加したファイルはありません。
Widgetが反映されて無い気も・・
ソースには特に目立った記述がないですね・・。それどころかWidgetやLayoutと言った、追加した項目が全くソースに現れていません。と思ったら、「mainwindow.ui」に記述されていました。UIの記述とプログラムが分離されていると言う事でしょうか?このファイルはXMLで表現されています。ですが、ソース上のどこからも直接はこのファイルが読み込まれている感じがありません・・。
「mainwindow.cpp」を見たところ、コンストラクタで「ui->setupUi(this)」と言うコードが見られます。
この処理で読み込まれるのか・・?
「ui」って何だ?と思って、「mainwindow.h」を見てみると、「Ui::MainWindowClass」のインスタンスとして宣言されていました・・。
MainWindowClassって何?
「MainWindowClass」ってどんなクラスなんでしょうね・・?上の方に「namespace」と言うキーワードが出てきていますが、これの使い方が良くわかっていません。その辺に何かあるんでしょうか?「Ui」って、何か予約されているキーワードなんですかね・・。
*
それはさておき、「mainwindow.ui」の中を見ていきます。
眺めていると、centralWidgetの中身に「QVBoxLayout」が2つ含まれています。
レイアウトが二つ・・。
私が足したのは一つだけ、それは「verticalLayout」です。それぞれのレイアウトの名前を見てみると外側のレイアウトに「_2」と言う文字が付加されています。おそらく、これが「MainWindowClass」のメニューから選択した「AdjustSize」で付加された内容ではないでしょうか。
これ、私が最初に足したレイアウトは不要な気がしますね・・。と言うことで、試しに消してみます。「Object」の箇所で「verticalLayout」を選択して右クリック→「Delete」。・・・えぇぇ~、一緒にwidgetも消えてしまいました。
消えた!
びっくりしましたが、メニューの「Edit」→「Undo」で元に戻せました。変わりに今度は「Object」のウィンドウで再度「verticalLayout」を右クリック、「Layout」→「Break Layout」。これでwidgetを残したまま、レイアウトを消去できました。これで保存して、「mainwindow.ui」の中身を確認してみます。
Layoutが二つとも消えた
どうも、レイアウトが二つとも消えてしまいましたね。良く見てみたら、widgetのサイズも小さくなってしまいました。
元通り
再度「Object」で「MainWindowClass」を右クリックして、「Layout」→「AdjustSize」。あれ?なんか、うまく行きませんね・・。
仕方がないので、もう一度verticalLayoutを追加して、widgetをその下に配置して、MainWindowClassを右クリックして「Layout」→「AdjustSize」・・・。ウィンドウ全体がちっちゃくなってしまいました。
悪化・・・
「MainWindow.ui」のソースを再度眺めてみたところ、明らかに最初の状態とは違いますね・・・。
違う・・
もう一度、加えたwidgetのレイアウトを破棄します。verticalLayoutを右クリックして、「Lay out」→「Break Layout」。で、ソースを見てみると先程のソースの通りに戻りました。
つづいて「MainWindowClass」を右クリックして、「Lay out」→「Lay Out Vertically」を選択したところ、うまく行きました!
ぴったり行きました。
これで、「MainWindow.ui」のソースを確認したところ、下記の通りです。思い通り、レイアウトが一つになっています。
すっきり
先程の画面を見直してみると、Object欄の「centralWidget」の部分のアイコンが変わってますね。縦のレイアウトのアイコンになってます。widgetのアイコンには進入禁止っぽいマークが。これがレイアウトされていないと言う印の様ですね。
以上、色々やりましたが、MainWindowClassにwidgetを追加して、枠ぴったりにレイアウトする方法は、おそらく下記の手順になる気がします。
・・・ドキュメントを読むつもりが、元に戻るのに手間取りましたね。まあ、「mainwindow.ui」のソースを見て何となく分かった気がすると言う事で、第一歩でした。
つづく。
ですが、まずはソースを確認してみたいと思います。今プロジェクト中にあるファイルは次の通りです。特に自分で追加したファイルはありません。
Widgetが反映されて無い気も・・
ソースには特に目立った記述がないですね・・。それどころかWidgetやLayoutと言った、追加した項目が全くソースに現れていません。と思ったら、「mainwindow.ui」に記述されていました。UIの記述とプログラムが分離されていると言う事でしょうか?このファイルはXMLで表現されています。ですが、ソース上のどこからも直接はこのファイルが読み込まれている感じがありません・・。
「mainwindow.cpp」を見たところ、コンストラクタで「ui->setupUi(this)」と言うコードが見られます。
この処理で読み込まれるのか・・?
「ui」って何だ?と思って、「mainwindow.h」を見てみると、「Ui::MainWindowClass」のインスタンスとして宣言されていました・・。
MainWindowClassって何?
「MainWindowClass」ってどんなクラスなんでしょうね・・?上の方に「namespace」と言うキーワードが出てきていますが、これの使い方が良くわかっていません。その辺に何かあるんでしょうか?「Ui」って、何か予約されているキーワードなんですかね・・。
*
それはさておき、「mainwindow.ui」の中を見ていきます。
眺めていると、centralWidgetの中身に「QVBoxLayout」が2つ含まれています。
レイアウトが二つ・・。
私が足したのは一つだけ、それは「verticalLayout」です。それぞれのレイアウトの名前を見てみると外側のレイアウトに「_2」と言う文字が付加されています。おそらく、これが「MainWindowClass」のメニューから選択した「AdjustSize」で付加された内容ではないでしょうか。
これ、私が最初に足したレイアウトは不要な気がしますね・・。と言うことで、試しに消してみます。「Object」の箇所で「verticalLayout」を選択して右クリック→「Delete」。・・・えぇぇ~、一緒にwidgetも消えてしまいました。
消えた!
びっくりしましたが、メニューの「Edit」→「Undo」で元に戻せました。変わりに今度は「Object」のウィンドウで再度「verticalLayout」を右クリック、「Layout」→「Break Layout」。これでwidgetを残したまま、レイアウトを消去できました。これで保存して、「mainwindow.ui」の中身を確認してみます。
Layoutが二つとも消えた
どうも、レイアウトが二つとも消えてしまいましたね。良く見てみたら、widgetのサイズも小さくなってしまいました。
元通り
再度「Object」で「MainWindowClass」を右クリックして、「Layout」→「AdjustSize」。あれ?なんか、うまく行きませんね・・。
仕方がないので、もう一度verticalLayoutを追加して、widgetをその下に配置して、MainWindowClassを右クリックして「Layout」→「AdjustSize」・・・。ウィンドウ全体がちっちゃくなってしまいました。
悪化・・・
「MainWindow.ui」のソースを再度眺めてみたところ、明らかに最初の状態とは違いますね・・・。
違う・・
もう一度、加えたwidgetのレイアウトを破棄します。verticalLayoutを右クリックして、「Lay out」→「Break Layout」。で、ソースを見てみると先程のソースの通りに戻りました。
つづいて「MainWindowClass」を右クリックして、「Lay out」→「Lay Out Vertically」を選択したところ、うまく行きました!
ぴったり行きました。
これで、「MainWindow.ui」のソースを確認したところ、下記の通りです。思い通り、レイアウトが一つになっています。
すっきり
先程の画面を見直してみると、Object欄の「centralWidget」の部分のアイコンが変わってますね。縦のレイアウトのアイコンになってます。widgetのアイコンには進入禁止っぽいマークが。これがレイアウトされていないと言う印の様ですね。
以上、色々やりましたが、MainWindowClassにwidgetを追加して、枠ぴったりにレイアウトする方法は、おそらく下記の手順になる気がします。
- widgetをドラッグして追加
- 「MainWindowClass」を右クリックして「Lay out」→「Lay Out Vertically」を選択
・・・ドキュメントを読むつもりが、元に戻るのに手間取りましたね。まあ、「mainwindow.ui」のソースを見て何となく分かった気がすると言う事で、第一歩でした。
つづく。