如何使用QStyle.drawControl()渲染一个红色的推按钮?

8

使用以下代码,我尝试使用QStyle.drawControl()来呈现一个红色的推按钮:

#include <QtCore/QtCore>
#include <QtGui/QtGui>

class Widget : public QWidget
{
    virtual void paintEvent(QPaintEvent* event)
    {
        QStyleOptionButton opt;
        opt.palette = QPalette(Qt::red);
        opt.state = QStyle::State_Active | QStyle::State_Enabled;
        opt.rect = QRect(50, 25, 100, 50);
        QPainter painter(this);
        style()->drawControl(QStyle::CE_PushButton, &opt, &painter);
    }
};

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    Widget w;
    w.resize(200, 100);
    w.show();
    return app.exec();
}

然而我得到了以下结果:

enter image description here

如何使用QStyle.drawControl()渲染红色按钮?

我正在使用Qt 4.8.1和Windows XP上的Visual Studio 2010。


你在这个按钮上设置了一些文本吗?也许 "Qt::red" 正好是文本颜色、背景/边框颜色。 - Kamil Klimek
@Kamil Klimek:'QPalette::QPalette(Qt::GlobalColor button)' 的文档说明:“从按钮颜色构建调色板。其他颜色将根据此颜色自动计算。窗口也将是按钮颜色。”请参见http://qt-project.org/doc/qt-4.8/qpalette.html#QPalette-3。 - Johan Råde
@Kamil Klimek:我也尝试了几种构建调色板的方法,但似乎无论使用什么调色板,按钮的颜色都是相同的。 - Johan Råde
如果您明确设置应用程序样式,它是否有效?也就是说,如果您调用app.setStyle("windows"),您会得到不同的结果吗? - RA.
@RA:是的,那么它就可以工作了。正如alexisdm答案中解释的链接所述,该问题特定于Windows XP、Windows Vista和Mac样式。 - Johan Råde
2个回答

10

这些按钮由本地样式引擎绘制,因此调色板可能根本不会被使用(请参见FAQ中有关该问题的解释)。

您可以使用一个实际的按钮,并将样式表作为最后一个参数传递给自己的按钮样式drawControl函数。

class Widget : public QWidget
{
  // To allow the automatic deletion without parenting it
  QScopedPointer<QPushButton> button;
public:
    Widget() : button(new QPushButton) {
      button->setStyleSheet("background-color: red");
    }
    virtual void paintEvent(QPaintEvent* event)
    {
        QStyleOptionButton opt;
        opt.state = QStyle::State_Active | QStyle::State_Enabled;
        opt.rect = QRect(50, 25, 100, 50);
        QPainter painter(this);
        button->style()->drawControl(QStyle::CE_PushButton, &opt, &painter, 
                                     button.data());
    }
};

但你将失去本地风格,所以你必须模拟它(bali182的回答对于这部分可能有用)。

或者您可以使用具有着色效果的相同按钮,并调用其render()函数进行绘制:

Colorized Button

class Widget : public QWidget {
    QScopedPointer<QPushButton> button;
public:
    Widget() : button(new QPushButton) {
        QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect(button.data());
        effect->setColor(Qt::red);
        button->setGraphicsEffect(effect);
    }
    virtual void paintEvent(QPaintEvent* event) {
        button->setFixedSize(100, 50);
        button->render(this, QPoint(50, 25));
    }
};

3
你正在尝试做的事情似乎过于复杂。如果你只想要一个红色按钮,为什么不使用QPushButton的setStyleSheet()方法呢?它接受一个QString参数,你可以像CSS一样定义你的按钮。在这里我为你创建了一个类似XP UI按钮的红色按钮:
QPushButton 
{ 
    background: qlineargradient(x1:0,y1:0,x2:0,y2:1, stop:0 #f4a3a3,stop: 1 #cc1212);
    border-width: 1px; 
    border-color: #d91414; 
    border-style: solid; 
    padding: 5px; 
    padding-left:10px; 
    padding-right:10px; 
    border-radius: 3px; 
    color:#000;
}

QPushButton:hover
{
    border-color: #e36666;
} 

QPushButton:pressed 
{
    background:qlineargradient(x1:0,y1:0,x2:0,y2:1,stop: 0 #de8383, stop: 1 #ad0C0C); 
    border-color: #d91414;
}

现在,您只需要将上述代码作为字符串传递给按钮的setStyleSheet()方法即可。如果您想创建一个默认为红色的按钮部件,则可以扩展QPushButton类,在构造函数中创建一个静态的QString字段,并将该按钮设置为样式表。
更多关于样式表的易于理解的示例: 样式表示例

我通过将alexisdm的答案与您的样式表结合起来解决了这个问题。 - Johan Råde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接