カンテラの光の下で

dNaga392's memorandom

QtDesigner の custom widget plugin を作る

参考

%%QTDIR%%/examples/designer/worldtimeclockplugin

構成

ファイル 例(worldtimeclockplugin)
ウィジェットクラスファイル worldtimeclock.h worldtimeclock.cpp
プラグインクラスファイル worldtimeclockplugin.h worldtimeclockplugin.cpp
プロジェクトファイル worldtimeclockplugin.pro

カスタムウィジェットプラグインを作る場合、この3種類のファイルが必要となる。

既にカスタムウィジェットを作成している場合、 プラグインクラスファイルとプロジェクトファイルを用意することで、 カスタムウィジェットプラグインのプロジェクトとなる。

追加

release ビルドを実行。
以下の2ファイルが生成される(***:project name)。

  • lib***.a
  • ***.dll

これを以下に配置すると追加プラグインとして利用できる。

%%QTDIR%%/plugins\designer

【QLibrary】DLL内の関数を呼び出す

今回は関数の定義されたDLLの作成と、DLLの関数の呼び出しについて。

QtライブラリのDLL読み込みクラスは、QLibraryとQPluginLoaderがありますが、
今回は QLibrary を使用して読み込みます。

やりたいことはだいたい以下の感じ。

// アプリケーションと同じフォルダに SharedLib.dll があると仮定する。
QLibrary myLib("SharedLib"); // 読み込み

// 関数シンボルの定義。定義のフォーマットは以下のとおり。
//   typedef 戻り値の型 (*定義型)( 入力値の型1, 入力値の型2, ... );
// 今回、読み込む関数は int addNumber( int, int ) なので次のようになる。
typedef int (*MyPrototype)(int,int);

// 関数シンボルのアドレスを取得する(失敗の場合は0)。
MyPrototype myFunction = (MyPrototype) myLib.resolve("addNumbers");

// 呼び出し関数を実行。
int result = myFunction(3,2);
qDebug() << result; // "5"

// アンロード。loadを呼び出してない場合、resolveでloadされているため。
myLib.unload();

実際には、これにアドレスの取得失敗した場合の処理が追加されることになります。

参考というかほぼ以下のページのコピペなんで、リンク先を見て実行すればおおよそ理解できると思います。

Call Symbol From Shared Object File (DLL) with QLibrary

ただし、当該記事は2つ注意することがあります(というか自分がハマったことです)。

まず、main.cpp の20行目で 結果値に 2 が加算されています。 そのため、デバック出力では 7 が表示されます。

次に、記事のソースでは main.cpp の最後のreturnが QCoreApplication クラスの実行になっているため、コンソールから実行した場合、アプリを終了する手立てがありません(厳密にはCtrl+Cなどいくつか方法がありますが)。
そこで、コンソールから実行する場合は、最後のreturn 文を return 0; としておくとよいです。

この他、覚えておきたいこととして1点。

ライブラリのソースを見ると、Q_DECL_EXPORT は Win 環境の場合、__declspec(dllexport) が定義されています。 そのため、 Sharedlib.cpp の __declspec(dllexport) は Q_DECL_EXPORT で置換しても問題なさそうです。

c++ - Delayed DLL load in QT - Stack Overflow

あとは量も多くないので、ドキュメントを一読することをオススメします(呼び出す関数は extern "C" とすること。などが記載されてます)。

以上

【QScrolArea】中身のサイズに応じてスクロールバーを表示する

QScrollArea はスクロールバーを表示するウィジェットです。

スクロールバーは内包するウィジェットのサイズを受けて設定されます。
他のツールでも同様ですが、意味のあるスクロールバーを表示するにはコツがいります。

もし QScrollArea を見て、「これで手軽にスクロールバー表示できるぜ!ヒャッホーイ!」
と特に設定せずウィジェットやアイテムのサイズを動的に変化した場合、
意図したスクロールバーの表示はされません。
(アイテムが潰れた表示になるかもしれません。)

この問題に対処するには、まず QScrollArea に対して以下の設定をします。

   widgetResizable:true

加えて、QScrollArea直下の内包ウィジェット(ContentWidget)のレイアウトに
以下の設定をします。

   layoutSizeConstraint:SetMinimumSize

1つ目の設定で、ウィジェットのサイズ変更をQScrollAreaに容認させ、
2つ目の設定で、ContentWidgetのサイズをそれの持つアイテムによって変化するものとします。

