📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

69行目: 69行目:
<br>
<br>
これらのクラスを使い分けることにより、効率的で柔軟な画像処理と表示が可能になる。<br>
これらのクラスを使い分けることにより、効率的で柔軟な画像処理と表示が可能になる。<br>
<br><br>
== QPixmapクラスの使用例 ==
==== 画像ビューアウィジェット ====
以下の例では、画像ビューアウィジェットのクラスを定義している。<br>
<br>
<syntaxhighlight lang="c++">
// ImageViewer.hファイル
#include <QWidget>
#include <QPixmap>
#include <QLabel>
#include <QVBoxLayout>
#include <QPushButton>
#include <QFileDialog>
#include <QMessageBox>
class ImageViewer : public QWidget
{
    Q_OBJECT
private:
    QLabel      *imageLabel;  // 画像表示用ラベル
    QPushButton *loadButton;  // 画像読み込みボタン
public:
    // コンストラクタ: ウィジェットの初期化
    ImageViewer(QWidget *parent = nullptr) : QWidget(parent)
    {
      // 画像を表示するためのQLabel
      imageLabel = new QLabel(this);
      imageLabel->setAlignment(Qt::AlignCenter);
      // 画像読み込みボタン
      loadButton = new QPushButton("画像を読み込む", this);
      // ボタンクリック時にloadImage()スロットを呼び出す
      connect(loadButton, &QPushButton::clicked, this, &ImageViewer::loadImage);
      // レイアウトの設定
      QVBoxLayout *layout = new QVBoxLayout(this);
      layout->addWidget(imageLabel);
      layout->addWidget(loadButton);
      setLayout(layout);
    }
private slots:
    // 画像読み込み処理を行うスロット
    void loadImage()
    {
      // ファイル選択ダイアログを表示
      QString fileName = QFileDialog::getOpenFileName(this, "画像を開く", "", "画像ファイル (*.png *.jpg *.bmp)");
      if (!fileName.isEmpty()) {
          // 選択されたファイルからQPixmapを作成
          QPixmap pixmap(fileName);
          if (pixmap.isNull()) {
            // 画像読み込みに失敗した場合はエラーメッセージを表示
            QMessageBox::critical(this, "エラー", "画像の読み込みに失敗");
            return;
          }
          // 読み込んだ画像をラベルに表示 (アスペクト比を保持してリサイズ)
          imageLabel->setPixmap(pixmap.scaled(imageLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
      }
    }
};
</syntaxhighlight>
<br>
==== アニメーションスプライトシート ====
以下の例では、スプライトシートを使用したアニメーションクラスを定義している。<br>
<br>
<syntaxhighlight lang="c++">
// AnimatedSprite.hファイル
#include <QWidget>
#include <QPixmap>
#include <QTimer>
#include <QPainter>
class AnimatedSprite : public QWidget
{
    Q_OBJECT
private:
    QPixmap spriteSheet;  // スプライトシート
    QTimer *timer;        // アニメーション用タイマ
    int currentFrame;    // 現在のフレーム番号
    int frameWidth;      // 1フレームの幅
    int frameHeight;      // 1フレームの高さ
 
protected:
    // ペイントイベント: 現在のフレームを描画
    void paintEvent(QPaintEvent *event) override
    {
      Q_UNUSED(event);
      QPainter painter(this);
      // スプライトシートから現在のフレームを切り出して描画
      painter.drawPixmap(0, 0, spriteSheet, currentFrame * frameWidth, 0, frameWidth, frameHeight);
    }
public:
    // コンストラクタ: スプライトシートの読み込みとタイマの設定
    AnimatedSprite(QWidget *parent = nullptr) : QWidget(parent), currentFrame(0)
    {
      // スプライトシートの読み込み
      spriteSheet.load(":/sprites/character.png");  // スプライトシートのリソースパス
      if (spriteSheet.isNull()) {
          qWarning() << "スプライトシートの読み込みに失敗";
          return;
      }
      // スプライトシートの各フレームのサイズを計算
      frameWidth = spriteSheet.width() / 4;  // 4フレームあると仮定
      frameHeight = spriteSheet.height();
      // アニメーション用タイマの設定
      timer = new QTimer(this);
      connect(timer, &QTimer::timeout, this, &AnimatedSprite::nextFrame);
      timer->start(100);  // 100[mS]ごとにフレーム更新
      // ウィジェットのサイズを1フレームのサイズに固定
      setFixedSize(frameWidth, frameHeight);
    }
private slots:
    // 次のフレームに進むスロット
    void nextFrame()
    {
      currentFrame = (currentFrame + 1) % 4;  // 4フレームを循環
      update();                              // ウィジェットの再描画をリクエスト
    }
};
</syntaxhighlight>
<br>
==== 非同期で画像を読み込む ====
以下の例では、大きなサイズの画像を非同期で読み込むウィジェットを定義している。<br>
<br>
<syntaxhighlight lang="c++">
// AsyncImageLoader.hファイル
#include <QWidget>
#include <QPixmap>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QFuture>
#include <QtConcurrent>
#include <QFileDialog>
#include <QMessageBox>
class AsyncImageLoader : public QWidget
{
    Q_OBJECT
private:
    QLabel *imageLabel;      // 画像表示用ラベル
    QPushButton *loadButton;  // 画像読み込みボタン
 
public:
    // コンストラクタ: ウィジェットの初期化
    AsyncImageLoader(QWidget *parent = nullptr) : QWidget(parent)
    {
      // 画像表示用ラベル
      imageLabel = new QLabel(this);
      imageLabel->setAlignment(Qt::AlignCenter);
      // 画像読み込みボタン
      loadButton = new QPushButton("大きな画像を読み込む", this);
      connect(loadButton, &QPushButton::clicked, this, &AsyncImageLoader::loadImageAsync);
      // レイアウトの設定
      QVBoxLayout *layout = new QVBoxLayout(this);
      layout->addWidget(imageLabel);
      layout->addWidget(loadButton);
      setLayout(layout);
    }
private slots:
    // 非同期で画像を読み込むスロット
    void loadImageAsync()
    {
      // ファイル選択ダイアログを表示
      QString fileName = QFileDialog::getOpenFileName(this, "大きな画像を開く", "", "画像ファイル (*.png *.jpg *.bmp)");
      if (!fileName.isEmpty()) {
          // UIの更新(ボタンを無効化し、テキストを変更)
          loadButton->setEnabled(false);
          loadButton->setText("読み込み中...");
          // 非同期で画像を読み込む
          QFuture<QPixmap> future = QtConcurrent::run([fileName]() {
            return QPixmap(fileName);
          });
          // 非同期処理の完了を監視するためのQFutureWatcherを設定
          QFutureWatcher<QPixmap> *watcher = new QFutureWatcher<QPixmap>(this);
          connect(watcher, &QFutureWatcher<QPixmap>::finished, this, [this, watcher]() {
            QPixmap pixmap = watcher->result();
            if (pixmap.isNull()) {
                // 画像読み込みに失敗した場合はエラーメッセージを表示
                QMessageBox::critical(this, "エラー", "画像の読み込みに失敗");
            }
            else {
                // 読み込んだ画像をラベルに表示 (アスペクト比を保持してリサイズ)
                imageLabel->setPixmap(pixmap.scaled(imageLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
            }
            // UIの更新 (ボタンを再度有効化して、元のテキストに戻す)
            loadButton->setEnabled(true);
            loadButton->setText("大きな画像を読み込む");
            // watcherのメモリを解放
            watcher->deleteLater();
          });
          // 非同期処理の監視を開始
          watcher->setFuture(future);
      }
    }
};
</syntaxhighlight>
<br><br>
<br><br>