[PyQt] What am I doing wrong with QWidget?

Phil Thompson phil at riverbankcomputing.com
Tue Sep 22 23:12:40 BST 2009


On Sat, 19 Sep 2009 23:09:52 +0200, David Boddie <david at boddie.org.uk>
wrote:
> On Sat Sep 19 19:27:06 BST 2009, Kurt Schwarz wrote:
> 
>> I'm having problems displaying a widget as a child inside a window. The
>> code below should create a window that is 500 x 500 with a red box
inside
>> 400 x 400.
>>
>> If I replace self.ChildWidget = AppWidget( self ) with self.ChildWidget
=
>> QtGui.QWidget( self ) I get the desired result, what am I doing wrong
>> with
>> AppWidget( ) that would cause it not to display correctly?
> 
> I don't think you're doing anything wrong. I quickly rewrote the example
in
> C++ and verified that it works.
> 
> 
> #include <QtGui>
> 
> class AppWidget : public QWidget
> {
> public:
>     AppWidget(QWidget *parent = 0) : QWidget(parent) {}
> };
> 
> class AppWindow : public QMainWindow
> {
> public:
>     AppWindow() : QMainWindow() {
>         setGeometry( 30, 30, 500, 500 );
> 
>         ChildWidget = new AppWidget(this);
>         ChildWidget->setGeometry( 10, 10, 400, 400 );
>         ChildWidget->setStyleSheet( "background-color: #ff0000" );
>     }
> 
> private:
>     QWidget *ChildWidget;
> };
> 
> int main(int argc, char *argv[])
> {
>     QApplication app(argc, argv);
>     AppWindow MainWindow;
>     MainWindow.show( );
>     return app.exec( );
> }
> 
> 
> In your Python version, if you change the base class of AppWidget to
> QFrame,
> it works, so there's definitely something strange happening.

Except that the above isn't equivalent to the Python version...

I think this is a Qt bug...

What's happening is the WA_StyledBackground window attribute isn't being
set. In fact the workaround is to explicitly set it in
AppWidget.__init__()...

    self.setAttribute(QtCore.Qt.WA_StyledBackground)

The attribute should be set by QStyleSheetStyle::polish() but that function
includes a test for QWidget and a limited number of QWidget sub-classes
(including QFrame).  The problem is that the test for QWidget uses
QWidget's static meta-object. In PyQt that test fails because a new
QMetaObject has been created for AppWidget. The above code works, but only
because it doesn't include Q_OBJECT and hasn't been put through moc.

In Python, changing the super-class of AppWidget to QFrame works because
the test for QWidget sub-classes (like QFrame) is less strict - instead it
uses qobject_cast() which means that QFrame sub-classes (like AppWidget)
also pass the test.

In my view there is no need for the tests in the first place - everything
is a QWidget so just set the attribute unconditionaly.  That may have
strange effects on some QWidget sub-classes (I assume the test is there for
a reason) but that is preferable to being prevented from doing things that
would work without a problem.

Phil


More information about the PyQt mailing list