Criando um estilo personalizado para o KDE/Qt

Se você quiser criar um estilo personalizado para suas aplicações, o primeiro passo é escolher um dos estilos fornecidos junto com a biblioteca Qt para a partir dele criar seu estilo personalizado. Sua escolha dependerá de qual estilo mais de assemelha ao estilo que você quiser criar. A classe mais genérica que você pode usar como base é QCommonStyle (e não QStyle), já que o Qt requer que os estiloes sejam derivados de QCommonStyle.

Dependendo de qual partes  do estilo base você quer alterar, você precisa reimplementar as funções que desenham cada parte da interface.  para ilustrar isso, nós modificaremos a aparência da seta da spinbox, que é desenhada pela classe QWindowsStyle. A seta é um elemento primitivo que é desenhado pela função drawPrimitive(), então nós iremos reimplementar essa função. Nós precisaremos da seguinte declaração de classe:

class CustomStyle : public QWindowsStyle
 {
     Q_OBJECT

 public:
     CustomStyle()
     ~CustomStyle() {}

     void drawPrimitive(PrimitiveElement element, const QStyleOption *option,
                        QPainter *painter, const QWidget *widget) const;
 };

Para desenhar as setas para cima e para baixo, o QSpinBox usa os elementos PE_IndicatorSpinUp and PE_IndicatorSpinDown. Abaixo está a reimplementação da função que faz o novo desenho do elemento:

void CustomStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
                                 QPainter *painter, const QWidget *widget) const
 {
     if (element == PE_IndicatorSpinUp || element == PE_IndicatorSpinDown) {
         QPolygon points(3);
         int x = option->rect.x();
         int y = option->rect.y();
         int w = option->rect.width() / 2;
         int h = option->rect.height() / 2;
         x += (option->rect.width() - w) / 2;
         y += (option->rect.height() - h) / 2;

         if (element == PE_IndicatorSpinUp) {
             points[0] = QPoint(x, y + h);
             points[1] = QPoint(x + w, y + h);
             points[2] = QPoint(x + w / 2, y);
         } else { // PE_SpinBoxDown
             points[0] = QPoint(x, y);
             points[1] = QPoint(x + w, y);
             points[2] = QPoint(x + w / 2, y + h);
         }

         if (option->state & State_Enabled) {
             painter->setPen(option->palette.mid().color());
             painter->setBrush(option->palette.buttonText());
         } else {
             painter->setPen(option->palette.buttonText().color());
             painter->setBrush(option->palette.mid());
         }
         painter->drawPolygon(points);
     } else {
         QWindowsStyle::drawPrimitive(element, option, painter, widget);
     }
 }

Observe que nós não usamos o argumento widget, exceto para chamar a função QWindowStyle::drawPrimitive(). Como mencionado antes, a informação sobre o que será desenhado e como deve ser desenhado é especificado por um objeto QStyleOption, então não há necessidade de chamar p widget.

Se você precisar usar o argumento widget para obter informações adicionais, tome o cuidado de se garantir que o tipo correto está sendo usado. Por exemplo:

 QSpinBox *spinBox = qobject_cast<QSpinBox *>(widget);
     if (spinBox) {
     ...
     }

Quando for implementar um estilo personalizado, você não pode assumir que o widget é um QSpinBox somente pelo fato de que o valor do enum é PE_IndicatorSpinUp or PE_IndicatorSpinDown.

A documentação dos exemplos de Estilos cobrem esse tópico com mais detalhes.

Traduzido de http://doc.trolltech.com/4.4/qstyle.html#creating-a-custom-style