Qtプログラミングで色を操る!QColorクラスの基礎と実践

2025-05-27

QColorクラスは、Qtフレームワークにおいて色を表現・操作するための基本的なクラスです。GUIアプリケーションで要素の色を設定したり、グラフィックを描画したりする際に頻繁に使用されます。

特徴と主な機能

QColorクラスには、以下のような特徴と機能があります。

  1. 多様な色モデルのサポート:

    • RGB (Red, Green, Blue): 赤、緑、青の3原色の組み合わせで色を表現します。コンピュータのディスプレイで色を表示する際に最も一般的に使われます。
    • HSV (Hue, Saturation, Value): 色相、彩度、明度の3つの要素で色を表現します。人間が直感的に色を理解しやすいモデルです。
    • CMYK (Cyan, Magenta, Yellow, Black): シアン、マゼンタ、イエロー、ブラックの4色で色を表現します。主に印刷業界で使われます。
    • アルファチャネル (Alpha Channel): 上記の色モデルに加えて、透明度を表現するためのアルファチャネルをサポートしています。0(完全な透明)から255(完全な不透明)の範囲で指定します。
  2. 色の生成方法:

    • RGB値による指定: QColor(int r, int g, int b, int a = 255) のように、赤、緑、青、透明度の値を直接指定して色を作成できます。
    • 名前による指定: "red", "blue", "darkGray" のような色の名前(SVG 1.0のカラーネームに対応)を使って色を作成できます。
    • 16進数文字列による指定: "#RRGGBB""#AARRGGBB" のような16進数文字列で色を指定することも可能です。
    • 定義済みの色: Qt::red, Qt::blue, Qt::white, Qt::black など、Qtに予め定義されているグローバルな色を使用できます。
  3. 色の取得と変換:

    • 各色モデルのコンポーネント(例: red(), hue(), cyan())を個別に取得できます。
    • getRgb(), getHsv(), getCmyk() などのメソッドを使って、一度に複数のコンポーネントを取得することも可能です。
    • toRgb(), toHsv(), toCmyk() などのメソッドで、異なる色モデルに変換した新しいQColorオブジェクトを取得できます。
  4. 色の操作:

    • lighter()darker() メソッドを使って、現在の色を明るくしたり暗くしたりできます。
    • setRgb(), setHsv(), setCmyk() などで、既存のQColorオブジェクトの色を変更できます。
  5. 浮動小数点精度での指定:

    • 整数の0-255の範囲だけでなく、0.0-1.0の浮動小数点数で色のコンポーネントを指定する関数(例: redF(), setHsvF())も提供されています。
  6. プラットフォーム独立性:

    • QColorはプラットフォームやデバイスに依存しないように設計されており、Qtが色のマッピングを抽象化してくれます。
#include <QColor>
#include <QDebug> // デバッグ出力用

int main() {
    // RGB値で色を作成(赤、緑、青、不透明度)
    QColor redColor(255, 0, 0); // 完全な赤
    QColor semiTransparentBlue(0, 0, 255, 128); // 半透明の青

    qDebug() << "Red Color RGB:" << redColor.red() << redColor.green() << redColor.blue();
    qDebug() << "Semi-Transparent Blue Alpha:" << semiTransparentBlue.alpha();

    // 色の名前で作成
    QColor greenColor("green");
    qDebug() << "Green Color Name:" << greenColor.name(); // #008000FF のような形式で出力

    // 16進数文字列で作成
    QColor purpleColor("#800080"); // 紫色
    qDebug() << "Purple Color RGB:" << purpleColor.red() << purpleColor.green() << purpleColor.blue();

    // 定義済みの色
    QColor defaultBlue = Qt::blue;
    qDebug() << "Default Blue RGB:" << defaultBlue.red() << defaultBlue.green() << defaultBlue.blue();

    // HSV値で色を作成し、RGB値を取得
    QColor hsvColor;
    hsvColor.setHsv(0, 255, 255); // 色相0(赤)、彩度最大、明度最大
    qDebug() << "HSV Color (Hue 0) RGB:" << hsvColor.red() << hsvColor.green() << hsvColor.blue();

    // 色を明るくする
    QColor lighterRed = redColor.lighter(150); // 150%明るくする
    qDebug() << "Lighter Red RGB:" << lighterRed.red() << lighterRed.green() << lighterRed.blue();

    // 色が有効かどうかのチェック
    QColor invalidColor(999, 0, 0); // 範囲外の値
    qDebug() << "Invalid Color is valid?" << invalidColor.isValid(); // false を出力

    return 0;
}


コンパイルエラー: fatal error: QColor: No such file or directory

