emblog Qtのあれ

Qt関連のあれだったり、これだったり by sazus

Qt 勉強会 @ Nagoya No3(16.12)に参加してきました

Qt勉強会に参加しました。

2016年12月10日(土曜日)に、@nekomatuさん主催の名古屋開催Qt 勉強会 @ Nagoya No3(16.12)に参加してきました。

今回のおやつ

勉強前の午前中に栄に用事があったりしたので、ぶらぶらしていると北海道物産展の催し物を見つけたので一緒に北海道おやつもGetして持って行きました!


勉強会の内容

もくもく会だったので僕の方では、Qt Advent Calendar 2016@task_jpさんのエントリにあるAutomotive Grade Linuxのデモ開発を手伝えたりできればいいなぁって思いながら、とりあえず動作させていろいろCodeを見てみる事にしました。
DemoApps/CES2017あたりをチェックアウトしてから、QMLのimportのPATHで少しハマったりしてましたが、なんとか表示までもってく事ができました。
自分のPC環境だと画面の解像度が低くアプリの全体が表示できなかったりしていたので少し直したりをして


だったのを
f:id:sazus:20161212235709p:plain
画面調整する程度の成果で、今回の勉強会は時間切れとなってしまいましたorz

一緒に参加された方の成果

Qt Advent Calendarに向けて、現実逃避?しながらも


  • QMacCocoaViewContainerを使ってみたり(Qt Advent Calendar 10日目のエントリになってます)
  • Raspberry picudeでBuildrootとQtCreatorを使ってQtアプリを開発する方法を試したり(Qt Advent Calendar 11日目のエントリになってます)
  • Qtの とあるライブラリの動作とサンプルCodeを書いていたり(Qt Advent Calendar 22日目のエントリの予定)
  • QtでOpenCVを動かせるようにしたり(Qt Advent Calendar 24日目のエントリの予定)

などなど、集まった方々が本日の成果を発表されていました。

懇親会

会場近くの中華料理
r.gnavi.co.jp
で、名古屋でギョーザが一番うまい餃子(自称)を堪能して、終了となりました。


まとめ

今回の勉強会のまとめとして@nekomatuさんが
Qt 勉強会 @ Nagoya No3 #qtjp - Togetterまとめ
でつぶやきのまとめをしていますので、参加してみようかなぁって方は見てもらうと雰囲気が掴めるかなぁって思います。

QtCreatorのプロジェクトファイル(.pro)で使用される変数について

はじめに

qbs1.0.0がリリース*1されちゃってあれなんですが、Qtのプロジェクトファイル(.pro)に記載される変数とMakefileの関係を少し。
主として、僕の環境がlinuxなのでlinux寄りの記載になりますが、WindowsでもMacでも参考にはなるかと思います。

QtのProjectFileについて

QtCreatorでProjectを作成されるプロジェクトファイル(.pro)ですが、
QtCreatorで使用されるだけでなく、qmakeの引数で渡す事によりMakeファイルを作成する事に使用されます。(下図)
f:id:sazus:20130604191252p:plain:w800

この為、プロジェクトファイルの記載された変数によって、
make時に生成されるアプリケーション名や、コンパイル環境毎にデバックオプション等を
個別につけたりできます。

デフォルトの変数

以下、プロジェクトの新規作成で、Qt GUIアプリケーションを選択した時に
プロジェクトファイルにデフォルトで追加される変数の説明です。

QT

QTのモジュールを使用する時に使用する変数です。以下が付加できるパラメータです。

