QMacCocoaViewContainer を使ってみる post

こんにちは、こんばんは。

Qt Advent Calendar 2016 の 10日目を担当する @sharkpp です。

今回は QMacCocoaViewContainer Class を触ってみようかと思います。

題して「QMacCocoaViewContainer を使ってみる」です。

はじめに

これは、 Qt で macOS Sierra の Touch Bar を使ってみようとして挫折したあれこれのから生まれた記事であります。

公式の方では [QTBUG-56908] Support NSTouchBar on latest MacBook Pro - Qt Bug Tracker で 5.9 を目標に実装が提案?されているようです。

まあ、とりあえず Touch Bar の事は忘れましょう。

環境

項目
OS macOS Sierra 10.12.1 (16B2659)
Qt 5.7.0
Qt Creator 4.1.0

この記事では Qt Creator でコードを書いていきます。

目標など

今回は NSButton を Qt のウインドウ上に表示してクリックをハンドリングするまでがこの記事の内容になります。

とりあえず作るクラスの階層です。

CocoaButton -- QPushButton を派生
  +-- CocoaButtonWrapper -- NSButton の参照を所有
        +-- CocoaButtonProxy -- NSButton のクリックを CocoaButtonWrapper に送る

CocoaButton が Qt のウィジェットとして利用できるようにするクラスで、そのほかに CocoaButtonWrapperCocoaButtonProxy があります。

プロジェクトを作る

まず適当なプロジェクトを作り、NSButton ボタン用のクラスを追加します。

Using Objective-C Code in Qt Applications に書かれているように OBJECTIVE_SOURCES.mm ファイルを追加しますが、「クラスの定義」でソースファイル名の拡張子を .mm に変更した場合は自動で設定してくれるようです。

Qt Creator

また、 NSButton などを利用するので .pro に AppKit をリンクするように LIBS に追加します。


FORMS += mainwindow.ui + + OBJECTIVE_SOURCES += \ + cocoabutton.mm + + macx: LIBS += -framework AppKit

こんな感じです。

完全な内容は MacCocoaWithQtSample.pro を見てみてください。

CocoaButton の実装

追加したファイルにクラスの実装をしていきます。

cocoabutton.mmCocoaButton を実装してきます。

Qt Cretor のデザイナでボタンを設置したいがために moveEventresizeEvent を実装します。

void CocoaButton::moveEvent(QMoveEvent *event)
{
    NSRect frame;
    frame = [m_wrpper->m_refButton frame];
    frame.origin.x = event->pos().x();
    frame.origin.y = event->pos().y();
    [m_wrpper->m_refButton setFrame:frame];
}

void CocoaButton::resizeEvent(QResizeEvent *event)
{
    NSRect frame;
    frame = [m_wrpper->m_refButton frame];
    frame.size.width = event->size().width();
    frame.size.height = event->size().height();
    [m_wrpper->m_refButton setFrame:frame];
}

setText でボタンのキャプションを変えれるようにしておきます。

void CocoaButton::setText(const QString &text)
{
    [m_wrpper->m_refButton setTitle: text.toNSString()];
}

あとは、

    CocoaButtonProxy *proxy = [[CocoaButtonProxy alloc] init:this];
    [m_refButton setTarget:proxy];
    [m_refButton setAction:@selector(clicked:)];

みたいな形で Objective-C で実装された target と action を登録して

- (IBAction)clicked:(id)sender
{
    proxyDest->handleClicked();
}

とすれば、クリックで C++ で実装されたメソッドが呼び出せます。

最後に CocoaButtonProxy から CocoaButton そしてその上位へとシグナルを飛ばすようにすれば、

connect(ui->buttonCocoa, SIGNAL(clicked()), this, SLOT(onCocoaButtonClick()));

このような形でシグナルを受け取ることができます。

Qt Creator

実際に動かすとこんな感じです。

成果物

sharkpp/MacCocoaWithQtSample に今回の記事の完全なソースを置いておきます。

参考

最後に

今回は、Touch Bar を Qt から使ってみたい、から始まり結果、かなりスケールダウンした記事となりましたが、それもこれも、初めてさわる Objective-C が原因でしたが、今回いろいろ調べてなんとなくわかってきたので Touch Bar の方も何かしらためせるといいなと思っています。

それでは、また。

明日は @nekomatu さんによる「BuildrootとQtCreatorを使ってQtアプリを開発する方法」です。 お楽しみに。


この投稿は Qt Advent Calendar 201610日目の記事です。



 /  変更履歴  /  Permalink  /  このエントリーをはてなブックマークに追加
カテゴリ: ブログ  /  タグ: Advent Calendar, Qt, AppKit, Objective-C, OS X, macOS