2011-09-01 107 views
24

我在當前項目中有幾個自定義小部件。我希望將樣式表應用於它們,當我在Qt Creator中使用樣式表時,它似乎可行。但是,在執行該程序時,不使用樣式表。 Qt窗口小部件的樣式表工作正常。用於自定義小部件的Qt樣式表

有沒有人有任何建議?這裏是一些相關的代碼。

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.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 < 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); 
} 

任何幫助將不勝感激。

這個小部件是可見的 - 我設置了一個工具提示,它顯示了我(它只是坐在它的QScrollArea相同的顏色)。

JEC

+0

你能展示相應的樣式表嗎? – alexisdm

+0

style sheet = background:rgb(170,0,255); \ nborder:2px純黑色; – jecjackal

+5

搜索了幾個小時後,我發現了這個http://developer.qt.nokia.com/forums/viewthread/7340該頁面引用的代碼是樣式表工作所必需的。 – jecjackal

回答

45

我有一個類似的問題,它是使用jecjackal的評論得到解決。正如sjwarner所說,答案的形式會更加明顯。所以我會提供它。爲了未來觀衆的利益。再次,這不是我的答案!感謝它的jecjackal!

因爲它在Qt的樣式表引用說,應用CSS樣式從QWidget的繼承自定義部件需要以這種方式重新實現的paintEvent():

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

沒有做你的自定義部件將僅支持後臺,背景剪輯和背景源屬性。

你可以在這裏閱讀:Qt Stylesheets reference在「Stylable Widgets列表」 - > QWidget部分。

4

爲了完整,PyQt中存在同樣的問題。

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) 
8

有一個答案不是寫自己的paintEvent容易得多:子類QFrame而不是QWidget,它會工作的時候了:

class WidgetUnits : public QFrame 
{ 
    Q_OBJECT 
.... 
可以通過添加類似的代碼應用樣式表到子類的QWidget
+1

我發現這是一個解決問題的少得多幹擾的方式。 它很簡單,只需爲每個自定義小部件查找/替換一行,並通過在默認構造函數中將QWidget(父)替換爲QFrame(父),將其轉換爲cpp文件計數器部分。 – Yattabyte

3

我和pyside有同樣的問題。我只是爲了完整而發佈我的解決方案。 就像Pieter-Jan Busschaert提出的PyQt一樣。 唯一的區別是,你需要調用,而不是初始化initFrom

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) 

一個你需要確保另一件事是,你在你的CSS文件中定義您的自定義插件的方式如下:

​​

和不像經常推薦的那樣

QDockWidget#FreeDockWidget{...} 
0

調用setAttribute(Qt::WA_StyledBackground, true)爲自定義小部件爲我工作。

相關問題