原因

QColorクラスを使用するために必要なヘッダーファイルがインクルードされていないか、Qtのモジュールが.proファイルに正しく追加されていない場合に発生します。

トラブルシューティング

  • .proファイルにモジュールを追加: QColorは通常、QtのQtGuiモジュール(Qt 5以降)またはQtWidgetsモジュール(QGuiApplicationを使用しない場合)に属しています。プロジェクトの.proファイルに以下の行を追加しているか確認してください。

    QT += gui  # QColorを使用するために必要
    QT += widgets # GUIアプリケーションでQWidgetなどを使う場合に必要
    

    Qt 6では、QT += guiではなくQT += Guiのように大文字で指定する必要があります。

  • ヘッダーのインクルードを確認: QColorを使用するC++ファイルの先頭に、以下の行を追加しているか確認してください。

    #include <QColor>
    

ランタイムエラー/不正な色表示: 不適切な値の指定

QColorのコンストラクタやsetRgb()などのメソッドに、範囲外の値を渡した場合に、期待通りの色が表示されないことがあります。例えば、RGB値は通常0から255の範囲です。

  • isValid()メソッドでチェック: QColorオブジェクトが有効な色を表しているかどうかは、isValid()メソッドで確認できます。無効な値を設定するとisValid()falseを返します。
    QColor myColor(300, 0, 0); // 無効なRGB値
    if (!myColor.isValid()) {
        qWarning() << "Error: Invalid color specified!";
    }
    
  • 値の範囲を確認:
    • RGB: 各コンポーネント(赤、緑、青、アルファ)は0から255の整数値です。
    • HSV: 色相(Hue)は0から359、彩度(Saturation)と明度(Value)は0から255の整数値です。
    • 浮動小数点版のメソッド(例: setRgbF())を使用する場合は、0.0から1.0の範囲で指定します。

ランタイムエラー/警告: QColor::setNamedColor: Unknown color name '...'

QColorコンストラクタやsetNamedColor()メソッドに、Qtが認識しない色の名前を文字列で渡した場合に発生します。

  • 名前ではなくRGB値で指定: もしカスタムの色を使用したい場合は、色の名前ではなくRGB値(QColor(r, g, b))または16進数文字列(QColor("#RRGGBB"))で直接指定することを検討してください。
    QColor unknownColor("myCustomColor"); // これはおそらく警告を出す
    QColor validColor("darkGray");       // これは問題ない
    
    // 代替案:
    QColor customColor(123, 45, 67);     // RGB値で指定
    QColor hexColor("#7B2D43");          // 16進数で指定
    
  • 正しい色の名前を使用: QtはSVG 1.0で定義されている色の名前(例: "red", "blue", "darkGray", "lightGreen"など)をサポートしています。スペルミスがないか、またはサポートされていない独自の色の名前を使用していないか確認してください。

QMLとの連携に関する問題: TypeError: Type error

C++で定義したQColorプロパティをQML側で操作しようとした際に、型変換がうまくいかない場合に発生することがあります。

  • QMLとC++間の型変換: Qtは通常、QColorをQMLのcolor型に自動的に変換します。しかし、QML側で期待される型とC++側で提供される型が一致しない場合に問題が発生します。
    • C++からQMLへQColorを渡す場合は、Q_PROPERTY(QColor myColor ...)として定義し、QML側で直接myComponent.myColor = someColorのように代入してみてください。
    • もしQ_INVOKABLEな関数でQColorを返す場合は、その関数の戻り値の型がQColorであることを確認してください。文字列で返す場合は、QML側で文字列として受け取り、QMLのQt.color()関数などで変換することを検討します。
    // C++側
    class MyCppObject : public QObject {
        Q_OBJECT
        Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY backgroundColorChanged)
    
    public:
        QColor backgroundColor() const { return m_backgroundColor; }
        void setBackgroundColor(const QColor& color) {
            if (m_backgroundColor != color) {
                m_backgroundColor = color;
                emit backgroundColorChanged();
            }
        }
    signals:
        void backgroundColorChanged();
    private:
        QColor m_backgroundColor;
    };
    
    // QML側
    MyCppObject {
        id: myObject
        backgroundColor: "red" // QMLで直接色名を指定
    }
    Rectangle {
        color: myObject.backgroundColor // C++から受け取った色を使用
    }
    

QColorのインスタンス化と寿命

