Qt GUIにおける座標系のしくみ:論理座標、ウィジェット座標、グローバル座標を理解しよう


論理座標系

  • 例:ボタンの位置を (10, 20) と指定すると、ウィジェット左上から 10 ピクセル水平方向に、20 ピクセル下方向にボタンが表示されます。
  • QPainter で描画を行う場合、この論理座標系がデフォルトで使用されます。
  • ウィジェット固有の座標系で、原点はウィジェット左上、X 軸は右方向、Y 軸は下方向となります。

ウィジェット座標系

  • 例:子ウィジェットを親ウィジェットの (50, 50) に配置したい場合、widget->move(50, 50) と記述します。
  • ウィジェットの位置や大きさをこの座標系で指定できます。
  • 親ウィジェット座標系を基にした座標系で、原点は親ウィジェットの左上となります。

グローバル座標系

  • 例:あるウィジェットの位置をグローバル座標系で取得するには、widget->mapToGlobal(pos) と記述します。
  • ウィジェット間の位置関係をこの座標系で把握できます。
  • デスクトップ全体を基にした座標系で、原点は画面左上となります。

座標系間の変換

各座標系間には変換関数** mapTo() mapFrom() **が用意されています。

  • 例:widget->mapFromGlobal(pos) は、グローバル座標を論理座標系に変換します。
  • mapFrom(): 別の座標系を現在の座標系に変換します。
  • 例:widget->mapToParent(pos) は、論理座標を親ウィジェット座標系に変換します。
  • mapTo(): ある座標系を別の座標系に変換します。
  • 座標系の理解は、GUI レイアウトや要素配置を正確に行うために重要です。
  • Qt 座標系は OpenGL 座標系とは異なるので、注意が必要です。
  • 3D グラフィックの場合は、X, Y, Z 軸を含む 3 次元の座標系が用いられます。


論理座標系での描画

#include <QApplication>
#include <QLabel>
#include <QPainter>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  // ウィジェットの作成
  QLabel label("Hello, Qt!");

  // ウィジェットの表示
  label.show();

  // ペイントイベントハンドラの設定
  label.installEventFilter(new MyEventFilter);

  return app.exec();
}

class MyEventFilter : public QEventFilter {
public:
  bool eventFilter(QObject *obj, QEvent *event) override {
    if (event->type() == QEvent::Paint) {
      // ペインタを取得
      QPainter painter(&label);

      // 論理座標系で線を描画
      painter.drawLine(10, 20, 50, 60);

      // 論理座標系でテキストを描画
      painter.drawText(70, 40, "Qt GUI");

      return true;
    } else {
      return QEventFilter::eventFilter(obj, event);
    }
  }
};

ウィジェット座標系での配置

#include <QApplication>
#include <QLabel>
#include <QWidget>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  // 親ウィジェットの作成
  QWidget parentWidget;

  // 子ウィジェットの作成
  QLabel label1("Label 1");
  QLabel label2("Label 2");

  // 子ウィジェットの配置 (ウィジェット座標系)
  label1.move(20, 20);
  label2.move(100, 50);

  // 子ウィジェットを親ウィジェットに追加
  label1.setParent(&parentWidget);
  label2.setParent(&parentWidget);

  // 親ウィジェットの表示
  parentWidget.show();

  return app.exec();
}

このコードでは、2 つのラベルをそれぞれ異なる位置に配置するために、move() 関数を使用してウィジェット座標系を指定しています。

#include <QApplication>
#include <QLabel>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  // ラベルの作成
  QLabel label("Hello, Qt!");

  // ラベルの表示
  label.show();

  // グローバル座標系でのラベルの位置取得
  QPoint globalPos = label.mapToGlobal(QPoint(10, 20));

  // 取得した位置情報の出力
  qDebug() << "Global position: " << globalPos;

  return app.exec();
}

このコードでは、ラベルの位置をグローバル座標系で取得し、コンソールに出力しています。

上記はあくまでも基本的な例であり、実際の用途に合わせて様々な応用が可能となります。

  • 座標系の変換関数以外にも、ウィジェットのサイズや位置を取得・設定する関数などが用意されています。


参照系

  • 物理学や工学など、空間的な関係性を厳密に記述する必要がある場面で適しています。
  • 空間における位置や動きを記述するための基準となる体系を指します。

座標軸

  • 3 次元空間における位置を直感的に表す際に適しています。
  • X, Y, Z などの軸で構成される体系を指します。

基準点

  • 特定の場所や物体を基準とする際に適しています。
  • 位置や動きを測るための原点を指します。

フレーム

  • ロボット工学やコンピュータグラフィックスなど、3 次元空間におけるオブジェクトの動きを扱う場面で適しています。
  • 空間における位置や姿勢を定義する座標系と、原点、回転、拡大などの変換情報を含むものを指します。

グリッド

  • 地図や図面など、空間上の位置関係をわかりやすく表現する際に適しています。
  • 空間を規則的な線で区切ったものを指します。

メッシュ

  • コンピュータグラフィックスなどで、複雑な形状を表現する際に適しています。
  • 3 次元空間を三角形や四角形などの要素で構成したものを指します。

  • 3D CAD モデルを作成する場合は、"座標軸" や "メッシュ" が適切です。
  • 地図上で場所を特定する場合は、"座標系" や "グリッド" が適切です。
  • ロボットアームの動きを記述する場合は、"参照系" や "フレーム" が適切です。

上記以外にも、"座標空間"、"位置情報"、"空間認識" などの表現も状況に応じて使用できます。

重要なのは、伝えたい内容を明確に理解し、それに合った表現を選択することです。

  • 相手との共通認識がある場合は、略語や専門用語を使用しても問題ありません。
  • 専門的な分野で使用される場合は、より専門的な用語を用いることも適切です。