Буквально вчера подобное делал, только без QSS:
C++ (Qt)
bool MyDialog::eventFilter( QObject * o, QEvent * e )
{
if(e->type() == QEvent::Paint)
{
if(o->property("required").toBool())
{
QWidget * w = dynamic_cast<QWidget *>(o);
if(w && w->parentWidget()) {
w->parentWidget()->update(QRect(w->pos(), w->size()).adjusted(-3, -3, 3, 3)); // Update parent widget
}
} else {
QPainter p(qobject_cast<QWidget *>(o));
QPen pen_;
pen_.setWidth(2);
pen_.setColor(QColor(66, 126, 255)); // Set border color
p.setPen(pen_);
p.setRenderHint(QPainter::Antialiasing);
bool ready_ = true;
foreach(QObject * obj, o->children())
{
if(obj->property("required").toBool()) // Check widget
{
if(
(obj->inherits("QLineEdit") && obj->property("text").toString().isEmpty()) || // Check empty text field
(obj->inherits("QComboBox") && obj->property("currentText").toString().isEmpty()) || // Check empty combo box
(obj->inherits("QListView") && ((QListView *)qobject_cast<QListView *>(obj))->model()->rowCount() == 0 ) // Check empty list
)
{
ready_ &= false;
QWidget * w = dynamic_cast<QWidget *>(obj);
if(w)
{
QRect r(w->pos(), w->size());
p.drawRect(r.adjusted(-1, -1, 1, 1));
}
}
}
}
sendButton_->setEnabled(ready_); // Enable send button
}
}
return QDialog::eventFilter(o, e);
}
Собственно использование:
C++ (Qt)
frame->installEventFilter(this); // Container of fields
orgName_->setProperty("required", true); // Mark widget
orgName_->installEventFilter(this);
Все получается довольно мило =)
Можно развить код, и в виде динамического параметра присвоить указатель на некоторый валидатор, тогда можно для каждого поля выполнить более гибкую проверку, так же и для более сложных виджетов (QTabWidget и т.п.).