So-net無料ブログ作成

Qtクラスの継承 - その2 [NetWalker]

前回の記事では、試行錯誤で多少混乱した感じになったので、いったん前回の作業をリセットすることにします。Objectペインのwidgetを右クリックし「Demote」、これだけでは、Promoteダイアログに前回設定した内容が残っているので、それも削除。そして、Projectsペインにあった作成したフォームに関する.h、.cpp、.uiファイルを削除、メニューから「Build」→「Clean All」で念のため掃除。そしてもいちど実行をかけてみました。

*

たぶん、これで元に戻っただろうということで、あらためてObjectペインのwidgetを右クリックして「Promote to」・・・。「Promote to」になってますね・・。「Promote」じゃなかったっけ・・?

1003_qt_promote_to.png
最初からこうか・・?


ま、気にせずに前回書いたのと同じクラスを再度設定することにします。そして「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」になってますね・・。

100330_qt_newform_object.png
う~ん


この作成した Qtl_Canvas と MainWindow はちゃんと結びついているんでしょうか(たぶん結びついていない)? それを確かめるために、Qtl_Canvas に適当なラベルを貼り付けます。

100330_qt_newform_put_label.png
うまく結びつけばいいですが・・


これで、ビルドしてみます。「Build」→「Build Project」。

おぉ・・・。エラーがいっぱい出てきました・・。エラー6、警告4ですね。

100330_qt_error.png
それ以前…


先頭が、「qtl_canvas.cpp」での「invalid use of incomplete type 'struct Ui::QtlCanvas'」となってます。一応このソースでは、「qtl_canvas.h」を読み込んでいて、そこでちゃんと宣言されている様な気もするんですが・・。

100330_qt_qtl_canvas_cpp.png
何が問題?


と思ったら、次のエラーメッセージで「qtl_canvas.h」での「forward declaration of 'struct Ui::Qtl_Canvas'」と出てますね・・。

100330_qt_qtl_canvas_h.png
namespaceの宣言って正確には知らないんですよねぇ・・


namespace の宣言のところで、エラーが出てますね。

別に、自分でコードを足したわけでもなし・・、どうしようかな・・。


【参考】
Using Custom Widgets with Qt Designer
Creating Custom Widgets for Qt Designer
Custom Widget Plugin Example
How to Create Qt Plugins








妄想 [雑感]

ちょっと、一休み。と言うか、同じ話題ばかりだと飽きてくるので・・。進捗悪いけど・・・。

先日、こんなページを見つけました。ベーマガです。懐かしいですね。ペーパー・アドベンチャーなんかもよく遊びましたね。これは、持ち込みで始まったんですか・・。「チャレンジ!アドベンチャーゲーム」のコーナーも持ち込みな様ですね。まさに、読者参加型の雑誌と言う感じだったんですね。

と、昔を懐かしんでたら、その翌日、プログラミング雑誌を創刊するぞ!と言う方の情報を見つけました。ターゲットはプログラム言語の入門学習を終えた人の様ですが、内容的には、こちらの様な技術情報系の雑誌を目指しておられる様に思われます。でも、ターゲットにされている読者層はまさにベーマガがターゲットにしていた読者層じゃあないですか。と思ってしまいました。

改めて探してみると、@ITdeveloperWorksCodeZineとか、技術情報系のWebマガジン(と言っていいのか・・?)はちらほらありますが、ベーマガの様に読者投稿型のサイトは見当たりませんね。そう言うサイトはできないですかねぇ・・。と妄想をベーマガとの比較で書いていきます。

ベーマガベーマガ風Webマガジン
掲載方式ソースコードを印刷ソースコードを含むプロジェクトを掲載
分類機種毎CPU、OSと開発環境毎
掲載ソフト数1分類に1〜2本1分類に1〜2本
更新間隔月刊月刊


いまどきソースを打ち込むのも無いでしょうから、とりあえず、プロジェクトで掲載。読者は自分でビルドしましょうと言うことで。投稿時は確認のための実行バイナリも投稿する必要があるでしょうけどね。で、昔はパソコンの機種も山の様にありましたが、今は機種はともかく、動作環境はOSで絞られています。でも、開発の際はEclipseだとか、Xcodeだとか、Qt Creatorだとか、開発環境はたくさん存在しています。また、PCだけじゃなくPDAとかも含めて考えれば、結構なパターンが出てくるのではと思われます。掲載ソフトはまあ、一ヶ月に1環境で1本を基本とすれば、ある程度の質は保てそうですし、読者側もいろいろとソースをいじることが可能になる様な気もします。

