You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QColor::fromHsv生成颜色异常:多为黑色仅灰色符合预期的求助

Qt中QColor::fromHsv生成颜色异常(多为黑色)的解决方法

问题描述

我正在构建一个包含图形场景的窗口,场景内是堆叠的彩色矩形(后续将实现移动功能)。使用Qt::green这类预定义颜色为矩形上色时一切正常(参考scheibe.cpp第3行代码),但通过QColor::fromHsv创建的自定义颜色却无法正常工作——生成的颜色大多为黑色,仅灰度值符合预期。

相关代码

main.cpp

#include <QApplication>
#include "fensterHaupt.h"

int main (int argc, char *argv []) {
    QApplication app (argc, argv);
    FensterHaupt fh (18, &app);
    fh.show ();
    return app.exec ();
}

fensterHaupt.h

#ifndef FENSTERHAUPT_H
#define FENSTERHAUPT_H

#include <QStyleOptionGraphicsItem>
#include <QLayout>
#include <QList>
#include <QMainWindow>
#include <QPainter>
#include <QRectF>
#include <QWidget>
#include "scheibe.h"
#include "ui_fensterHaupt.h"

class FensterHaupt : public QMainWindow {
    Q_OBJECT

public :
    FensterHaupt (int scheibenzahl, QApplication *vorfahr = 0);
    Ui::FensterHaupt uiFensterHaupt;
    QVBoxLayout *layout;
    QGraphicsScene* szenenbild = new QGraphicsScene (this);
    int scheibenzahl = 18;
    QList <QColor> farbpalette;
    QColor farbeFestlegen (int scheibennr);
    void spielfeldFullen ();
};

#endif // FENSTERHAUPT_H

fensterHaupt.cpp

#include "fensterHaupt.h"
#include "ui_fensterHaupt.h"

FensterHaupt::FensterHaupt (int sz, QApplication *vorfahr) : scheibenzahl (sz) {
    uiFensterHaupt.setupUi (this);
    for (int h = 0; h <= 359; h += 60) {
        farbpalette.append (QColor::fromHsv (h, 0, 0) );
    }
    farbpalette.append (QColor (QColor::fromHsv (30, 0, 0) ) );
    spielfeldFullen ();
}

QColor FensterHaupt::farbeFestlegen (int scheibennr) {
    return farbpalette.at (scheibennr);
}

void FensterHaupt::spielfeldFullen () {
    for (int s = 0; s < scheibenzahl; s ++) {
        Scheibe* S = new Scheibe (s, farbeFestlegen (s), 20 * s, szenenbild);
        QWidget *widget = new QWidget;
        szenenbild->addItem (S);
        S->paint (new QPainter, new QStyleOptionGraphicsItem, nullptr);
    }
    uiFensterHaupt.spielfeld->setScene (szenenbild);
}

scheibe.h

#ifndef SCHEIBE_H
#define SCHEIBE_H

#include <QColor>
#include <QGraphicsItem>
#include <QPainter>

class Scheibe : public QGraphicsItem {
public :
    Scheibe (int scheibennr, QColor scheibenfarbe, int y, QGraphicsScene *vorfahr);
    QRectF boundingRect () const;
    void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr);
    int scheibennr = 0, x, y, breite = 120;
    const int hohe = 20;
    QColor farbe;
    QRectF scheibenbild;
    QGraphicsScene* szenenbild;
};

#endif // SCHEIBE_H

scheibe.cpp

#include "scheibe.h"

const std::vector <QColor> farben = {(Qt::red), (Qt::magenta), (Qt::yellow), (Qt::green), (Qt::blue), (Qt::cyan), (Qt::gray), (Qt::black)};

Scheibe::Scheibe (int snr, QColor scheibenfarbe, int positionY, QGraphicsScene *vorfahr) : scheibennr (snr), farbe (scheibenfarbe), y (positionY), szenenbild (vorfahr) {
    QRectF sb (20, y, 60, 20);
    scheibenbild = sb;
}

QRectF Scheibe::boundingRect () const {
    return scheibenbild;
}

void Scheibe::paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
    Q_UNUSED (option);
    Q_UNUSED (widget);
    painter->setBrush (farben [scheibennr]); // 这里用预定义颜色正常
    painter->setBrush (farbe); // 这里用自定义颜色异常
    painter->drawRect (boundingRect () );
}

fensterHaupt.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>FensterHaupt</class>
 <widget class="QMainWindow" name="FensterHaupt">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>480</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="rahmenAuen">
   <widget class="QGraphicsView" name="spielfeld">
    <property name="geometry">
     <rect>
      <x>0</x>
      <y>0</y>
      <width>790</width>
      <height>420</height>
     </rect>
    </property>
    <property name="minimumSize">
     <size>
      <width>20</width>
      <height>20</height>
     </size>
    </property>
    <property name="sizeAdjustPolicy">
     <enum>QAbstractScrollArea::AdjustToContents</enum>
    </property>
    <property name="alignment">
     <set>Qt::AlignBottom|Qt::AlignHCenter</set>
    </property>
   </widget>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

问题根源

  1. HSV参数错误:QColor::fromHsv(h, s, v)的三个参数分别是色相(H)、饱和度(S)、明度(V)。你当前设置的饱和度和明度都是0:

    • 饱和度为0时,颜色会退化为灰度色
    • 明度为0时,直接就是黑色
      这是自定义颜色大多为黑色的核心原因。
  2. 手动调用paint方法错误:在spielfeldFullen中手动调用S->paint(new QPainter, ...)完全错误——QGraphicsItem的paint方法由Qt图形框架自动调用,手动创建QPainter会导致资源泄漏,还可能干扰正常绘制流程。

  3. 索引越界风险:farbpalette仅包含7个颜色,但要创建18个Scheibe,调用farbpalette.at(scheibennr)会触发越界错误。

修复方案

1. 修正HSV颜色参数

将饱和度和明度调整为合理值(比如255,代表完全饱和、最高明度),修改fensterHaupt.cpp中的构造函数:

FensterHaupt::FensterHaupt (int sz, QApplication *vorfahr) : scheibenzahl (sz) {
    uiFensterHaupt.setupUi (this);
    for (int h = 0; h <= 359; h += 60) {
        // 修正饱和度(S)和明度(V)为255
        farbpalette.append(QColor::fromHsv(h, 255, 255));
    }
    farbpalette.append(QColor::fromHsv(30, 255, 255));
    spielfeldFullen ();
}

2. 删除错误的手动paint调用

在spielfeldFullen中删掉以下两行无用代码:

QWidget *widget = new QWidget;
S->paint (new QPainter, new QStyleOptionGraphicsItem, nullptr);

3. 处理索引越界问题

修改farbeFestlegen方法,使用取模运算循环获取调色板颜色:

QColor FensterHaupt::farbeFestlegen (int scheibennr) {
    // 取模避免索引越界
    return farbpalette.at(scheibennr % farbpalette.size());
}

4. 清理冗余代码

在scheibe.cpp的paint方法中,你先设置了farben[scheibennr]的画笔,又立刻用farbe覆盖,可以删掉第一行setBrush:

void Scheibe::paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
    Q_UNUSED (option);
    Q_UNUSED (widget);
    // 删除这行无用代码
    // painter->setBrush (farben [scheibennr]);
    painter->setBrush (farbe);
    painter->drawRect (boundingRect () );
}

效果验证

完成上述修改后,QColor::fromHsv生成的彩色会正常显示,矩形堆叠场景也能正确渲染,同时避免了资源泄漏和越界错误。

内容的提问来源于stack exchange,提问作者muggi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:52:02