widgets personalizar estilos qt qt4 focus qwidget

qt - personalizar - ¿Cómo cambiar el fondo de un widget padre cuando un widget secundario tiene foco?



personalizar widgets wordpress (2)

Me gustaría destacar un QFrame, si uno de sus widgets secundarios tiene foco (para que los usuarios sepan dónde buscar el cursor ;-)

usando algo a lo largo

ui->frame->setFocusPolicy(Qt::StrongFocus); ui->frame->setStyleSheet("QFrame:focus {background-color: #FFFFCC;}");

resalta QFrame cuando hago clic en él, pero pierde su enfoque una vez que se selecciona uno de sus widgets secundarios.

Posibles enfoques:

  • Podría connect() QApplication::focusChanged(old,now) y verificar cada nuevo objeto si es un elemento secundario de QFrame, pero esto se complica.

  • También podría focusInEvent() una subclase de cada widget hijo y focusInEvent() / focusOutEvent() y reaccionar sobre eso, pero con muchos widgets diferentes, esto también es mucho trabajo.

¿Hay una solución más elegante?


Bueno, puedes extender QFrame para que escuche el cambio de enfoque de sus widgets para niños. O también puede instalar un filtro de eventos en widgets de niños para capturar QFocusEvent .

Aquí hay un ejemplo:

MyFrame.h

#ifndef MYFRAME_H #define MYFRAME_H #include <QFrame> class MyFrame : public QFrame { Q_OBJECT public: explicit MyFrame(QWidget* parent = 0, Qt::WindowFlags f = 0); void hookChildrenWidgetsFocus(); protected: bool eventFilter(QObject *object, QEvent *event); private: QString m_originalStyleSheet; }; #endif // MYFRAME_H

MyFrame.cpp

#include <QEvent> #include "MyFrame.h" MyFrame::MyFrame(QWidget *parent, Qt::WindowFlags f) : QFrame(parent, f) { m_originalStyleSheet = styleSheet(); } void MyFrame::hookChildrenWidgetsFocus() { foreach (QObject *child, children()) { if (child->isWidgetType()) { child->installEventFilter(this); } } } bool MyFrame::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::FocusIn) { setStyleSheet("background-color: #FFFFCC;"); } else if (event->type() == QEvent::FocusOut) { setStyleSheet(m_originalStyleSheet); } return QObject::eventFilter(object, event); }

MainWindow.cpp

#include <QHBoxLayout> #include <QVBoxLayout> #include <QLineEdit> #include "MyFrame.h" #include "mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle(tr("Test")); MyFrame *frame1 = new MyFrame(this); frame1->setLayout(new QVBoxLayout()); frame1->layout()->addWidget(new QLineEdit()); frame1->layout()->addWidget(new QLineEdit()); frame1->layout()->addWidget(new QLineEdit()); frame1->hookChildrenWidgetsFocus(); MyFrame *frame2 = new MyFrame(this); frame2->setLayout(new QVBoxLayout()); frame2->layout()->addWidget(new QLineEdit()); frame2->layout()->addWidget(new QLineEdit()); frame2->layout()->addWidget(new QLineEdit()); frame2->hookChildrenWidgetsFocus(); QHBoxLayout *centralLayout = new QHBoxLayout(); centralLayout->addWidget(frame1); centralLayout->addWidget(frame2); QWidget *centralWidget = new QWidget(); centralWidget->setLayout(centralLayout); setCentralWidget(centralWidget); }


Primero, cree una subclase simple de QFrame que eventFilter(QObject*, QEvent*) la función virtual eventFilter(QObject*, QEvent*) :

class MyFrame : public QFrame { Q_OBJECT public: MyFrame(QWidget *parent = 0, Qt::WindowFlags f = 0); ~MyFrame(); virtual bool eventFilter(QObject *watched, QEvent *event); };

Use MyFrame lugar de QFrame para contener sus widgets. Luego, en algún lugar de su código donde crea los widgets contenidos en MyFrame , instale un filtro de eventos en esos widgets:

// ... m_myFrame = new MyFrame(parentWidget); QVBoxLayout *layout = new QVBoxLayout(myFrame); m_button = new QPushButton("Widget 1", myFrame); layout->addWidget(m_button); m_button->installEventFilter(myFrame); //...

En ese momento, se MyFrame::eventFilter() antes de que se entregue cualquier evento al widget, lo que le permitirá actuar sobre él antes de que el widget lo sepa. En MyFrame::eventFilter() , devuelva true si desea filtrar el evento (es decir, no desea que el widget procese el evento), o devuelva false caso contrario.

bool MyFrame::eventFilter(QObject *watched, QEvent *event) { if (watched == m_button) { // An event occured on m_button switch (event -> type()) { case QEvent::FocusIn: // Change the stylesheet of the frame break; case QEvent::FocusOut: // Change the stylesheet back break; default: break; } } return false; // We always want the event to propagate, so always return false }