QColorは軽量な値クラスなので、通常はスタックで作成したり、値渡しで利用したりしても問題ありません。しかし、誤ってポインタとして扱ったり、不適切なメモリ管理を行ったりすると問題が発生する可能性があります。

  • ポインタの使用は避ける: 特別な理由がない限り、QColor*のようにポインタで扱うことは避けるべきです。
    // 悪い例 (通常は不要)
    QColor* myColorPtr = new QColor(0, 0, 255);
    // ...
    delete myColorPtr; // メモリリークを避けるために解放が必要
    
    // 良い例
    QColor myColor(0, 0, 255);
    
  • 値クラスとしての理解: QColorQStringQPointなどと同様に値クラスです。コピーは高速で、所有権の管理についてあまり心配する必要はありません。
    QColor color1 = Qt::red;
    QColor color2 = color1; // 値がコピーされる
    

異なる色空間(RGB, HSV, CMYK)間での変換や、特定のコンポーネント(例: アルファ値)の扱いの誤解。

  • 変換メソッドの利用: 例えば、RGBで色を設定した後、HSV値を取得したい場合はtoHsv()メソッドを使用します。
    QColor rgbColor(255, 128, 0); // オレンジ
    QColor hsvColor = rgbColor.toHsv();
    qDebug() << "Hue:" << hsvColor.hue() << "Saturation:" << hsvColor.saturation() << "Value:" << hsvColor.value();
    
  • アルファ値の確認: 色が透明であるはずなのに透明にならない場合、アルファ値が255(完全な不透明)になっていないか確認してください。
    QColor transparentRed(255, 0, 0, 100); // 100は半透明
    // QPainterなどで描画する際に、QPainter::CompositionModeを設定しないと透明度が反映されない場合がある
    
  • 色空間の理解:
    • RGB: 画面表示に最適。各チャネルが独立して光の強度を示す。
    • HSV: 人間が直感的に色を調整するのに便利(色相をずらす、彩度を下げるなど)。
    • CMYK: 印刷用。インクの混合をシミュレートする。


QColorオブジェクトの基本的な作成と値の取得

最も基本的なQColorオブジェクトの作成方法と、その色コンポーネント(RGB、アルファ値)の取得方法です。

#include <QApplication> // QApplicationはQtアプリケーションの基本的な制御を提供
#include <QLabel>       // テキストや画像を表示するためのウィジェット
#include <QPalette>     // ウィジェットの色を設定するためのクラス
#include <QColor>       // 色を表現するクラス
#include <QDebug>       // デバッグ出力用

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

    // --- QColorの作成例 ---

    // 1. RGB値(赤、緑、青、アルファ)で作成
    //    各値は0〜255の範囲。アルファは省略すると255(不透明)
    QColor redColor(255, 0, 0); // 純粋な赤
    QColor semiTransparentBlue(0, 0, 255, 128); // 半透明の青

    // 2. 色の名前(SVG 1.0のカラーネーム)で作成
    QColor greenColor("green");         // "green"
    QColor darkGrayColor("darkGray");   // "darkGray"

    // 3. 16進数文字列で作成
    //    #RRGGBB または #AARRGGBB 形式
    QColor purpleColor("#800080");     // 紫色
    QColor orangeColor("#FFA500");     // オレンジ色
    QColor transparentYellow("#80FFFF00"); // 半透明の黄色

    // 4. Qtの定義済み定数で作成
    QColor blueColor = Qt::blue;
    QColor whiteColor = Qt::white;

    // --- 色コンポーネントの取得例 ---
    qDebug() << "--- Color Component Values ---";

    qDebug() << "Red Color:";
    qDebug() << "  RGB:" << redColor.red() << redColor.green() << redColor.blue();
    qDebug() << "  Alpha:" << redColor.alpha();
    qDebug() << "  Hex Name:" << redColor.name(QColor::HexRgb); // #FF0000

    qDebug() << "Semi-Transparent Blue:";
    qDebug() << "  RGB:" << semiTransparentBlue.red() << semiTransparentBlue.green() << semiTransparentBlue.blue();
    qDebug() << "  Alpha:" << semiTransparentBlue.alpha();
    qDebug() << "  Hex Name (ARGB):" << semiTransparentBlue.name(QColor::HexArgb); // #800000FF

    qDebug() << "Purple Color:";
    qDebug() << "  RGB:" << purpleColor.red() << purpleColor.green() << purpleColor.blue();
    qDebug() << "  Alpha:" << purpleColor.alpha();
    qDebug() << "  Is valid?" << purpleColor.isValid(); // true

    // 無効な色(範囲外の値を指定)
    QColor invalidColor(300, 0, 0);
    qDebug() << "Invalid Color is valid?" << invalidColor.isValid(); // false を出力

    // --- QLabelを使った色の表示例 ---
    QLabel *label = new QLabel("Hello QColor!");
    label->setAlignment(Qt::AlignCenter);

    // 背景色を設定 (QPaletteを使用)
    QPalette palette = label->palette();
    palette.setColor(QPalette::Window, orangeColor); // ウィジェットの背景色
    palette.setColor(QPalette::WindowText, Qt::white); // テキストの色
    label->setAutoFillBackground(true); // パレットの背景色を適用するために必要
    label->setPalette(palette);

    // 半透明の背景を持つラベル
    QLabel *transparentLabel = new QLabel("Transparent Text");
    transparentLabel->setAlignment(Qt::AlignCenter);
    QPalette transparentPalette = transparentLabel->palette();
    transparentPalette.setColor(QPalette::Window, transparentYellow);
    transparentPalette.setColor(QPalette::WindowText, Qt::darkBlue);
    transparentLabel->setAutoFillBackground(true);
    transparentLabel->setPalette(transparentPalette);

    // ウィンドウにラベルを配置
    QWidget *window = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout(window);
    layout->addWidget(label);
    layout->addWidget(transparentLabel); // 半透明のラベルも追加
    window->setWindowTitle("QColor Example");
    window->resize(300, 150);
    window->show();

    return app.exec();
}