これにより、QScrollAreaは中身のサイズの変化したことを受け取り、
スクロールバーが表示されるようになります。

参考

モバイルフレンドリー についてメモ

先日 Googleが検索結果アルゴリズムを新しくしました。
この変更で、モバイル端末ではモバイルフレンドリーなウェブページが、 優先して表示されるとのことです。

モバイルフレンドリー という単語を聞いたこともなかったので、
調べたことをつらつら書いていこうと思います。

モバイルフレンドリーとは

モバイルフレンドリーについては以下で概要が説明されています。

developers.google.com

Google基準のモバイルフレンドリーに合致してるかどうかも判定できるようです。
簡単に確認できるのは便利ですね。

Mobile-Friendly Test

モバイルフレンドリーにするには

モバイルフレンドリー にする手法は以下の3つがあるとのことです。

  • レスポンシブ ウェブ デザイン
  • 動的な配信
  • 別々の URL

レスポンシブ ウェブ デザイン

デバイスの画面サイズに応じて、表示を変える手法です。
cssの振り分けにより実装できるので、変更は小さく抑えらます。

小規模なサイトではこの手法を取るのが良さそうです。

レスポンシブWebデザインの作り方(簡単設定方法)

動的な配信

デバイスの種類に応じて、ページを動的に表示する手法です。
ページを動的に生成するので、URLは1つで済みます。

動的なページの表示は、JavaPHP などを用いて
ユーザーエージェントに応じてページを生成することで実装できます。

柔軟な対応が取れるので、中規模以上のサイトなら
将来的にもこちらの対応もよいかと思われます。

別々の URL

デバイスの種類に応じて、ページのURLを変える手法です。
独立性が高いため、デバイスに特化した表示ができます。

デバイスごとにページを用意する必要が有るため、
大規模化に耐えられるならば選択肢に挙がります。

【Qt】【QListView】QListViewの選択項目の取得

QListViewの選択項目の取得には以下の2通りの方法があります。

  • フォーカス中のアイテムの取得
  • 選択状態のアイテムの取得

まずはそれぞれの方法を示します。

  • フォーカス中のアイテムの取得
    QStandardItem * item = NULL;

    // フォーカス中のアイテムのインデックスを取得
    const QModelIndex index = listView->selectionModel()->currentIndex();
    item = model->itemFromIndex(index);
    Q_ASSERT(item);
  • 選択状態のアイテムの取得
    QStandardItem * item = NULL;
    QList<QStandardItem *> listItem;

    // 選択項目のインデックスリスト(選択順)
    QModelIndexList listIndex = listView->selectionModel()->selectedIndexes();
    foreach ( QModelIndex index, listIndex )
    {
        item = model->itemFromIndex( index );
        Q_ASSERT(item);
        listItem << item;
    }

見ていただければわかるように、この2つの方法には以下の違いがあります。

  • フォーカス中の項目の取得は1つのアイテムインデックスが得られる
  • 選択中の項目の取得は複数のアイテムインデックスが得られる

設定をしない限りは同時に選択できる項目が1つのみのため、
得られる結果に違いはありません。

ただし、複数選択を可能とした場合には、
後者の方法が見かけの選択項目と同じ項目を返します。

複数選択は、以下の設定をすることで可能となります。

    // 選択モードを複数選択に設定
    listView->setSelectionMode( QAbstractItemView::ExtendedSelection );

参考

【Qt】【QListView】QListViewの項目の追加

QListView に項目の追加する方法を示します。
まずは、前準備として以下のようにモデルの設定します。

    // リストビュー
    QListView *listView;
    listView = new QListView();
    Q_CHECK_PTR(listView);


    // 表示モデルを用意
    QStandardItemModel * model = new QStandardItemModel();
    
    // モデルの設定
    listView->setModel(model);

この ListView にテキストの項目を追加する場合、 以下のようにモデルの参照を取得して追加します。

    // 追加アイテムのテキストリスト
    QStringList listItemText;
    listItemText << "murmur";
    listItemText << "chant";
    listItemText << "pray";
    listItemText << "invoke!";


    // 設定モデルの取得
    QStandardItemModel * model = qobject_cast<QStandardItemModel*>(listView->model());
    // テキストアイテムの追加
    QStandardItem * item = NULL;
    foreach ( QString text, listItemtext )
    {
        item = new QStandardItem();
        Q_CHECK_PTR(item);
        item->setText( text );
        item->setEditable( false );
        model->appendRow( item ); // リストビューはアイテムを列に追加
    }