[Qt-interest] QWidget update() function not calling paintEvent()

Tony Rietwyk tony.rietwyk at rightsoft.com.au
Mon Apr 18 02:23:46 CEST 2011


Hi YoBro, 
 
Sorry for responding directly before.  
 
The parenting via the constructor parameter is separate from the 'parent' related to inheritance.  
 
What is the size() of the CannonShot widgets?  You may need to setMinimumSize on them.  
 
Hope that helps, 
 
Tony
 
 
 

-----Original Message-----
From: yobro at rediffmail.com [mailto:yobro at rediffmail.com] 
Sent: Monday, 18 April 2011 02:19 AM
To: Tony Rietwyk
Subject: Re: [Qt-interest] QWidget update() function not calling paintEvent()


Thanks Tony!
  I am inheriting CannonShot from QWidget...and when I create a new shot from within the shoot() 
function of CannonField, I am creating it as: 

shots.push_back(new CannonShot(this));

where, recall that the CannonShot's constructor calls QWidget constructor:
CannonShot::CannonShot(QWidget *parent): QWidget(parent)

   Now, since CannonField is also inherited from QWidget and is created in the MyWidget constructor (created in main driver) also using:
   
CannonField *cannonField = new CannonField(this);

   and finally MyWidget itself is defined in the main:

int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   MyWidget widget;
   widget.setMinimumSize(300, 300);
   widget.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
   widget.setGeometry(100, 100, 500, 355);
   widget.show();
   return app.exec();
}

My understanding is that since the shot is created using the "this" argument, it should automatically be initialized with MyWidget's dimensions, etc.., no? What am I missing here? I deliberately did not inherit CannonShot from CannonField, since there is no well-established is-a relation ship there..

Thanks for your help!
--T.

On Sun, 17 Apr 2011 10:25:02 , "Tony Rietwyk" <tony.rietwyk at rightsoft.com.au> wrote

Hi Yobro, 
 
When you create a CannonShot, are you giving them a parent?  I'll presume they are parented by the CannonField.  
 
Do the CannonShot's have a minimum size?  I assume the CannonField is being sized by the layout, but not the CannonShot's.  There's no point calling paint if the size is empty.  
 
Hope that helps, 
 
Tony
 
 

-----Original Message-----
From: qt-interest-bounces+tony.rietwyk=rightsoft.com.au at qt.nokia.com [mailto:qt-interest-bounces+tony.rietwyk=rightsoft.com.au at qt.nokia.com] On Behalf Of YoBro 
Sent: Sunday, 17 April 2011 14:22 PM
To: qt-interest at qt.nokia.com
Subject: [Qt-interest] QWidget update() function not calling paintEvent()


Hi all!
   Sorry I am reposting since the formatting got messed up when I cut and pasted last time. I realize others have had this problem too; but I haven't found a fix to mine yet. I was playing around with some code from the Qt tutorial and I am stuck because one of my QWidget inherited classes calls update(QRegion&) but it does not trigger a call to paintEvent(..) - essentially I am trying to do a simple refactoring of the tutorial source code to add multiple shots using a CannonShot class in the 12th chapter of the Qt tutorial (see the link: http://doc.trolltech.com/4.3/tutorial-t12.html)

The CannonField update() still works correctly and causes its paintEvent re-implementation to be called. Its only CannonShot's update() that does not call its own paintEvent. (I've confirmed that it does get before and after the update call). Here are some snippets:

CannonField class:
-----------------------------------------------

#ifndef CANNONFIELD_H
#define CANNONFIELD_H

#include <QWidget>
class QTimer;
class CannonShot;

class CannonField : public QWidget
{
   Q_OBJECT

public:
   CannonField(QWidget *parent = 0);
   ~CannonField();
   static int angle() { return currentAngle; }
   static int force() { return currentForce; }

public slots:
   void setAngle(int angle);
   void setForce(int force);
   void shoot();

signals:
   void angleChanged(int newAngle);
   void forceChanged(int newForce);

protected:
   void paintEvent(QPaintEvent *event);

public:
   static int currentAngle;
   static int currentForce;

private:
    //-Vector of shots
   QVector<CannonShot*> shots;

    void paintCannon(QPainter& painter, QColor& color);
};

#endif

CannonField source:
------------------------------------

#include "cannonfield.h"
#include "cannonshot.h"

int CannonField::currentAngle = 45;
int CannonField::currentForce = 0;

CannonField::CannonField(QWidget *parent): QWidget(parent)
{
    setPalette(QPalette(QColor(250, 250, 200)));
   setAutoFillBackground(true);
 }

CannonField::~CannonField() {
   //-Delete all allocated shots
   for(int i=0; i < shots.size(); ++i) {
      if(shots[i]) {
         delete shots[i];
         shots[i] = NULL;
      }
   }
   shots.clear();
}

void CannonField::shoot()
{
   shots.push_back(new CannonShot(this));
   (shots.back())->shoot();
}

