Feuille de style Qt pour widget personnalisé

j'ai plusieurs widgets personnalisés dans mon projet actuel. Je souhaite appliquer des feuilles de style à eux et lorsque je le fais à L'intérieur de Qt Creator, il semble fonctionner. Cependant, lors de l'exécution du programme, aucune feuille de style n'est utilisée. Les feuilles de style des widgets Qt fonctionnent normalement.

quelqu'un aurait-il des conseils? voici quelques codes pertinents.

WidgetUnits.h

#ifndef WIDGETUNITS_H
#define WIDGETUNITS_H

#include <QList>

#include <QWidget>
#include <QPainter>

#include <Widgets/JECButton.h>

#include <Unit.h>
#include <Time.h>

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<Unit*>*>* units);
    Ui::WidgetUnits *ui;

    const int pictureWidth;                         // The width of the Unit pictures.
    const int pictureHeight;                        // The height of the Unit pictures.

    QList<QList<JECButton*>*> 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.rpc

#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 < buttonPictures.length(); ++a)
    {
        if (buttonPictures.at(a)->length() > maxNewQueue)
        {
            maxNewQueue = buttonPictures.at(a)->length();
        }
    }

    if (buttonPictures.length() > 0)
    {
        this->setGeometry(0, 0, buttonPictures.length() * 130,
                          maxNewQueue * (pictureWidth + 10) + 20);

        QList<JECButton*>* tickButtons = 0;
        for (int a = 0; a < buttonPictures.length(); ++a)
        {
            tickButtons = buttonPictures.at(a);
            for (int b = 0; b < tickButtons->length(); ++b)
            {
                tickButtons->at(b)->move(a * 130, b * (pictureHeight + 10));
            }
        }
    }
    update();
}

void WidgetUnits::checkNewQueue(const QList<QList<Unit *> *> *units)
{
    if (units != 0)
    {
        const Unit* currentUnit = 0;
        JECButton* currentButton = 0;
        for (int a = 0; a < units->length(); ++a)
        {
            buttonPictures.append(new QList<JECButton*>());

            for (int b = 0; b < units->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<JECButton*>());
    }
}

void WidgetUnits::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);
}

Toute aide sera appréciée.

le widget est visible - j'ai mis un tooltip qu'il m'a montré (sa juste la même couleur de la QScrollArea sa position assise).

Jec

28
demandé sur RAM 2011-09-02 00:48:00

5 réponses

j'ai eu un problème similaire et il a été résolu en utilisant le commentaire de jecjackal. Comme sjwarner dit, il serait beaucoup plus perceptible dans la forme d'une réponse. Donc je vais le fournir. Pour le bénéfice des futurs spectateurs. Encore une fois, ce n'est pas ma réponse! J'apprécie jecjackal pour ça!

comme il est dit dans la référence des feuilles de style de Qt, appliquer les styles CSS aux widgets personnalisés hérités de QWidget nécessite de réimplémenter paintEvent () de cette façon:

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

sans le faire votre les widgets personnalisés ne supporteront que les propriétés background, background-clip et background-origin.

Vous pouvez le lire ici:Qt feuilles de style de référence dans la section "Liste des Widgets Stylables" -> QWidget.

50
répondu Roman Kruglov 2017-02-09 15:24:39

il y a une réponse beaucoup plus facile que d'écrire la vôtre paintEvent: sous-classe QFrame au lieu de QWidget et il va travailler tout de suite:

class WidgetUnits : public QFrame
{
    Q_OBJECT
....
9
répondu Marco 2014-02-28 12:04:27

Pour être complet, le même problème est présent dans PyQt. Vous pouvez appliquer une feuille de style à un QWidget sous-classé en ajoutant du code similaire:

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)
5
répondu Pieter-Jan Busschaert 2013-07-10 14:35:53

j'ai eu le même problème avec pyside. Je poste ma solution juste pour l'exhaustivité. C'est presque comme dans PyQt comme Pieter-Jan Busschaert l'a proposé. la seule différence est que vous devez appeler init from au lieu de 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) 

Une autre chose que vous devez vous assurer que vous définissez votre widget personnalisé dans votre fichier css de la façon suivante:

FreeDockWidget{...}

et non, comme souvent recommandé

QDockWidget#FreeDockWidget{...}
3
répondu Stefan Reinhardt 2014-04-29 08:34:57

appel setAttribute(Qt::WA_StyledBackground, true) pour le widget personnalisé a fonctionné pour moi.

0
répondu mentalmushroom 2018-03-08 17:58:42