[PyQt] QGLWidget c++ widget works, SIP binding doesn't
Josh Knox
jknox at irobot.com
Wed Apr 28 20:13:02 BST 2010
Josh Knox wrote:
> Hi All,
>
> I've got a simple custom QGLWidget that works fine when loaded from
> c++. (basically the Sierpinski demo)
>
> I've built a SIP binding against it, that I can load from python but
> it only ever displays a black area and it appears that the event loop
> never starts.
>
> My SIP file is trivial:
>
> %Import QtCore/QtCoremod.sip
> %Import QtGui/QtGuimod.sip
>
> %Import QtOpenGL/QtOpenGLmod.sip
> %Module MyGLTest 0
>
>
> class MyGLWidget : QGLWidget
> {
> %TypeHeaderCode
> #include "../MyGLTest/include/QtGLTest.hpp"
> #include <QGLWidget>
> %End
>
> public:
> MyGLWidget(QWidget* parent /TransferThis/ = 0, const
> QGLWidget*
> shareWidget = 0, Qt::WindowFlags f = 0);
>
> };
>
> My Python script to show it is also trivial (essentially equivalent to
> the C++ code to do the same):
>
> import sys
> from PyQt4 import QtGui
> from MyGLTest import MyGLWidget
>
> if __name__ == "__main__":
>
> app = QtGui.QApplication(sys.argv)
>
> # test the simple GL widget
> myGLWidget = MyGLWidget()
> myGLWidget.resize(400, 350)
> myGLWidget.setWindowTitle('MyGLWidget')
> myGLWidget.show()
>
> app.exec_()
>
>
> This just launches a Qt window with an all black widget area.
>
> So, given that the C++ widget works, what could I be missing that's
> prevent the SIP binding from running properly?
>
> I'm still new at this, so any ideas appreciated!
>
>
> Thanks,
>
> Josh
> _______________________________________________
> PyQt mailing list PyQt at riverbankcomputing.com
> http://www.riverbankcomputing.com/mailman/listinfo/pyqt
Hmm, after lots of researching and building SIP bindings for various
widgets I've discovered some strange behavior.
It appears that for any QWidget class I make in C++, when loaded from
python via SIP bindings, the top-level/parent widget does not receive
any events. If I place children on a container QWidget in another C++
class and make bindings for that, then the widget does show up and work
properly.
If, in Python, I create a Qwidget and then place my custom widget on it,
it does not work; again receives no events.
I've reproduced this behavior with multiple custom widgets that I have
created. The code below demonstrates this problem.
The ColorSlider class is my widget. It just paints on the QWidget directly.
ColorSliderX is a widget that contains a ColorSlider.
When created in python, ColorSlider does not update or receive events.
When created via ColorSliderX, the child ColorSlider works fine.
I'm still kinda new at this so I might be missing something really
obvious, but I have no idea what. My workaround by nsting the widget in
the C++ implementation will get me working for now but it seems really
wrong to have to do this.
Any ideas what I'm missing?
Thanks,
Josh
============= HEADER =============
#ifndef QTPY_H
#define QTPY_H
#include <QtGui/QtGui>
#include <QtGui/QPaintEvent>
#include <QtGui/QResizeEvent>
#include <QtGui/QWheelEvent>
#include <QtGui/QWidget>
// colorful slider widget test class
class ColorSlider : public QWidget
{
Q_OBJECT
public:
ColorSlider(QWidget *parent=0);
virtual ~ColorSlider();
public:
QSize sizeHint() const { return QSize(100,300); }
QSize minimumSizeHint() const { return sizeHint(); }
public slots:
void setValue(int value);
signals:
void valueChanged(int value);
protected:
virtual void paintEvent(QPaintEvent* event);
virtual void resizeEvent(QResizeEvent* event);
virtual void wheelEvent(QWheelEvent *event);
private:
int m_temp;
QTransform m_xform;
bool m_mdrag;
};
/* This class is a workaround to get the ColorSlider to show up with
PyQt. */
class ColorSliderX : public QWidget
{
Q_OBJECT
public:
ColorSliderX(QWidget *parent=0);
virtual ~ColorSliderX();
// The child widget
ColorSlider *slider;
};
#endif // QTPY_H
============= CPP =============
/* ColorSlider & ColorSliderX implementation.
#include "qtpy.h"
#include <iostream>
ColorSlider::ColorSlider(QWidget *parent)
: QWidget(parent),
m_temp(50),
m_mdrag(false)
{
std::cerr << "ColorSlider::ColorSlider()" << std::endl;
show();
}
ColorSlider::~ColorSlider()
{
std::cerr << "ColorSlider::~ColorSlider()" << std::endl;
}
void ColorSlider::setValue(int value)
{
std::cerr << "ColorSlider::setValue(" << value << ")" << std::endl;
if (value != m_temp) {
if (value < 0)
m_temp = 0;
else if (value > 100)
m_temp = 100;
else
m_temp = value;
emit valueChanged(m_temp);
update();
}
}
void ColorSlider::paintEvent(QPaintEvent* event)
{
std::cerr << "ColorSlider::paintEvent()" << std::endl;
QColor color(0,255,0);
if (m_temp > 50) {
color.setRedF((m_temp - 50)/50.0);
color.setGreenF((100 - m_temp)/50.0);
}
else if (m_temp < 50) {
color.setGreenF(m_temp/50.0);
color.setBlueF((50.0 - m_temp)/50.0);
}
QPainter painter(this);
painter.setPen(QPen(Qt::NoPen));
painter.setBrush(QBrush(color));
painter.setWindow(0, 0, 100, 100);
painter.translate(0, 100);
painter.scale(1, -1);
painter.drawRect(0,0,100,m_temp);
m_xform = painter.combinedTransform();
}
void ColorSlider::resizeEvent(QResizeEvent* event)
{
std::cerr << "ColorSlider::resizeEvent(" << width() << ", " <<
height() \
<< ")" << std::endl;
}
void ColorSlider::wheelEvent(QWheelEvent *event)
{
if (event->delta()>0 && m_temp<100) {
std::cerr << "ColorSlider::wheelEvent(SCROLL_UP)" << std::endl;
setValue(m_temp + 1);
}
else if (event->delta()<0 && m_temp>0) {
std::cerr << "ColorSlider::wheelEvent(SCROLL_DOWN)" << std::endl;
setValue(m_temp - 1);
}
}
/* The parent container */
ColorSliderX::ColorSliderX(QWidget* parent):
QWidget(parent), slider(new ColorSlider(this))
{
slider->show();
std::cerr << "ColorSliderX::ColorSliderX()" << std::endl;
}
ColorSliderX::~ColorSliderX()
{
std::cerr << "ColorSliderX::~ColorSliderX()" << std::endl;
}
============== SIP =============
%Module QtPy 0
%Import QtCore/QtCoremod.sip
%Import QtGui/QtGuimod.sip
class ColorSlider : QWidget
{
%TypeHeaderCode
#include "../QtTest/QtPy/qtpy.h"
%End
public:
ColorSlider(QWidget* parent /TransferThis/ = 0);
~ColorSlider();
public slots:
void setValue(int value);
signals:
void valueChanged(int value);
};
class ColorSliderX : QWidget
{
%TypeHeaderCode
#include "../QtTest/QtPy/qtpy.h"
%End
public:
ColorSliderX(QWidget* parent /TransferThis/ = 0);
~ColorSliderX();
ColorSlider* slider;
};
More information about the PyQt
mailing list