解説:

  • QLabelウィジェットの背景色や文字色を設定するためにQPaletteクラスを使用しています。setAutoFillBackground(true)を呼び出すことで、パレットの背景色がウィジェットに適用されます。
  • isValid()QColorオブジェクトが有効な色を表しているかを確認するのに便利です。
  • name() メソッドは色を16進数文字列として返します。引数にQColor::HexRgbQColor::HexArgbを指定することで、アルファ値を含む形式で出力できます。
  • red(), green(), blue(), alpha() メソッドで各コンポーネントの値を取得できます。
  • QColorの作成方法は複数あります。最も一般的なのはRGB値の直接指定、色の名前(文字列)、16進数文字列です。

色モデル間の変換 (RGB, HSV, CMYK)

QColorは、RGB以外にもHSV(Hue, Saturation, Value)やCMYK(Cyan, Magenta, Yellow, Black)といった色モデルをサポートしており、相互に変換することができます。

#include <QApplication>
#include <QLabel>
#include <QColor>
#include <QDebug>
#include <QVBoxLayout>

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

    QColor originalColor(150, 75, 200); // オリジナルの色 (紫っぽい色)

    qDebug() << "--- Original Color (RGB) ---";
    qDebug() << "R:" << originalColor.red() << "G:" << originalColor.green() << "B:" << originalColor.blue() << "A:" << originalColor.alpha();

    // --- RGBからHSVへの変換 ---
    QColor hsvColor = originalColor.toHsv();
    qDebug() << "\n--- Converted to HSV ---";
    qDebug() << "Hue:" << hsvColor.hue() << "Saturation:" << hsvColor.saturation() << "Value:" << hsvColor.value() << "Alpha:" << hsvColor.alpha();
    qDebug() << "(float) H:" << hsvColor.hueF() << "S:" << hsvColor.saturationF() << "V:" << hsvColor.valueF();

    // --- RGBからCMYKへの変換 ---
    QColor cmykColor = originalColor.toCmyk();
    qDebug() << "\n--- Converted to CMYK ---";
    qDebug() << "Cyan:" << cmykColor.cyan() << "Magenta:" << cmykColor.magenta() << "Yellow:" << cmykColor.yellow() << "Black:" << cmykColor.black() << "Alpha:" << cmykColor.alpha();
    qDebug() << "(float) C:" << cmykColor.cyanF() << "M:" << cmykColor.magentaF() << "Y:" << cmykColor.yellowF() << "K:" << cmykColor.blackF();

    // --- HSV値からQColorを作成し、RGBを取得 ---
    QColor hsvCreatedColor;
    hsvCreatedColor.setHsv(0, 255, 255); // 色相0(赤)、彩度最大、明度最大
    qDebug() << "\n--- HSV Created Color (Red) ---";
    qDebug() << "R:" << hsvCreatedColor.red() << "G:" << hsvCreatedColor.green() << "B:" << hsvCreatedColor.blue(); // 255 0 0 となる

    // --- QLabels for visualization ---
    QWidget *window = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout(window);

    auto createColorLabel = [](const QColor &color, const QString &text) {
        QLabel *label = new QLabel(text);
        label->setAlignment(Qt::AlignCenter);
        QPalette palette;
        palette.setColor(QPalette::Window, color);
        label->setAutoFillBackground(true);
        label->setPalette(palette);
        return label;
    };

    layout->addWidget(createColorLabel(originalColor, "Original RGB Color"));
    layout->addWidget(createColorLabel(hsvColor.toRgb(), "Converted back from HSV")); // HSVからRGBに戻す
    layout->addWidget(createColorLabel(cmykColor.toRgb(), "Converted back from CMYK")); // CMYKからRGBに戻す
    layout->addWidget(createColorLabel(hsvCreatedColor, "Created from HSV"));

    window->setWindowTitle("QColor Conversions");
    window->resize(300, 250);
    window->show();

    return app.exec();
}

