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 yfocusInEvent()
/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
}