付加するパラメータ 使用モジュール
core QtCore モジュール
gui QtGui モジュール
widgets QtWidgets モジュール(Qt4では、QtGuiモジュールに
含まれているので不要
network QtNetwork モジュール
opengl QtOpenGL モジュール
sql QtSql モジュール
svg QtSvg モジュール
xml QtXml モジュール
webkit WebKit 関連(link先はWebView)

TARGET

生成される実行ファイル名を設定します。
デフォルトでは、プロジェクト名になります。
Makefileでも、TARGETとして記載があります。

TEMPLATE

Makefleの種類を設定します。以下のパラメータを選択します。

付加するパラメータ 使用モジュール
app アプリケーションとしてbuidする
Makefileを生成します。
lib ライブラリとしてbuildする
Makefileを生成します。
subdirs サブディレクトリ中のプロジェクトのMakefileを作成します。
ディレクトリは別途、SUBDIRS変数を使用して指定します。
vcapp VisualStudioのアプリケーションプロジェクトファイルを作成します。
vclib VisualStudioのライブラリプロジェクトファイルを作成します。

SOURCES

Projectで使用されるソースファイルを指定します。
e.g.
main.cppを登録しておくと、linux環境でのgccMakefileでは、

$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/main.o main.cpp

のように追加されていきます。

HEADERS

Projectで使用されるヘッダファイルを指定します。
e.g.
SOURCESにhoge.cppを登録しておき、hoge.cpp内部に#include"hoge.h"としている場合
linux環境でのgccMakefileでは、

$(CXX) -c $(CXXFLAGS) $(INCPATH) -o debug/hoge.o: hoge.cpp hoge.h

のように追加されていきます。

変数に設定する演算子について

以下のように扱います。詳細はこちら

代入(=)

e.g.

QT = core gui

QtCore モジュール(core)、QtGuiモジュール(gui)を設定します。

削除(-=)

e.g.

QT -= gui

QtGuiモジュール(gui)の設定を削除します。

追加(+=)

e.g.

QT += network

QTに設定されている設定値にプラスして、QtNetworkモジュール(network)を追加する。

すでに存在していない場合のみ追加(*=)

e.g.

QT *= network

QTに設定されている設定値で、QtNetworkモジュール(network)が設定されていなければ追加する。

その他

RESOURCES

リソースファイルを追加すると出てくるあれ
リソースコレクションファイル(.qrc)を設定します。
qrcに追加された画像などは、バイナリファイルとしてアプリケーション(もしくはライブラリ)内に格納されます。
リソースファイルについての詳細は、QtCore 5.0: The Qt Resource System | Documentation | Qt Project
に詳細なドキュメントがあります。

TRANSLATIONS

翻訳ファイル(.ts)のファイルを設定します。
使い方の詳細は
QtLinguist : Qt Linguist Manual: Developers | Documentation | Qt Project
に詳細がドキュメントがありますが、
Qt@福岡勉強会(facebook)を主催しておられる@vivisukeさんの本に詳しい説明がされており、僕はこっちでお勉強しましたw。

Qtプログラミング入門―使いやすいフレームワークを基礎から解説 (I・O BOOKS)

Qtプログラミング入門―使いやすいフレームワークを基礎から解説 (I・O BOOKS)

DEFINES

Makefileに-Dのプリプロセッサオプション*2を追加します。
gccの -Dオプションについて:
-Dhoge - マクロhogeを文字列1として定義してくれます。
参照:Preprocessor Options - Using the GNU Compiler Collection (GCC)
e.g.

DEFINES += TEST

とすると、
Makefileには、

DEFINES = -DTEST

が追加されます。

LIBS

プロジェクトにリンクするライブラリの設定を行います。

  • Linuxの場合は、 -Lでライブラリの検索をするディレクトリ指定-lでライブラリ名の指定を行います。
    gccの参照:-Lオプション-lオプション
  • Windowsの場合は、ライブラリファイルまでのフルパス指定を行います。
    qt-projectのページのNOTEにあるようにWindowsの場合は、-lオプションを指定しない方がいいようです。
    例えば、-lmath等すると、libmathlibの代わりにlibmath2.libといった最も高いバージョン番号のライブラリが使用されるっぽいです。
    なので、使用したいライブラリ名を明示的に指定するほうがいいらしい。
    (組み込み専門でWindowsは知らないので...誰か詳しい人コメントよろしく)

また、ディレクトリ名に" "(スペース)が含まれる場合には、""で囲みます
e.g.
Linuxの場合
/usr/local/lib/libhoge.soを設定する場合(ディレクトリにスペースなし)
/home/usr/my lib/libfuga.soを設定する場合(ディレクトリにスペースあり)

LIBS += -L/usr/local/lib -lhoge
LIBS += "-L/home/usr/my lib" -lfuga

Windowsの場合
c:/libs/hoge.libを設定する場合(ディレクトリにスペースなし)
c:/my libs/fuga.lib(ディレクトリにスペースあり)

LIBS += c:/libs/math.lib
LIBS += "c:/my libs/fuga.lib"

INCLUDEPATH

指定されたディレクトリをヘッダファイルを検索するリストとして設定します。
gccの -Dオプションについて:
参照-Iオプション
e.g.
f:id:sazus:20130608210510p:plain
上記のようなディレクトリ構成の場合で、
a.cppや、b.cppがab.hを#includeする場合

#include"../dir_h/ab.h"
・・・

と記載が必要ですが
プロジェクトファイルに、

INCLUDE += $$PWD/dir_h

NOTE:"$$PWD"の変数はparsedされ、現在のファイルを含むディレクトリに至る完全なパスに置き換えてくれます。
とプロジェクトファイルに記載しておく事により
a.cppや、b.cppでのab.hのincludeを

#include"ab.h"
・・・

の記載でも大丈夫になります。
linux環境でかつシャドービルドONの場合、gccMakefileでは、
INCPATH = -I/opt/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/mkspecs/linux-g++ -I../SampleProject -I../SampleProject/b
とQtlibraryのpathが最初にきて、その後プロジェクトのディレクトリ
その次に指定がされました。
(../SampleProject 等になっているのは、シャドービルドでは、プロジェクトディレクトリと同位のディレクトリpathにbuild用のディレクトリが生成され、その中にMakefileが生成される為。)
演算子の指定が"="でも"+="でもこの順番は変わっていませんでした。(演算子はこの変数では意味がないかもしれないです。)

最後に

Macでもいろいろ確認してみたいので、誰かMacください!

*1:qmakeはビルド用のファイルを生成するツールなのですが、qbsはビルドも実行しちゃうツールらしいっす。

*2:プリプロセス - ソースプログラムに対してコンパイル前に行われる前処理のこと

Qt5でbuildされた QtCreatorで日本語入力をできるようにする(@Linux環境)

はじめに

Qt 5.1 Beta Released | Qt Blogの発表もあり、今回からバイナリが手に入るのとの事で
週末の名古屋もくもく会場(になってしまっている場所)で早速installしてみたのですが
付属のQtCreatorで日本語入力できなかった!

動作確認 環境


動作結果

QtCreator QtLibrary
Version
デフォルトでの
日本語入力
対応方法
qt-linux-opensource-5.1.0-beta1-x86_64-offline.runのQtCreator Qt 5.1.0(64bit) できない 環境変数の変更
pluginの追加または、plugin pathの変更
qt-projectの単体配布 Qt4.8.4(64bit) できる -
gitのqt-creator tag v2.7.1 Qt 5.1.0(64bit) できない 環境変数の追加



Qt4では各プラットフォームにてInputMethodが実装されていたようなのですが
Qt5では、QInputContextクラスが整備され、QPlatformInputContextのクラスを新設する事によって、
プラットフォーム毎のInputMethodを統合したようです。

この為、今回のようにQt4とQt5でbuidしたものによって、挙動が変わってしまったと思われます。
(Qt4.8系は、組み込み用で使用しているQWSあたりしか、ざっと見たことが無いので良く分からんとです。)

詳細な情報は、Qt5 の Input Method | Qt のあれこれ (仮)に分かりやすく まとめられています。

対応方法(Qt5を使用する場合)

  • 環境変数の変更
  • pluginの追加または、plugin pathの変更

となります。

環境変数の変更

exportにて、環境変数の確認を行い、

$ export | grep IM
declare -x GTK_IM_MODULE="ibus"
declare -x LC_TIME="ja_JP.UTF-8"
declare -x QT_IM_MODULE="xim"

QT_IM_MODULE="xim"
となっている場合、コンソール上にて
export QT_IM_MODULE=ibus
とした後、そのコンソールにてqtcreatorを呼び出します。

ざっくりと、該当Codeを眺めて見たのですが

  • 環境変数QT_IM_MODULEにセットされたStringをicStringにセット(83行)
  • 環境変数に入っている文字にて、create()にてpluginをload。(88行)
  • loadの戻値が設定されており、入力方式が有効な場合はreturn(89行)

といった感じでしょうか。
${Qt5.1.0}/qtbase/blobs/v5.1.0-beta1/src/gui/kernel/qplatforminputcontextfactory.cpp

 79: QPlatformInputContext *QPlatformInputContextFactory::create()
 80: {
 81:    QPlatformInputContext *ic = 0;
 82:	
 83:     QString icString = QString::fromLatin1(qgetenv("QT_IM_MODULE"));
 84:	
 85:     if (icString == QLatin1String("none"))
 86:         icString = QStringLiteral("compose");
 87:	
 88:     ic = create(icString);
 89:     if (ic && ic->isValid())
 90:         return ic;
 91:	
 92:     delete ic;
 93:     ic = 0;
 94:	
 95:     QStringList k = keys();
 96:     for (int i = 0; i < k.size(); ++i) {
 97:         if (k.at(i) == icString)
 98:             continue;
 99:         ic = create(k.at(i));
100:         if (ic && ic->isValid())
101:             return ic;
102:         delete ic;
103:         ic = 0;
104:     }
105: 	
106:     return 0;
107: }

また、Qt5.1.0beta1で対応(?)されているInputMethodは、
${Qt5.1.0}/qtbase/src/plugins/platforminputcontexts より

  • compose これ何??(誰か教えてくださいw) ..... libcomposeplatforminputcontextplugin
  • Maliit(マリート ..... libmaliitplatforminputcontextplugin
  • ibus ..... libibusplatforminputcontextplugin

の3種類のようです。

pluginの追加または、plugin pathの変更

上記だけの対応だけで、OKかと思ったのですが
qt-linux-opensource-5.1.0-beta1-x86_64-offline.runに含まれるToolsのQtCreatorが、まだ日本語入力できない。
でも、gitでcloneしてbuildしたものは問題なく日本語入力できるといった所で詰んでいたのですが
同もくもく会場で、何かと戦っている猫帽子王から


お告げ来ました!。
diffってみる

$ LANG=c diff -rq ${QT510BETA1}/5.1.0-beta1/gcc_64/plugins/ ${QT510BETA1}/Tools/QtCreator/bin/plugins/ | grep "Only"
Only in /opt/DeveloperTool/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/plugins/: audio
Only in /opt/DeveloperTool/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/plugins/: bearer
Only in /opt/DeveloperTool/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/plugins/: generic
Only in /opt/DeveloperTool/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/plugins/: mediaservice
Only in /opt/DeveloperTool/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/plugins/: platforminputcontexts
Only in /opt/DeveloperTool/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/plugins/: platformthemes
Only in /opt/DeveloperTool/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/plugins/: playlistformats
Only in /opt/DeveloperTool/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/plugins/: qmltooling
Only in /opt/DeveloperTool/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/plugins/: sensorgestures
Only in /opt/DeveloperTool/Qt/qtlib/Qt5.1.0beta/5.1.0-beta1/gcc_64/plugins/: sensors

ToolsのQtCreatorが参照しているplugin Directoryにplatforminputcontexts丸々入ってない...。(なんでやねん)

対応1:
Qt5.1.0のpluginから./platforminputcontextsをQtCreatorのpluginへCopyする。
一番手っ取り早い手ですね。

$ cd ${QT510BETA1}/Tools/QtCreator/bin/plugins
$ cp -arpv ../../../../5.1.0-beta1/gcc_64/plugins/platforminputcontexts/ .
`../../../../5.1.0-beta1/gcc_64/plugins/platforminputcontexts/' -> `./platforminputcontexts'
`../../../../5.1.0-beta1/gcc_64/plugins/platforminputcontexts/libmaliitplatforminputcontextplugin.so' -> `./platforminputcontexts/libmaliitplatforminputcontextplugin.so'
`../../../../5.1.0-beta1/gcc_64/plugins/platforminputcontexts/libibusplatforminputcontextplugin.so' -> `./platforminputcontexts/libibusplatforminputcontextplugin.so'
`../../../../5.1.0-beta1/gcc_64/plugins/platforminputcontexts/libcomposeplatforminputcontextplugin.so' -> `./platforminputcontexts/libcomposeplatforminputcontextplugin.so'



対応2:
${QT510BETA1}/Tools/QtCreator/bin/の中にある、qt.confを書き変える。
Pluginsのpathを下記のように書きかえる事により参照先をQt5.1.0のlibraryのplugin先に変える。
ただしplugin自体のディレクトリ以下で、同名のファイルにおいてbinaryLvで差が出ていたので
あまりヨロシクない方法だと思います。

--- qt.conf.org	2013-05-18 13:48:13.783456942 +0900
+++ qt.conf	2013-05-21 23:35:27.646429207 +0900
@@ -1,5 +1,5 @@
 [Paths]
 Libraries=../lib/qtcreator
-Plugins=plugins
+Plugins=../../../5.1.0-beta1/gcc_64/plugins
 Imports=imports
 Qml2Imports=qml



対応3:
installしたディレクトリを弄りたくない人向け(僕これw)

$ cat > ./qtcreator271_Qt510 <<EOF 
#!/bin/bash

export QT_IM_MODULE=ibus
export QT_PLUGIN_PATH=${QT510BETA1}/5.1.0-beta1/gcc_64/plugins
${QT510BETA1}/Tools/QtCreator/bin/qtcreator
EOF
$ chmod 755 ./qtcreator271_Qt510
$ sudo mv ./qtcreator271_Qt510 /usr/local/bin

FULL pathで記載してください。${QT510BETA1}は、インストール時のpathになります。
各インストール環境によって読み替えてください。
デフォルトのinstall pathだと、
"/home/$USER/Qt5.1.0"
となっていると思います。

実行するときは、コンソール上にて

$ qtcreator271_Qt510 &



GUI環境のマウスクリックじゃないと耐えられないかたは、デスクトップショートカットを作成する。

$ cat > ./QtCreator2.7.1.desktop <<EOF
[Desktop Entry]
Name=Qt Creator2.7.1
Name[ja]=Qt Creator2.7.1
Categories=Development;IDE;Qt;
Encoding=UTF-8
Exec=/bin/sh -c "export QT_IM_MODULE=ibus; export QT_PLUGIN_PATH=${QT510BETA1}/5.1.0-beta1/gcc_64/plugins; ${QT510BETA1}/Tools/QtCreator/bin/qtcreator"
Path=${QT510BETA1}/Tools/QtCreator
GenericName=The IDE of choice for Qt development.
Hidden=true
Icon=QtProject-qtcreator
MimeType=text/x-c++src;text/x-c++hdr;text/x-xsrc;application/x-designer;application/vnd.nokia.qt.qmakeprofile;application/vnd.nokia.xml.qt.resource;
Terminal=false
Type=Application
EOF
$ chmod 755 ./QtCreator2.7.1.desktop

shにて
export QT_IM_MODULE=ibus;
export QT_PLUGIN_PATH=${QT510BETA1}/5.1.0-beta1/gcc_64/plugins;
${QT510BETA1}/Tools/QtCreator/bin/qtcreator"
をコマンド実行させるデスクトップショートカットです。
生成したファイルをダブルクリックで実行してUbuntuの場合なら、Launcherの
QtCreatorアイコン箇所を右クリック->Launcherに登録


POINT
export QT_IM_MODULE=ibus;は必須。
環境変数QT_PLUGIN_PATHを入れることにより、Pluginsディレクトリの設定ができます。

Raspberry PiでのQt5日本語表示

リツイート等もして頂いたので、blogに書いておく。

はじめに

Raspbianを日本語にがんばってローカライズしたとしても、
Qt5で日本語表示した場合に、日本語の文字列が豆腐にすらならず
非常に残念極まりない表示になります。
Widgetの場合
(対応前)
f:id:sazus:20130509024400j:plain
(対応後)
f:id:sazus:20130509024442j:plain
QMLの場合
(対応前)
f:id:sazus:20130509024553j:plain
(対応後)
f:id:sazus:20130509024625j:plain


動作確認 環境

  • Raspberry Pi導入OS
    • Raspbian "wheezy(Hard-float)”2013-02-09-wheezy-raspbian
  • Qt5 :
    • gitのtag v5.0.2
    • configureにて、-prefix /usr/local/qt5piと設定してbuild



対応方法

  • Qt5のlib以下の/fontディレクトリに日本語のフォントを入れる。
  • Code上にて、導入した日本語フォントのfontfamilyをセットする。

ことにより対応可能です。

Qt5のlib以下の/fontディレクトリに日本語のフォントを入れる

私の環境では、"-prefix /usr/local/qt5pi"としているので、
/usr/local/qt5pi/lib/fonts/
に日本語フォントを入れちゃえばOKです。
導入先は、各自で環境設定を読み替えてください。

- 日本語フォントの取得

とりあえず、今回はtakao fontあたりを取得してみました。

$ sudo apt-get install fonts-takao

これで、Raspbianに
fonts-takao-gothic fonts-takao-mincho

/usr/share/fonts/truetype/takao-gothic/
/usr/share/fonts/truetype/takao-mincho/
以下に導入されます。

- 日本語フォントをQt5のフォントディレクトリーにコピーする

先ほどのフォント(今回は、takao-gothicの方)をコピーします。

$ sudo cp /usr/share/fonts/truetype/takao-gothic/TakaoGothic.ttf /usr/local/qt5pi/lib/fonts/


Code上にて、導入した日本語フォントのfontfamilyをセットする

QApplicationに対して、QFontクラスにてfontfamilyを指定します。

  QApplication a(argc, argv);
  ・・・
  QFont font;
  // 導入した日本語のフォントファミリーを指定します。
  font.setFamily("TakaoGothic");
  a.setFont( font );
  ・・・
  • QMLの場合

Text Elementのfont.familyのPropertiesを指定する。

  Text {
       ・・・
       // 導入した日本語のフォントファミリーを指定する。
       font.family: "TakaoGothic"    //[*]
       ・・・
  }



確認に使ったソース

Widget

  • main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QLabel>
#include <QFont>

MainWindow::MainWindow(QWidget *parent) :
	QMainWindow(parent)
{
	QLabel *label = new QLabel("Hello RaspberryPi \n\
こんにちはRaspberryPi");
	setCentralWidget(label);
}

MainWindow::~MainWindow()
{
}


int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	QFont font;
        // 導入した日本語のフォントファミリーを指定する。
	font.setFamily("TakaoGothic");    //[*]
	font.setPointSize( 48 );
	a.setFont( font );

	MainWindow w;
	w.show();
	
	return a.exec();
}
  • mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
	Q_OBJECT
	
public:
	MainWindow(QWidget *parent = 0);
	~MainWindow();
};

#endif // MAINWINDOW_H

QML版

  • Sample_Raspberrypi_Qt5_qml.qml
Rectangle {
   width:  800
   height: 600
   Text {
         anchors.centerIn: parent
         font.pointSize: 48
          // 導入した日本語のフォントファミリーを指定する。
         font.family: "TakaoGothic"    //[*]
         text: "Hello RaspberryPi \n こんにちはRaspberryPi"
   }
}

QML実行方法

$ qmlscene ./Sample_Raspberrypi_Qt5_qml.qml