解説:

  • *_F() の付くメソッド(例: hueF())は、浮動小数点精度で値を返します(0.0〜1.0)。
  • setHsv(), setRgb() などのメソッドを使って、既存のQColorオブジェクトの色モデルを変更することも可能です。
  • hue(), saturation(), value(), cyan(), magenta(), yellow(), black() メソッドで、それぞれの色モデルのコンポーネント値を取得できます。
  • toHsv(), toCmyk() メソッドを使って、現在のQColorオブジェクトを新しいHSVまたはCMYKのQColorオブジェクトに変換します。

QColorは、色の明るさを変更したり、他の色とブレンドしたりする機能も提供します。

#include <QApplication>
#include <QLabel>
#include <QColor>
#include <QDebug>
#include <QVBoxLayout>
#include <QPushButton>
#include <QSlider>

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

    QWidget *window = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout(window);

    // --- 明るさの変更 ---
    QLabel *originalLabel = new QLabel("Original Red");
    originalLabel->setAlignment(Qt::AlignCenter);
    QColor baseRed(200, 0, 0); // 基本の赤
    QPalette originalPalette = originalLabel->palette();
    originalPalette.setColor(QPalette::Window, baseRed);
    originalLabel->setAutoFillBackground(true);
    originalLabel->setPalette(originalPalette);
    layout->addWidget(originalLabel);

    QLabel *lighterLabel = new QLabel("Lighter Red (150%)");
    lighterLabel->setAlignment(Qt::AlignCenter);
    QColor lighterRed = baseRed.lighter(150); // 150%明るくする
    QPalette lighterPalette = lighterLabel->palette();
    lighterPalette.setColor(QPalette::Window, lighterRed);
    lighterLabel->setAutoFillBackground(true);
    lighterLabel->setPalette(lighterPalette);
    layout->addWidget(lighterLabel);

    QLabel *darkerLabel = new QLabel("Darker Red (50%)");
    darkerLabel->setAlignment(Qt::AlignCenter);
    QColor darkerRed = baseRed.darker(50); // 50%暗くする
    QPalette darkerPalette = darkerLabel->palette();
    darkerPalette.setColor(QPalette::Window, darkerRed);
    darkerLabel->setAutoFillBackground(true);
    darkerLabel->setPalette(darkerPalette);
    layout->addWidget(darkerLabel);

    // --- 色のブレンド ---
    QLabel *blendedLabel = new QLabel("Blended Color");
    blendedLabel->setAlignment(Qt::AlignCenter);
    QColor colorA = Qt::blue;
    QColor colorB = Qt::yellow;
    // colorAとcolorBを50:50でブレンド
    QColor blendedColor = colorA.lighter(colorB.lighter(200)).darker(colorA.darker(100)); // このブレンド方法は一例
    // より簡単なブレンド: QColor::fromRgbF() などで手動でR,G,Bの平均を取る
    // QColor blendedColor = QColor::fromRgbF((colorA.redF() + colorB.redF()) / 2.0,
    //                                        (colorA.greenF() + colorB.greenF()) / 2.0,
    //                                        (colorA.blueF() + colorB.blueF()) / 2.0);
    // あるいは、QPainter::CompositionMode を使って描画時にブレンドする方が一般的
    
    // 実際にはより数学的なブレンドやQPainterを使うことが多い
    // ここでは単純な例として、それぞれの明るさを調整して加算
    QColor simpleBlend = QColor(
        (colorA.red() + colorB.red()) / 2,
        (colorA.green() + colorB.green()) / 2,
        (colorA.blue() + colorB.blue()) / 2
    );

    QPalette blendedPalette = blendedLabel->palette();
    blendedPalette.setColor(QPalette::Window, simpleBlend); // 平均色をセット
    blendedLabel->setAutoFillBackground(true);
    blendedLabel->setPalette(blendedPalette);
    layout->addWidget(blendedLabel);
    
    // スライダーで色の明るさをリアルタイムで調整する例
    QSlider *brightnessSlider = new QSlider(Qt::Horizontal);
    brightnessSlider->setRange(0, 200); // 0%から200%まで
    brightnessSlider->setValue(100); // 初期値は100%
    layout->addWidget(new QLabel("Adjust Red Brightness:"));
    layout->addWidget(brightnessSlider);

    // スライダーの値が変更されたらラベルの背景色を更新
    QObject::connect(brightnessSlider, &QSlider::valueChanged, [=](int value){
        QColor currentRed = baseRed.lighter(value);
        QPalette p = originalLabel->palette();
        p.setColor(QPalette::Window, currentRed);
        originalLabel->setPalette(p);
    });

    window->setWindowTitle("QColor Operations");
    window->resize(350, 400);
    window->show();

    return app.exec();
}

