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>
问题根源
HSV参数错误:
QColor::fromHsv(h, s, v)的三个参数分别是色相(H)、饱和度(S)、明度(V)。你当前设置的饱和度和明度都是0:- 饱和度为0时,颜色会退化为灰度色
- 明度为0时,直接就是黑色
这是自定义颜色大多为黑色的核心原因。
手动调用paint方法错误:在
spielfeldFullen中手动调用S->paint(new QPainter, ...)完全错误——QGraphicsItem的paint方法由Qt图形框架自动调用,手动创建QPainter会导致资源泄漏,还可能干扰正常绘制流程。索引越界风险:
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