って、だめですかねぇ。昔は打ちこまないとソフトがなかったんですが、今はいちいちビルドしなくても動くソフトがいっぱいありますからねぇ。読者が増えるかどうかもありますが、そもそも投稿が来ないですかね? まあ、逆に投稿が来すぎても環境の構築、検証、選出が大変でしょうけど・・。投稿の際は、自分で工夫した点をアピールすることができて、それについてコメントがついたりすると投稿へのモチベーションにならないですかねぇ。

ソフト開発って、理屈ばかり読んでいてもちっとも身につかないので、結局自分で書かないと上達しないんですが、0から書き始めると言うのはかなりハードルが高いんですよね・・。で、大抵の開発環境にはサンプルコードが付いてるんですが、まあ、大抵のサンプルコードはそれ自体に全然魅力がないものばかりですからね・・。コードを読む気にもならんし、そっから拡張しようかと言う気にもならないですね。投稿が増えれば、それなりに面白いソフトになるでしょうし、そこから自分で改造したいとか、ここをどうやってるのか見てみたいと言う形になればかなり学習効果が期待できるんですけどねぇ。と言うか、個人的にそう言うのが欲しいなぁ・・・。いろんな開発環境を一から勉強するのは大変ですからねぇ・・。


アスキーさんあたりで無理ですかねぇ・・。あるいは、また電波新聞社さんとか。これを有料サイトにしたらそもそもの投稿が来ないでしょうし、どこで収益を上げるかと言うのが大問題ですね。ちなみに、関係ありませんが「Software Design」はまだ生き残ってるんですね。ちょっと、びっくりしました。


【参考】
ALL ABOUT ベーマガ
マイコンBASICマガジン - ウィキペディア
山下章 - ウィキペディア
まさにプログラマの原典!「ベーマガ」の魅力 - Tech総研
我々はプログラミング雑誌を創刊す - 本の虫
@IT
developerWorks Japan
CodeZine
マイコミジャーナル>エンタープライズ>プログラミング







Qtクラスの継承 [NetWalker]

さて、実装していきましょう。

QPainterで描画を行うわけですが、ペンでタッチされてからリリースされるまでは同じQPainterのオブジェクトを使用したいと思っています。なので、まずQPainterを保持するメンバ変数を用意しましょう。と言うことで、QWidgetにメンバ変数追加!・・・と思いましたが、Qtで用意されているクラスにそんなことできませんね・・。これを継承して新しいクラスを作らないといけませんが、Qt Designer上でそんなことができるんでしょうか・・?

ドキュメントを眺めていると「Using a Designer .ui File in Your Application」というページがあったので、見てみましたが、特にそのような記載はなし。よくわからないので、とりあえず、メニューから「File」→「New」を選択してみると「Qt Designer Form Class」という項目がありました。

1003_qt_new_form_class.png
これでできるかな・・?


「OK」で選択して次に進むと、「templates/forms」の項目に「Widget」と言うのがあるので選択してみます。で、「Next >」。

1003_qt_templates.png
いろいろありますねぇ・・


続いて、クラス名、ヘッダファイル名、ソースファイル名、.uiファイル名の設定です。クラス名を入れるとその他のファイル名も追随してくれますね。便利。ま、設定して「Next >」。

1003_qt_class_name.png
クラス名に追随してくれます


で、プロジェクトに追加ですね「Finish」。

1003_qt_form_finish.png
フォームとソースが追加されます


これで、プロジェクトにフォームが一つ追加されました。

クラスの名前は「Qtl_Canvas」にしたんですが、追加した「qtl_canvas.h」を見てみると、QWidgetクラスを継承したクラスとなっています。ソースはいじれる様なので、これで好きに動作を記述できるような気がしますが、元のmainwindowへの追加はできますでしょうか・・?

1003_qt_canvas_source.png
簡単にサブクラスが作れますね


