Qt Stylesheet per widget personalizzati

Ho diversi widget personalizzati nel mio progetto attuale. Desidero applicare loro fogli di stile e quando lo faccio all’interno di Qt Creator, sembra funzionare. Tuttavia, quando si esegue il programma, non viene utilizzato alcun foglio di stile. I fogli di stile per i widget Qt funzionano normalmente.

Qualcuno ha qualche consiglio? ecco un codice rilevante.

WidgetUnits.h

#ifndef WIDGETUNITS_H #define WIDGETUNITS_H #include  #include  #include  #include  #include  #include  namespace Ui { class WidgetUnits; } class WidgetUnits : public QWidget { Q_OBJECT public: explicit WidgetUnits(QWidget *parent = 0); ~WidgetUnits(); void setNumTimes(const int& numTimes); public slots: void updatePictures(const Time* time); protected: void paintEvent(QPaintEvent *event); private: void checkNewQueue(const QList<QList*>* units); Ui::WidgetUnits *ui; const int pictureWidth; // The width of the Unit pictures. const int pictureHeight; // The height of the Unit pictures. QList<QList*> buttonPictures; // The Units' pictures. The outer QList stores the QList of pictures for a given tick. // The inner QList stores the JECButtons for the specific tick. }; 

WidgetUnits.cpp

 #include "WidgetUnits.h" #include "ui_WidgetUnits.h" WidgetUnits::WidgetUnits(QWidget *parent): QWidget(parent), ui(new Ui::WidgetUnits), pictureWidth(36), pictureHeight(36) { ui->setupUi(this); } WidgetUnits::~WidgetUnits() { delete ui; } void WidgetUnits::updatePictures(const Time *time) { // Only showing units that started to get built this turn. checkNewQueue(time->getUnits()); checkNewQueue(time->getBuildings()); checkNewQueue(time->getUpgrades()); // Updating the position of the remaining pictures (after some were removed). // Checking the maximum number of Units made in one tick. int maxNewQueue = 0; for (int a = 0; a length() > maxNewQueue) { maxNewQueue = buttonPictures.at(a)->length(); } } if (buttonPictures.length() > 0) { this->setGeometry(0, 0, buttonPictures.length() * 130, maxNewQueue * (pictureWidth + 10) + 20); QList* tickButtons = 0; for (int a = 0; a < buttonPictures.length(); ++a) { tickButtons = buttonPictures.at(a); for (int b = 0; b length(); ++b) { tickButtons->at(b)->move(a * 130, b * (pictureHeight + 10)); } } } update(); } void WidgetUnits::checkNewQueue(const QList<QList *> *units) { if (units != 0) { const Unit* currentUnit = 0; JECButton* currentButton = 0; for (int a = 0; a length(); ++a) { buttonPictures.append(new QList()); for (int b = 0; b at(a)->length(); ++b) { currentUnit = units->at(a)->at(b); // Verifying that there is an item in the queue and the queue action was started this turn. if (currentUnit->getQueue() != 0 && currentUnit->getAction()->getTimeStart() == currentUnit->getAction()->getTimeCurrent() && (currentUnit->getAction()->getType() == Action::BUILD || currentUnit->getAction()->getType() == Action::TRAIN || currentUnit->getAction()->getType() == Action::UPGRADE)) { buttonPictures.last()->append(new JECButton(this)); currentButton = buttonPictures.last()->last(); QImage* image = new QImage(currentUnit->getQueue()->getUnitBase()->getImage().scaled(pictureWidth, pictureHeight)); currentButton->setImage(*image); currentButton->setGeometry(0, 0, currentButton->getImage().width(), currentButton->getImage().height()); currentButton->setColorHover(QColor(0, 0, 225)); currentButton->setColorPressed(QColor(120, 120, 120)); currentButton->setImageOwner(true); currentButton->setVisible(true); } } } } } void WidgetUnits::setNumTimes(const int &numTimes) { // Appending new button lists for added ticks. for (int a = buttonPictures.length(); a < numTimes; ++a) { buttonPictures.append(new QList()); } } void WidgetUnits::paintEvent(QPaintEvent *event) { QWidget::paintEvent(event); } 

Qualsiasi aiuto sarà apprezzato.

Il widget è visibile- ho impostato un suggerimento che mi ha mostrato (è proprio lo stesso colore di QScrollArea cui è seduto).

Jec

Ho avuto un problema simile ed è stato risolto utilizzando il commento di jecjackal. Come ha detto sjwarner, sarebbe molto più evidente nella forma di una risposta. Quindi lo fornirò. Per il beneficio di eventuali futuri spettatori. Ancora una volta, non è la mia risposta! Apprezzo il jecjackal per questo!

Come si dice nel riferimento ai fogli di stile di Qt, l’applicazione degli stili CSS ai widget personalizzati ereditati da QWidget richiede il reimplementamento di paintEvent () in questo modo:

  void CustomWidget::paintEvent(QPaintEvent *) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } 

Senza farlo, i tuoi widget personalizzati supporteranno solo le proprietà background, background-clip e background-origin.

Puoi leggerlo qui: Qt Stylesheets reference nella sezione “Elenco di Stylable Widgets” -> QWidget.

C’è una risposta molto più semplice che scrivere il tuo paintEvent : sottoclass QFrame invece di QWidget e funzionerà subito:

 class WidgetUnits : public QFrame { Q_OBJECT .... 

Per completezza, lo stesso problema è presente in PyQt. Puoi applicare un foglio di stile a QWidget sottoclassata aggiungendo un codice simile:

 def paintEvent(self, pe): opt = QtGui.QStyleOption() opt.init(self) p = QtGui.QPainter(self) s = self.style() s.drawPrimitive(QtGui.QStyle.PE_Widget, opt, p, self) 

Ho avuto lo stesso problema con campagna. Pubblichiamo la mia soluzione solo per completezza. È quasi come in PyQt, come proposto da Pieter-Jan Busschaert. l’unica differenza è che devi chiamare initFrom invece di init

 def paintEvent(self, evt): super(FreeDockWidget,self).paintEvent(evt) opt = QtGui.QStyleOption() opt.initFrom(self) p = QtGui.QPainter(self) s = self.style() s.drawPrimitive(QtGui.QStyle.PE_Widget, opt, p, self) 

Un’altra cosa che devi accertare è che tu definisca il tuo widget personalizzato nel tuo file css nel seguente modo:

 FreeDockWidget{...} 

e non come spesso raccomandato

 QDockWidget#FreeDockWidget{...} 

Chiamare setAttribute(Qt::WA_StyledBackground, true) per il widget personalizzato ha funzionato per me.