Hello folks,
Sorry about the title, the two problems are IMO not connected at all. But I am running into those on the same code snippet and they are puzzling me. First, my setup: Qt Desktop SDK 4.7.3 Linux Ubuntu 11.04 x86_64 Windows 7 / Visual Studio 2010 express *Now the description:* (I moved all the code samples at the end of the post - anyone should be able to reproduce what I am describing now with this minimal example. The code snippet can also be downloaded from here: https://transfert.inria.fr/fichiers/f0ab563059f84fb4b3ca77e7ddfdf2b1/qml_bug.rar- it is available for 5 months). I want to display a *toolbar* on top of a *QGraphicsView* and *animate it*when the mouse enters the top of the view. The toolbar is designed using QML and called from a C++ app. I wrote a QML element, namely a ToolBar (see ToolBar.qml), composed of ToolButtons (see ToolButton.qml). Those ToolButtons are made of a MouseArea and an Image showing the ToolButton icon. Nothing exceptional. Note that icons are taken from a Qt resource file that I embedd in my binary. Now, those QML elements are created from my C++ app using customized QGraphicsScene / QGraphicsView (see myGraphicsView / myGraphicsScene) and QDeclarativeComponent. *My QGraphicsView sets its viewPort to an openGL Widget* because I need it for displaying other stuff. My QGraphicsScene is responsible for creating the QML element and adding it to itself. I also use some logic using a QStateMachine to make the toolbar appear / disappear smoothly (using an animation) when the mouse is over the top the view. In my main app (see main.cpp), *I finally create two of these* (two pairs of (view , scene) embedded in an horizontal layout). *Now the problems:* 1. on Linux, *toolbar icons are totally mixed up or just shown incorrectly* (random pixels). I also get tons of X errors about invalid pixmap parameters. If I use a regular QWidget as a viewPort for my QGraphicsView, everything works fine (but this is not an option). I tried to use item providers, clearing the QPixmapCache, nothing worked. This problem occurs only on Linux, meanging that the behaviour is correct on Windows and Mac. 2. *on Windows, if compiled in Release mode, the program crashes when emitting the signal enterToolbarArea()*. This signal is emitted when the mouse passes over a certain region of the view. It is emitted from the mouseMoveEvent() of the QGraphicsView. This event is then interpreted by the state machine to trigger the display of the toolbar. Note that *if I remove any signal declaration in the root Item of the ToolBar* (see ToolBar.qml - I added a custom dummy signal which is actually never called), *the program runs fine*. If *I remove the animation, the program runs fine as well*. The bug *only appears when compiling in Release mode with Visual Studio*(compiling in Debug or on any other system, it works). I tried with other version of visual studio, same effect. If anyone has an idea about one or the other problem, you'll be my champion. Cheers, Pierre. *Now the code:* ToolButton.qml: import Qt 4.7 > > Rectangle { > id: container > > property string text: "Button" > > property string icon > > signal clicked (bool value); > signal pressed > signal released > > SystemPalette { id: activePalette } > > width: 45 > height: 45 > smooth: true > > color: { > if (mouseArea.pressed) { > return activePalette.highlight; > } > else { > return "gray"; > } > } > > MouseArea { > id: mouseArea > anchors.fill: parent > onClicked: {container.clicked(true);} > > onPressed: container.pressed(); > > onReleased: {container.released();} > } > > Image { > id: myImage > smooth: true > anchors.centerIn: container > source: container.icon > sourceSize.width: container.width > sourceSize.height: container.height > } > } > ToolBar.qml: import Qt 4.7 > > Item { > width: 640 > height: 45 > > signal dummySignal // makes app crash on Windows when compiled in > Release mode > > Rectangle { > id:myToolBar > objectName:"toolBar" > > anchors.fill: parent > > color: "transparent" > > property int spacing: 5 > > > ToolButton { > id: tb1 > icon: "/icons/designer.png" > > anchors.right: parent.right > anchors.verticalCenter: parent.verticalCenter > } > > ToolButton { > id: tb2 > icon: "/icons/go-next.png" > > anchors.right: tb1.left > anchors.rightMargin: parent.spacing > anchors.verticalCenter: parent.verticalCenter > } > > ToolButton { > id: tb3 > icon: "/icons/qwebview.png" > > anchors.right: tb2.left > anchors.rightMargin: parent.spacing > anchors.verticalCenter: parent.verticalCenter > } > > ToolButton { > id: tb4 > icon: "/icons/videoplayer.png" > > anchors.right: tb3.left > anchors.rightMargin: parent.spacing > anchors.verticalCenter: parent.verticalCenter > } > > Rectangle { > id: spacer > anchors {right: tb4.left; rightMargin: 5; verticalCenter: > parent.verticalCenter} > width: parent.width - 4*(tb1.width + 5) > height: parent.height > color: "white" > } > } > } > myGraphicsView.h: #ifndef MYGRAPHICSVIEW_H > #define MYGRAPHICSVIEW_H > > #include <QtGui> > > class myGraphicsScene; > class myGraphicsViewPrivate; > > class myGraphicsView : public QGraphicsView > { > Q_OBJECT > > public: > myGraphicsView (myGraphicsScene * scene, QWidget * parent = > 0); > virtual ~myGraphicsView (void); > > signals: > void enterToolbarArea (void); > void leaveToolbarArea (void); > > protected: > void resizeEvent (QResizeEvent * event); > void mouseMoveEvent (QMouseEvent *event); > > private: > myGraphicsViewPrivate *d; > }; > > #endif // MYGRAPHICSVIEW_H > myGraphicsView.cpp: #include "myGraphicsView.h" > > #include "myGraphicsScene.h" > > #include <QGLWidget> > > #include <QDeclarativeItem> > > class myGraphicsViewPrivate > { > public: > bool top; > > myGraphicsScene *scene; > > QStateMachine *stateMachine; > > QState *toolbarState; > QState *defaultState; > > QPropertyAnimation *toolbarAnimation; > }; > > myGraphicsView::myGraphicsView (myGraphicsScene * scene, QWidget * parent) > : QGraphicsView (scene, parent), d (new myGraphicsViewPrivate) > { > this->setViewport(new QGLWidget(this) ); > this->setViewportUpdateMode( > > QGraphicsView::FullViewportUpdate); > this->setCacheMode(CacheNone); > this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); > this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); > this->setMouseTracking(true); > > Q_ASSERT (scene!=NULL); > > d->scene = scene; > > d->top = false; > > d->toolbarAnimation = new QPropertyAnimation (d->scene->toolbar(), "y", > this); > d->toolbarAnimation->setDuration(250); > d->toolbarAnimation->setEasingCurve(QEasingCurve::InOutQuad); > > // Build the state machine > d->stateMachine = new QStateMachine (this); > > d->toolbarState = new QState (d->stateMachine); > d->defaultState = new QState (d->stateMachine); > > d->stateMachine->setInitialState (d->defaultState); > > d->defaultState->addTransition (this, SIGNAL (enterToolbarArea()), > d->toolbarState) > ->addAnimation (d->toolbarAnimation); > d->toolbarState->addTransition (this, SIGNAL (leaveToolbarArea()), > d->defaultState) > ->addAnimation (d->toolbarAnimation); > > QRectF rect = d->scene->toolbar()->boundingRect(); > > d->toolbarState->assignProperty (d->scene->toolbar(), "y", 0); > d->defaultState->assignProperty (d->scene->toolbar(), "y", > -rect.height()); > > d->stateMachine->start(); > } > > myGraphicsView::~myGraphicsView (void) > { > delete d; > } > > void myGraphicsView::resizeEvent (QResizeEvent * event) > { > QGraphicsView::resizeEvent (event); > > if (d->scene) { > QPointF shownPos = this->mapToScene (0, 0); > QPointF hiddenPos = this->mapToScene (0, -45); > > if (d->stateMachine->configuration().contains (d->toolbarState)) > d->scene->toolbar()->setPos ( shownPos ); > else > d->scene->toolbar()->setPos ( hiddenPos ); > > d->scene->toolbar()->setWidth ( event->size().width() ); > > d->toolbarState->assignProperty (d->scene->toolbar(), "y", > shownPos.y()); > d->defaultState->assignProperty (d->scene->toolbar(), "y", > hiddenPos.y()); > > this->update(); > } > } > > > void myGraphicsView::mouseMoveEvent( QMouseEvent * e ) > { > if ( e->buttons() == Qt::NoButton ) { > if (d->scene->toolbar()->boundingRect().contains ( e->pos() ) ) { > if (!d->top) { > d->top = true; > emit enterToolbarArea(); > } > } > else { > if (d->top) { > d->top = false; > emit leaveToolbarArea(); > } > } > } > else > QGraphicsView::mouseMoveEvent (e); > } > myGraphicsScene.h: #ifndef MYGRAPHICSSCENE_H > #define MYGRAPHICSSCENE_H > > #include <QtGui> > > class QDeclarativeItem; > class myGraphicsScenePrivate; > > class myGraphicsScene : public QGraphicsScene > { > Q_OBJECT > > public: > myGraphicsScene (QObject * parent = 0); > virtual ~myGraphicsScene (void); > > QDeclarativeItem *toolbar (void) const; > > private: > myGraphicsScenePrivate *d; > > }; > > #endif // myGraphicsScene_H > myGraphicsScene.cpp: #include "myGraphicsScene.h" > > #include <QDeclarativeEngine> > #include <QDeclarativeComponent> > #include <QDeclarativeItem> > > #include <QDebug> > > class myGraphicsScenePrivate > { > public: > QDeclarativeEngine *engine; > QDeclarativeItem *toolbar; > }; > > myGraphicsScene::myGraphicsScene(QObject *parent) > : QGraphicsScene (parent), d (new myGraphicsScenePrivate) > { > d->engine = new QDeclarativeEngine (this); > > QDeclarativeComponent component (d->engine, > QUrl("qrc:/qml/ToolBar.qml")); > d->toolbar = qobject_cast<QDeclarativeItem *>(component.create()); > if (!d->toolbar) { > qDebug() << "cannot create toolbar"; > qDebug() << component.errorString(); > } > Q_ASSERT (d->toolbar!=NULL); > > d->toolbar->setPos (0, 0); > d->toolbar->setHeight (45); > d->toolbar->setY(-45); > > this->addItem (d->toolbar); > } > > myGraphicsScene::~myGraphicsScene (void) > { > delete d; > } > > QDeclarativeItem *myGraphicsScene::toolbar (void) const > { > return d->toolbar; > } > main.cpp: #include <QApplication> > > #include <QtGui> > > #include "myGraphicsScene.h" > #include "myGraphicsView.h" > > int main (int argc, char *argv[]) > { > QApplication application (argc, argv); > > QMainWindow mainWindow; > > QWidget *mainWidget = new QWidget (&mainWindow); > > // create 2 scenes > myGraphicsScene *scene1 = new myGraphicsScene (mainWidget); > myGraphicsScene *scene2 = new myGraphicsScene (mainWidget); > > // create 2 myGraphicsView instances > myGraphicsView *view1 = new myGraphicsView (scene1, mainWidget); > myGraphicsView *view2 = new myGraphicsView (scene2, mainWidget); > > // create a default layout > QHBoxLayout * layout = new QHBoxLayout (mainWidget); > layout->addWidget (view1); > layout->addWidget (view2); > > mainWindow.setCentralWidget (mainWidget); > mainWindow.resize (640, 480); > > mainWindow.show(); > > return application.exec(); > } > -- Pierre Fillard, Ph.D., Research Scientist INRIA Parietal - Neurospin Bât 145, Point Courrier 156 91191 Gif/Yvette, France tel: +33 1 69 08 79 92 INRIA Saclay-Île-de-France, Parc Orsay Université 4, rue Jacques Monod 91893 Orsay cedex tel: +33 1 72 92 59 62
_______________________________________________ Qt-qml mailing list [email protected] http://lists.qt.nokia.com/mailman/listinfo/qt-qml