void CannonField::paintEvent(QPaintEvent * /* event */)
{
   QPainter painter(this);
   QColor color;

   //-Update the widget for all shots currently on the field
   bool no_shots_plots_active = true;
   for(QVector<CannonShot*>::const_iterator itr = shots.begin(); itr != shots.end(); ++itr) {
      if ((*itr)->shotTimer()->isActive()) {
         (*itr)->paintShot(painter);
         color = Qt::red;
         paintCannon(painter, color);
         no_shots_plots_active = false;
      }
      else if ((*itr)->plotTimer()->isActive()) {
         (*itr)->paintShotTrajectory(painter);
         color = Qt::blue;
         paintCannon(painter, color);
         no_shots_plots_active = false;
      }
   }
   if(no_shots_plots_active) {
      color = Qt::blue;
      paintCannon(painter, color);
   }
}

CannonShot class:
----------------------------
#ifndef CANNONSHOT_H
#define CANNONSHOT_H

#include <QWidget>
#include <QMap>
class QTimer;
class QSignalMapper;

class CannonShot : public QWidget
{
   Q_OBJECT

public:
   CannonShot(QWidget *parent = 0);
   int angle() const { return shotAngle; }
   int force() const { return shotForce; }
   QTimer* shotTimer() {return autoShotTimer;}
   void shoot();
   QRect shotRect() const;
   void paintShot(QPainter&);
 
private slots:
   void moveShot();

signals:
   void angleChanged(int);
   void forceChanged(int);

protected:
   void paintEvent(QPaintEvent *event);

private:
   QVector<QRect> shotRects() const;
  
   int shotTimerCount;
   QTimer* autoShotTimer;
   float shotAngle;
   float shotForce;
};

#endif

CannonShot source:
-------------------------------

#include "cannonshot.h"

CannonShot::CannonShot(QWidget *parent): QWidget(parent)
{
   setPalette(QPalette(QColor(250, 250, 200)));
   setAutoFillBackground(true);
   shotTimerCount = 0;
   autoShotTimer = new QTimer(this);
   connect(autoShotTimer, SIGNAL(timeout()), this, SLOT(moveShot()));
}

void CannonShot::shoot()
{
   if (autoShotTimer->isActive())
      return;
   shotTimerCount = 0;
   shotAngle = angle();
   shotForce = force();
   autoShotTimer->start(5);
}

void CannonShot::moveShot()
{
    QRegion region = shotRect();
   ++shotTimerCount;

   QRect shotR = shotRect();
   if (shotR.x() > width() || shotR.y() > height()) {
       autoShotTimer->stop();
       emit missed();
   }
   else {
       region = region.unite(shotR);
   }

   //-These fail to call paintEvent even though code passes this point as I checked.
   update(region);
   //repaint(region);
}

void CannonShot::paintEvent(QPaintEvent * /* event */)
{
   //-Never gets here!!
   QPainter painter(this);
   QColor color;
   //-Do whatever
}

Driver app:
-------------------

#include "cannonfield.h"
#include "lcdrange.h"

class MyWidget : public QWidget
{
public:
   MyWidget(QWidget *parent = 0);
};

MyWidget::MyWidget(QWidget *parent)
   : QWidget(parent)
{
   QPushButton *quit = new QPushButton(tr("&Quit"));
   quit->setFont(QFont("Times", 18, QFont::Bold));

   connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));

   LCDRange *angle = new LCDRange(tr("&ANGLE"));
    angle->setRange(0, 90);

   LCDRange *force = new LCDRange(tr("&FORCE"));
   force->setRange(10, 50);

   //CannonField *cannonField = new CannonField;
   CannonField *cannonField = new CannonField(this);

   connect(angle, SIGNAL(valueChanged(int)),
           cannonField, SLOT(setAngle(int)));
   connect(cannonField, SIGNAL(angleChanged(int)),
           angle, SLOT(setValue(int)));

   connect(force, SIGNAL(valueChanged(int)),
           cannonField, SLOT(setForce(int)));
   connect(cannonField, SIGNAL(forceChanged(int)),
           force, SLOT(setValue(int)));

   QPushButton *shoot = new QPushButton(tr("&Shoot"));
   shoot->setFont(QFont("Times", 18, QFont::Bold));
   connect(shoot, SIGNAL(clicked()), cannonField, SLOT(shoot()));

   //-Other layout stuff..

int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   MyWidget widget;
   widget.setMinimumSize(300, 300);
   widget.setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
   widget.setGeometry(100, 100, 500, 355);
   widget.show();
   return app.exec();
}

Again, sorry for the repost.. thanks to anyone who has read and responded. Any ideas are 
appreciated!

--T.


  <http://immail.rediff.com/icons/rediff_mail_gold/grayblock.gif> 


-----

No virus found in this message.

Checked by AVG - www.avg.com

Version: 10.0.1209 / Virus Database: 1500/3578 - Release Date: 04/16/11


 <http://sigads.rediff.com/RealMedia/ads/click_nx.ads/www.rediffmail.com/signatureline.htm@Middle?> 


-----

No virus found in this message.

Checked by AVG - www.avg.com

Version: 10.0.1209 / Virus Database: 1500/3580 - Release Date: 04/17/11

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.qt-project.org/pipermail/qt-interest-old/attachments/20110418/50eb8b6f/attachment.html 


More information about the Qt-interest-old mailing list