色々試していたところ、下記でできそうな感じです。まずは、既にフォームに追加しているwidgetを右クリック。「Promote」というメニューを選択すると、ベースクラスを選択し、クラス名等を入力して「Add」すれば、継承したクラスとして扱えるようになるようです。

1003_qt_promote.png
追加した後です


メニューにあるなら、どこかに説明があるのでは?と思って、あらためてドキュメントを眺めていたところ、ありました。と言うことで、カスタムウィジェットもQt Designer で扱える雰囲気ですね。でも、先程作ったフォームと同じ名前のクラスを追加したんですが、追加は手書きで行いましたし、今のところ作成したフォームとこの継承したクラスとが関連付けされていないような気がしています・・。ちなみに、今回作成したフォームは上に何か置くわけでもないので、いちいちフォームを作成する必要もないですね・・。


さて、どうしましょうかね・・。つづく。


【参考】
Using a Designer .ui File in Your Application
Calculator Form Example
Using Custom Widgets with Qt Designer








Qtでのペン操作の追随と描画への準備 [NetWalker]

さて、「まず線でも引こうか」と書きましたが、いい加減まどろっこしいので、やっぱりペンの補足と線の描画を一気にやって行きたいと思います。

どこから見ればいいかなぁとドキュメントを眺めていましたが、ペン(と言うか、マウス)のイベント捕捉についての項目はなさそうですね・・。仕方がないので、QWidgetの説明を見ていたところ、まさに該当しそうなところがありました。そこによると、関連ありそうなのは以下の三つのイベントですね。

mousePressEvent()widget内でマウスボタンが押された(ペンでタッチされた)時に呼ばれる。描画の開始ポイントになりますね。
mouseMoveEvent()マウスボタンが押されたままマウスが動いている(ペンでなぞっている)時に呼ばれる。線の描画を行うのに使えます。
mouseReleaseEvent()マウスボタンが離された(ペンが離された)時に呼ばれる。描画の終了ポイントですね。


と、これはいいんですが、実はQtでこれらのイベントを補足する際はSignalとSlotと言うQt独特の仕組みを理解しておく必要があります。上記は全てイベントハンドラ関数になるんですが、この仕組みの中では「Slot」に該当します。まあ、詳しくはこちらをご覧ください。

・・と思いましたが、用意されているSlotを使うだけなら、理解は不要かもしれませんね・・。Ruby/Qteの時はSignalを補足するために事前に準備(と言うほどのものでもありませんが・・)が必要でしたが、今回ドキュメントを読んでいてもそのような記載がありませんね。C++の場合はそのあたりは、意識せずに使えるのかもしれません。

以上でペンの捕捉についてはたぶん問題ないと思います。次は描画について。以前にちらっと見てたんですが、描画の手順については書かれていないんですよね。Zaurusでのプログラミングの経験とQPainterの詳細の説明から、だいたい下記のような手順で描画が可能と思われます。

  1. QPainterの生成と初期設定
  2. QPainterを用いて描画
  3. QPainterの破棄


これらを、先程のマウスイベントの処理のところにあてこめば描画できると思われます。一応、見直そうと思ってドキュメントを見てみたんですが、昔とあんまり変わっていませんね。


次回から実際の作業に移りたいと思います。スムーズに行けばいいんですけどねぇ・・。

QMainWindowのcentralWidgetへのレイアウトについて [NetWalker]

さて、前回で一応、メインウィンドウ上へのウィジェットの展開ができましたが、一見、ウィンドウにフィットしたものの、枠を見る限り周りにある程度、スペースがありますし、そもそもあの「AdjustSize」と言うメニューがどういう意味を持つのかが良くわかっていません。今回、ドキュメントを読んで、大体の対応付けを確認したいと思います。

ですが、まずはソースを確認してみたいと思います。今プロジェクト中にあるファイルは次の通りです。特に自分で追加したファイルはありません。

1003_qt_project_1.png
Widgetが反映されて無い気も・・


ソースには特に目立った記述がないですね・・。それどころかWidgetやLayoutと言った、追加した項目が全くソースに現れていません。と思ったら、「mainwindow.ui」に記述されていました。UIの記述とプログラムが分離されていると言う事でしょうか?このファイルはXMLで表現されています。ですが、ソース上のどこからも直接はこのファイルが読み込まれている感じがありません・・。