解説:

  • スライダーとQObject::connectを使用して、色の明るさをリアルタイムで変更するインタラクティブな例も示しています。
  • 色のブレンドはより複雑ですが、QColor自体には直接的なブレンドメソッドはありません。一般的には、各RGBコンポーネントを数学的に平均したり、QPainterのコンポジションモード(QPainter::CompositionMode_SourceOverなど)を使用して描画時にブレンドします。上記の例では単純な平均化でブレンドをシミュレートしています。
  • lighter(factor)darker(factor)メソッドは、現在の色を指定されたファクター(パーセンテージ、100が元の明るさ)で明るくしたり暗くしたりします。


QColor自体は色の表現とその操作に特化したクラスであり、これに代わる「色」の概念を扱う直接的なクラスは Qt にはほとんどありません。しかし、「色の指定方法」「色の管理方法」「色を使った描画方法」という観点から、QColorと連携したり、間接的に色の概念を扱う代替・関連技術を説明します。

CSS (Cascading Style Sheets) による色の指定

Qt のウィジェットやアプリケーション全体の色を制御する強力な方法の一つに、CSS(Qt Style Sheets)があります。これはウェブ開発で使われるCSSと非常によく似ており、ウィジェットのプロパティ(背景色、文字色、ボーダー色など)を直接指定できます。

特徴

  • 特定のウィジェットタイプ、ID、クラスなどに対してスタイルを適用できる。
  • ランタイムでスタイルを変更できるため、テーマ変更などに利用できる。
  • 宣言的にスタイルを記述できるため、見た目のカスタマイズが容易。

QColorとの関係

CSSで色を指定する際も、結局は色の名前や16進数コードを使用するため、内部的にはQColorが使用されています。しかし、開発者からは直接QColorオブジェクトを操作するよりも、文字列ベースで色を指定する形になります。

#include <QApplication>
#include <QPushButton>
#include <QWidget>
#include <QVBoxLayout>

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

    QPushButton *button1 = new QPushButton("Blue Button");
    QPushButton *button2 = new QPushButton("Custom Styled Button");

    // CSSで背景色と文字色を設定
    button1->setStyleSheet("background-color: blue; color: white;");

    // より複雑なスタイル設定
    button2->setStyleSheet(
        "QPushButton {"
        "   background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FF6600, stop: 1 #FF0000);" // グラデーション
        "   color: white;"
        "   border-style: outset;"
        "   border-width: 2px;"
        "   border-radius: 10px;"
        "   border-color: #880000;"
        "   font: bold 14px;"
        "   padding: 6px;"
        "}"
        "QPushButton:pressed {" // 押された時のスタイル
        "   background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #FF0000, stop: 1 #FF6600);"
        "   border-style: inset;"
        "}"
    );

    QWidget *window = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout(window);
    layout->addWidget(button1);
    layout->addWidget(button2);
    window->setWindowTitle("Qt Style Sheets Example");
    window->show();

    return app.exec();
}

QPaletteによるテーマ/UI要素ごとの色の管理

QPaletteクラスは、ウィジェットの各「役割(Role)」に応じた色を管理するためのクラスです。例えば、ウィジェットの背景色(Window)、文字色(WindowText)、ボタンの背景色(Button)、ボタンの文字色(ButtonText)など、UI要素が持つ様々な色の役割を抽象化しています。

  • アプリケーション全体、または個々のウィジェットに対してパレットを設定できる。
  • システム設定やデスクトップ環境のテーマに追従できる。
  • ウィジェットの状態(アクティブ、非アクティブ、無効)に応じた色グループを持つ。

QPaletteは内部的にQColorオブジェクトを使って色を保持します。QPalette::setColor()QPalette::brush()などでQColorオブジェクトを渡したり、受け取ったりします。

