Доброго времени суток. Сразу к делу - есть
два стула спойлер, то есть мой виджет, унаследованный от класса QWidget. Этот спойлер содержит в себе заголовок, состоящий из двух QLabel, а также сам контент, скрывающийся под спойлером, то есть ещё один виджет, находящийся под заголовком и скрывающийся/появляющийся по клику на любой из лейблов заголовка. Вобщем, нужно применить стили CSS к заголовку и к самому спойлеру,
но не к виджету-контенту.
Код:
labelex.h
C++ (Qt)
#ifndef LABELEX_H
#define LABELEX_H
#include "common.h"
class LabelEx : public QLabel {
Q_OBJECT
public:
LabelEx(QLabel *pwgt) :
QLabel(pwgt)
{
}
protected:
virtual void mousePressEvent(QMouseEvent *pe)
{
if (pe->button() == Qt::LeftButton)
emit clicked();
}
signals:
void clicked();
};
#endif
header.h
C++ (Qt)
#ifndef HEADER_H
#define HEADER_H
#include "labelex.h"
class Header : public QWidget {
Q_OBJECT
private:
LabelEx *pBtn;
bool expanded;
void refresh()
{
pBtn->setPixmap(QPixmap(expanded ? ":/img/collapse.png" : ":/img/expand.png"));
}
public:
Header(QWidget *pwgt, const QString& Title) : QWidget(pwgt)
{
pBtn = new LabelEx(0);
expanded = false;
pBtn->setPixmap(QPixmap(":/img/expand.png"));
LabelEx *pTitle = new LabelEx(0);
QFont font("Impact");
font.setPointSize(9);
pTitle->setFont(font);
pTitle->setText(Title);
pBtn->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
pTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
setStyleSheet("border-width: 1px; border-color: #565656; border-style: solid; background-color: #E6E6E6; border-radius: 0px;");
QHBoxLayout *hbx = new QHBoxLayout;
hbx->setSpacing(0);
hbx->addWidget(pBtn);
hbx->addWidget(pTitle);
setLayout(hbx);
connect(pBtn, SIGNAL(clicked()), SLOT(click()));
connect(pTitle, SIGNAL(clicked()), SLOT(click()));
}
~Header()
{
delete layout();
}
bool isExpanded()
{
return expanded;
}
void expand()
{
expanded = true;
refresh();
}
void collapse()
{
expanded = false;
refresh();
}
private slots:
void click()
{
expanded = !expanded;
refresh();
emit clicked();
}
signals:
void clicked();
};
#endif
spoiler.h
C++ (Qt)
#ifndef SPOILER_H
#define SPOILER_H
#include "header.h"
class Spoiler : public QWidget {
Q_OBJECT
private:
QWidget *pWidget;
Header *pHeader;
bool expanded;
public:
Spoiler(QWidget *pwgt, const QString&, QWidget*);
private slots:
void headerClicked();
public slots:
void expand();
void collapse();
};
#endif
spoiler.cpp
C++ (Qt)
#include "spoiler.h"
Spoiler::Spoiler(QWidget *pwgt, const QString &Title, QWidget *Widget) : QWidget(pwgt), pWidget(Widget)
{
if (!pWidget)
Error(QString("Не проинициализирован виджет спойлера %1").arg(Title));
pHeader = new Header(0, Title);
QVBoxLayout *vbx = new QVBoxLayout;
vbx->setAlignment(Qt::AlignTop);
vbx->setSizeConstraint(QLayout::SetMinimumSize);
setStyleSheet("Spoiler { border-width: 1px; border-style: solid; border-color: #F47300; border-radius: 5px; background-color: #A0A0A0; }");
setContentsMargins(5, 5, 5, 1);
pWidget->setVisible(false);
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
vbx->setSpacing(0);
vbx->addWidget(pHeader);
vbx->addWidget(pWidget);
setLayout(vbx);
connect(pHeader, SIGNAL(clicked()), SLOT(headerClicked()));
}
void Spoiler::headerClicked()
{
pWidget->setVisible(pHeader->isExpanded());
}
void Spoiler::collapse()
{
pHeader->collapse();
pWidget->setVisible(false);
}
void Spoiler::expand()
{
pHeader->expand();
pWidget->setVisible(true);
}
И да, немного, конечно, извращённо, но не карайте строго.
Стиль в конструкторе спойлера вообще не применяется ни к чему.
Если я напишу в конструкторе спойлера
C++ (Qt)
setStyleSheet("border-width: 1px; border-style: solid; border-color: #F47300; border-radius: 5px; background-color: #A0A0A0;");
, то применится это только к виджету-контенту. А мне надо, чтобы применилось только к самому спойлеру, но его виджеты были незатронуты, за исключением, если у них уже будут применены свои стили.
Пробовал ещё так
C++ (Qt)
setObjectName("spoiler");
setStyleSheet("QWidget#spoiler { border-width: 1px; border-style: solid; border-color: #F47300; border-radius: 5px; background-color: #A0A0A0; }");
, но эффект остался прежним - ничего не применилось.
Ну и напоследок делаю так
C++ (Qt)
setStyleSheet(".QWidget { border-width: 1px; border-style: solid; border-color: #F47300; border-radius: 5px; background-color: #A0A0A0; }");
и тоже эффекта ноль.
Как справиться с этой проблемой?
Сам класс QWidget не поддерживает стили, его метод paintEvent просто ничего не делает, хотя все следующие потомки уже умеют это делать.
Можно (и наверное стоит) наследовать Spoiler от одного из потомков QWidget, например QFrame или реализовать рисование самому:
C++ (Qt)
void Spoiler::paintEvent(QPaintEvent *)
{
QStyleOption opt;
opt.init( this );
QPainter p( this );
style()->drawPrimitive( QStyle::PE_Widget, &opt, &p, this );
}
Есть подозрения, что у виджета нельзя задавать бордюры. Попробуй ради эксперимента управлять заливкой виджета, чтобы убедиться в том стили вообще применяются.