「mainwindow.cpp」を見たところ、コンストラクタで「ui->setupUi(this)」と言うコードが見られます。

1003_qt_mainwin_cpp.png
この処理で読み込まれるのか・・?


「ui」って何だ?と思って、「mainwindow.h」を見てみると、「Ui::MainWindowClass」のインスタンスとして宣言されていました・・。

1003_qt_mainwin_h.png
MainWindowClassって何?


「MainWindowClass」ってどんなクラスなんでしょうね・・?上の方に「namespace」と言うキーワードが出てきていますが、これの使い方が良くわかっていません。その辺に何かあるんでしょうか?「Ui」って、何か予約されているキーワードなんですかね・・。

*

それはさておき、「mainwindow.ui」の中を見ていきます。

眺めていると、centralWidgetの中身に「QVBoxLayout」が2つ含まれています。

1003_qt_mainwin_ui_1.png
レイアウトが二つ・・。


私が足したのは一つだけ、それは「verticalLayout」です。それぞれのレイアウトの名前を見てみると外側のレイアウトに「_2」と言う文字が付加されています。おそらく、これが「MainWindowClass」のメニューから選択した「AdjustSize」で付加された内容ではないでしょうか。

これ、私が最初に足したレイアウトは不要な気がしますね・・。と言うことで、試しに消してみます。「Object」の箇所で「verticalLayout」を選択して右クリック→「Delete」。・・・えぇぇ~、一緒にwidgetも消えてしまいました。

1003_qt_delete_layout.png
消えた!


びっくりしましたが、メニューの「Edit」→「Undo」で元に戻せました。変わりに今度は「Object」のウィンドウで再度「verticalLayout」を右クリック、「Layout」→「Break Layout」。これでwidgetを残したまま、レイアウトを消去できました。これで保存して、「mainwindow.ui」の中身を確認してみます。

1003_qt_mainwin_ui_2.png
Layoutが二つとも消えた


どうも、レイアウトが二つとも消えてしまいましたね。良く見てみたら、widgetのサイズも小さくなってしまいました。

1003_qt_widget1.png
元通り


再度「Object」で「MainWindowClass」を右クリックして、「Layout」→「AdjustSize」。あれ?なんか、うまく行きませんね・・。

仕方がないので、もう一度verticalLayoutを追加して、widgetをその下に配置して、MainWindowClassを右クリックして「Layout」→「AdjustSize」・・・。ウィンドウ全体がちっちゃくなってしまいました。

1003_qt_window_small.png
悪化・・・


「MainWindow.ui」のソースを再度眺めてみたところ、明らかに最初の状態とは違いますね・・・。

1003_qt_mainwin_ui_3.png
違う・・


もう一度、加えたwidgetのレイアウトを破棄します。verticalLayoutを右クリックして、「Lay out」→「Break Layout」。で、ソースを見てみると先程のソースの通りに戻りました。

つづいて「MainWindowClass」を右クリックして、「Lay out」→「Lay Out Vertically」を選択したところ、うまく行きました!

1003_qt_widget2.png
ぴったり行きました。


これで、「MainWindow.ui」のソースを確認したところ、下記の通りです。思い通り、レイアウトが一つになっています。

1003_qt_mainwin_ui_4.png
すっきり


先程の画面を見直してみると、Object欄の「centralWidget」の部分のアイコンが変わってますね。縦のレイアウトのアイコンになってます。widgetのアイコンには進入禁止っぽいマークが。これがレイアウトされていないと言う印の様ですね。

以上、色々やりましたが、MainWindowClassにwidgetを追加して、枠ぴったりにレイアウトする方法は、おそらく下記の手順になる気がします。

  1. widgetをドラッグして追加
  2. 「MainWindowClass」を右クリックして「Lay out」→「Lay Out Vertically」を選択


・・・ドキュメントを読むつもりが、元に戻るのに手間取りましたね。まあ、「mainwindow.ui」のソースを見て何となく分かった気がすると言う事で、第一歩でした。


つづく。

ブログを作る(無料) powered by So-netブログ

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。

×

この広告は1年以上新しい記事の更新がないブログに表示されております。