#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QPalette>
#include <QVBoxLayout>

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

    QLabel *label = new QLabel("Palette Example");
    QPushButton *button = new QPushButton("Click Me");

    // ウィジェットのパレットを取得
    QPalette labelPalette = label->palette();
    // ラベルの背景色と文字色を設定
    labelPalette.setColor(QPalette::Window, Qt::magenta); // 背景色
    labelPalette.setColor(QPalette::WindowText, Qt::yellow); // 文字色
    label->setAutoFillBackground(true); // 背景色を適用するために必要
    label->setPalette(labelPalette);

    // ボタンのパレットを個別に設定
    QPalette buttonPalette = button->palette();
    // ボタンの通常時の背景色と文字色を設定
    buttonPalette.setColor(QPalette::Button, QColor(50, 150, 250)); // 明るい青
    buttonPalette.setColor(QPalette::ButtonText, Qt::white);
    // ボタンの無効時の文字色を設定
    buttonPalette.setColor(QPalette::Disabled, QPalette::ButtonText, Qt::darkGray);
    button->setPalette(buttonPalette);

    // ボタンを無効にしてみる
    // button->setEnabled(false);

    QWidget *window = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout(window);
    layout->addWidget(label);
    layout->addWidget(button);
    window->setWindowTitle("QPalette Example");
    window->show();

    return app.exec();
}

QRgb型と非メンバ関数 (qRgb, qAlpha, qRedなど)

QColorクラスが導入される以前、Qt 1.x の時代などでは、色を単なる unsigned int 型で表現することが一般的でした。この unsigned int は、通常 0xAARRGGBB の形式でアルファ、赤、緑、青の各コンポーネントを格納します。Qt はこの QRgb 型(unsigned intのtypedef)と、それを操作するための非メンバ関数を提供しています。

  • QImageのピクセルデータへのアクセスなどで使用されることがある。
  • パフォーマンスが非常に重視されるピクセル操作などで直接バイトを操作するのと同等の感覚で扱える。
  • 低レベルでの色の操作が必要な場合や、古いコードベースとの互換性が必要な場合に利用。

QColorQRgb型との相互変換が可能です(例: QColor::fromRgb(QRgb)QColor::rgb())。通常、QColorを使用する方がオブジェクト指向的で安全ですが、特定の場合にQRgbを直接扱うことがあります。

#include <QApplication>
#include <QImage>
#include <QPainter>
#include <QLabel>
#include <QRgb> // QRgb型と関連関数

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

    // QRgb値の作成
    QRgb red = qRgb(255, 0, 0); // 赤
    QRgb semiTransparentGreen = qRgba(0, 255, 0, 128); // 半透明の緑

    // QRgb値から各コンポーネントを取得
    qDebug() << "Red (QRgb):";
    qDebug() << "  R:" << qRed(red) << "G:" << qGreen(red) << "B:" << qBlue(red);
    qDebug() << "Semi-Transparent Green (QRgb):";
    qDebug() << "  R:" << qRed(semiTransparentGreen) << "G:" << qGreen(semiTransparentGreen) << "B:" << qBlue(semiTransparentGreen) << "A:" << qAlpha(semiTransparentGreen);

    // QColorからQRgbへの変換、およびその逆
    QColor qtColor = Qt::blue;
    QRgb qColorAsRgb = qtColor.rgb(); // QColorからQRgbへ
    QColor newQtColor = QColor::fromRgb(qColorAsRgb); // QRgbからQColorへ

    qDebug() << "Qt Blue as QRgb (R,G,B):" << qRed(qColorAsRgb) << qGreen(qColorAsRgb) << qBlue(qColorAsRgb);

    // QImageのピクセル操作でQRgbを使用する例
    QImage image(100, 100, QImage::Format_ARGB32);
    for (int y = 0; y < image.height(); ++y) {
        for (int x = 0; x < image.width(); ++x) {
            // グラデーションを作成
            int r = x * 255 / image.width();
            int g = y * 255 / image.height();
            int b = 0;
            QRgb pixelColor = qRgb(r, g, b);
            image.setPixel(x, y, pixelColor);
        }
    }

    QLabel *imageLabel = new QLabel();
    imageLabel->setPixmap(QPixmap::fromImage(image));

    QWidget *window = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout(window);
    layout->addWidget(imageLabel);
    window->setWindowTitle("QRgb Example");
    window->show();

    return app.exec();
}

QBrushとQPen

QBrushは図形の「塗りつぶし」を定義するクラスで、単色だけでなく、グラデーション、パターン、画像など、様々な種類の塗りつぶしをサポートします。QPenは図形の「輪郭線」を定義するクラスで、色、幅、スタイル(実線、点線など)を指定できます。

  • 単なる色以上の塗りつぶしや線のスタイルを管理できる。
  • QPainterによる描画操作において、色を直接指定する代わりにQBrushQPenを使用することで、より豊かな視覚表現が可能になる。

