Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Unexpected behavior on QWidget while the event filtering



  • Just i've tested the following codes on QPushButton and on QWidget and i've encountered with different behaviors. But why?

    MainWindow::MainWindow(QWidget *parent) 
            : QMainWindow(parent)
            , ui(new Ui::MainWindow)
    {
    	ui->setupUi(this);
    	ui->widget->setStyleSheet("background:blue;");
    	ui->pushButton->setStyleSheet("background:blue;");
    	ui->widget->installEventFilter(this);
    	ui->pushButton->installEventFilter(this);
    
            ...
    }
    
    bool MainWindow::eventFilter(QObject* watched, QEvent* event)
    {
    	if (watched==ui->pushButton && event->type()==QEvent::Paint)
    	{
    		// Do nothing
    		return true;
    	}
    	else if (watched==ui->widget && event->type()==QEvent::Paint)
    	{
    		// Do nothing
    		return true;
    	}
    	else
    		return QMainWindow::eventFilter(watched, event);
    }
    

    Then, the pushButton has disappeared as normally, because i've masked its paintEvent with eventFilter. But the widget has painted to blue. Why widget hasn't disappeared.



  • Very interesting question.

    Because you are using stylesheets you have to filter QEvent::Polish too.

    else if (watched==widget && event->type()==QEvent::Paint || event->type()==QEvent::Polish)
    

    Alternativ you can set QPalette instead of stylesheets.

    QPalette p = widget->palette();
    p.setBrush(QPalette::All,QPalette::Background,Qt::blue);
    widget->setPalette(p);
    

    Thats the solution. But i cannot explain why the widget is painted blue without filtering the Polish event. Would be interesting for me too.


  • Moderators

    @MrKozmon
    The paintEvent() handler paints most of the parts of a widget.
    But there is stuff (like the background) which is painted by Qt outside the paintEvent() handler.
    I think this is done in QWidgetPrivate::drawWidget(), which calls paintBackground().
    IIRC drawWidget() is called by the backingstore.

    The autoFillBackground property, WA_StyledBackground attribute, WA_OpaquePaintEvent attribute and WA_NoSystemBackground attribute should influence this.



  • @euchkatzl First, as i can see, QWidget not even have any member function starts with "polish", so, there is no polishEvent for QWidget.
    QWidget All Members List

    On the other hand, even with QPalette, the result is same, pushButton disappeared, widget not.


  • Moderators

    @MrKozmon
    not all events have an own event handler method. These are just here for convenience purposes to help keep the code clean.

    All events go through the widgets standard event() handler, whcih then forwards it to the specific event handlers if available.


  • Qt Champions 2017

    @MrKozmon
    Here's a pretty extensive list of the types of events passed around. As you can see most of those have no dedicated handler functions (just as @raven-worx pointed out).



  • You're right and thanks for your answers. I've solved the problem with changing QEvent::Paint with QEvent::Polish. Then, as normally, QWidget disappeared.

    else if (watched==ui->widget && event->type()==QEvent::Polish)
    {
        // Do nothing
        return true;
    }
    

    Because as @euchkatzl pointed out, sytleSheets handled in Polish event for QWidget. But for QPushButton this not work. For QPushButton, styleSheets handled in just Paint event, not in Polish event. So the following not work on QPushButton:

    if (watched==ui->pushButton && event->type()==QEvent::Polish)
    {
    	// Do nothing
    	return true;
    } //And pushButton painted to blue as abnormally.
    

    But what's the difference between this two widgets. Whereas QPushButton derivered from QWidget, right. And the second question is that, when i set a Palette to widget, i can't mask the painting event anymore in both of Polish and Paint events filter. So this is not work anymore:

    else if (watched==ui->widget && (event->type()==QEvent::Polish || event->type()==QEvent::Paint))
    {
    	// I can't catch the painting anymore
    	return true;
    }
    

    Where the painting actually happened in when i used pallets. And why every painting events just not happening only on paintEvent. How can i know all the different paint handlers in different situations. Why it's not just paintEvent function. Isn't that a worse programming model, and also i couldn't even found a proper explanation(documentation) for this, "Where the painting actually happening outside paintEvent for different situations."

    Anyway, thanks everybody.


Log in to reply