QBrushQPenは、その色を指定する際にQColorオブジェクトを引数に取ります。

#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QBrush>
#include <QPen>
#include <QColor>

// 描画を行うカスタムウィジェット
class DrawingWidget : public QWidget {
protected:
    void paintEvent(QPaintEvent *event) override {
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing); // アンチエイリアス

        // --- QBrushの使用例 ---
        // 単色のブラシ (QColorを使用)
        QBrush solidBrush(Qt::red);
        painter.setBrush(solidBrush);
        painter.drawRect(10, 10, 80, 80);

        // グラデーションのブラシ (QColorを使用)
        QLinearGradient gradient(100, 10, 180, 90); // 始点と終点
        gradient.setColorAt(0, Qt::blue);    // 0%の位置は青
        gradient.setColorAt(1, Qt::yellow);  // 100%の位置は黄
        QBrush gradientBrush(gradient);
        painter.setBrush(gradientBrush);
        painter.drawEllipse(100, 10, 80, 80);

        // --- QPenの使用例 ---
        // 単色のペン (QColorを使用)
        QPen redPen(Qt::red);
        redPen.setWidth(5); // 太さ5ピクセル
        painter.setPen(redPen);
        painter.drawLine(200, 10, 280, 90);

        // 太くて点線のペン (QColorを使用)
        QPen dashedBluePen(Qt::blue);
        dashedBluePen.setWidth(3);
        dashedBluePen.setStyle(Qt::DotLine); // 点線スタイル
        painter.setPen(dashedBluePen);
        painter.drawRect(200, 10, 80, 80);

        // QBrushとQPenの組み合わせ
        QBrush purpleBrush(QColor(128, 0, 128)); // 紫色のブラシ
        QPen greenPen(Qt::darkGreen);            // 濃い緑のペン
        greenPen.setWidth(2);
        painter.setBrush(purpleBrush);
        painter.setPen(greenPen);
        painter.drawRoundedRect(10, 100, 100, 50, 10, 10); // 角丸四角形
    }
};

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

    DrawingWidget *widget = new DrawingWidget();
    widget->setWindowTitle("QBrush and QPen Example");
    widget->resize(300, 200);
    widget->show();

    return app.exec();
}

Qt 6 では、より高度なカラーマネージメントのために QColorSpace クラスが導入されました。これは、特定のデバイスや標準(sRGB、Display P3など)に対応した色空間を定義し、異なる色空間間での正確な色変換を可能にします。

  • プロフェッショナルなグラフィックアプリケーションや画像処理で重要になる。
  • HDR(High Dynamic Range)のような新しいディスプレイ技術に対応。
  • モニターや印刷デバイスの特性に合わせた色表示を可能にする。

QColorは、QColorSpaceオブジェクトを指定して色を作成したり、ある色空間の色を別の色空間に変換したりすることができます。

例(簡略化)

#include <QApplication>
#include <QColor>
#include <QColorSpace> // Qt 6以降
#include <QDebug>

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

    // sRGB色空間の赤色
    QColor srgbRed = QColor::fromRgb(255, 0, 0, QColorSpace::SRgb);

    // Display P3色空間の赤色(Qt 6.2以降で利用可能)
    // QColor displayP3Red = QColor::fromRgb(255, 0, 0, QColorSpace::DisplayP3);

    // 現在の色空間を取得
    qDebug() << "sRGB Red Color Space:" << srgbRed.colorSpace().name();

    // 別の色空間に変換
    // QColor convertedRed = srgbRed.toColorSpace(QColorSpace::DisplayP3);
    // qDebug() << "Converted Red Color Space:" << convertedRed.colorSpace().name();

    // 注: QColorSpaceは複雑なテーマであり、具体的な描画や表示はさらに詳細な設定が必要です。
    // この例は概念を示すためのものです。

    return 0; // QApplicationがイベントループに入らないため、すぐに終了
}

QColorはQtにおける色の基本的な「単位」ですが、その使い方や管理方法には様々な代替・関連技術があります。

  • 正確なカラーマネージメントや高度な色空間の扱いならQColorSpace(Qt 6以降)。
  • 図形の塗りつぶしや線の描画ならQBrushQPen(これらはQColorを内部で使う)。
  • 低レベルでのピクセル操作や古いAPIとの互換性ならQRgb型と関連の非メンバ関数。
  • ウィジェットの役割に応じた色の体系的な管理ならQPalette
  • GUIの見た目を手軽にカスタマイズするならQt Style Sheets (CSS)。