View Full Version : Qt Tutorial #1 Add-on
ShaChris23
18th April 2007, 07:06
Hi guys,
For this tutorial here,
http://doc.trolltech.com/4.2/tutorial-t11.html
Does someone know how to do this?
"Modify the program such that the X Y location of each shot bullet is displayed on the GUI on the top right. X Y should become 0, 0 once the shot is completely gone. The definition of gone is not just the bullet being off screen since it's possible for a bullet to go off the screen and fall down."
And, no, this is not a homework! I'm just curious how such feature would be implemented!
marcel
18th April 2007, 07:14
Sure...
First you have to create two labels in the GUI ( or just one ) - one for X and one for Y.
The moving of the bullet is made in CannonField::moveShot(). You should emit a signal from here with the x and y position. The signal should be connected to a slot in the dialog that just updates the labels with the X and Y values.
void CannonField::moveShot()
{
QRegion region = shotRect();
++timerCount;
QRect shotR = shotRect();
if (shotR.x() > width() || shotR.y() > height()) {
autoShootTimer->stop();
} else {
region = region.unite(shotR);
}
update(region);
emit updateBulletPosition(shotRect().topLeft().x(), shotRect().topLeft().y() );
}
Regards
marcel
18th April 2007, 07:24
You have to create the labels in main.cpp:
QHBoxLayout *topLayout = new QHBoxLayout;
topLayout->addWidget(shoot);
topLayout->addStretch(1);
QLabel* mxLabel = new QLabel( this );
QLabel* myLabel = new QLabel( this );
topLayout->addWidget( xLabel );
topLayout->addWidget( yLabel );
connect( cannonField, SIGNAL( updateBulletPosition(int,int) ), this, SLOT( setBulletPosition(int, int ) ) );
QVBoxLayout *leftLayout = new QVBoxLayout;
leftLayout->addWidget(angle);
leftLayout->addWidget(force);
QGridLayout *gridLayout = new QGridLayout;
gridLayout->addWidget(quit, 0, 0);
gridLayout->addLayout(topLayout, 0, 1);
gridLayout->addLayout(leftLayout, 1, 0);
gridLayout->addWidget(cannonField, 1, 1, 2, 1);
gridLayout->setColumnStretch(1, 10);
setLayout(gridLayout);
angle->setValue(60);
force->setValue(25);
angle->setFocus();
In the MyWidget class declaration:
class MyWidget : public QWidget
{
public:
MyWidget(QWidget *parent = 0);
public slots:
void setBulletPosition( int x, int y );
private:
QLabel* mxLabel;
QLabel* myLabel;
};
the slot:
void MyWidget::setBulletPostion( int x, int y )
{
mxLabel->setText( QVariant(x).toString() );
myLabel->setText( QVariant(y).toString() );
}
This is it, pretty much. I'm not sure if the labels will appear correctly ( int the top-right corner ), but that can be fixed easily.
ShaChris23
20th April 2007, 00:28
Hi Marcel,
Thanks for a very helpful post. For some reason though, when I run the program, Qt reports the following:
Object::connect: No such slot QWidget::setBulletPosition(int,int)
I also dont see the x y label on the top right. Here's my current code:
From MyWidget constructor
QHBoxLayout* topLayout = new QHBoxLayout;
topLayout->addWidget(shoot);
topLayout->addStretch(1);
QLabel* mxLabel = new QLabel( this );
QLabel* myLabel = new QLabel( this );
topLayout->addWidget( mxLabel );
topLayout->addWidget( myLabel );
connect( cannonField, SIGNAL( updateBulletPosition( int, int ) ), this, SLOT( setBulletPosition( int, int ) ) );
From MyWidget class declaration
class MyWidget : public QWidget
{
public:
MyWidget( QWidget* parent = 0 );
public slots:
void setBulletPosition( int x, int y );
private:
QLabel* mxLabel;
QLabel* myLabel;
};
From MyWidget::setBulletPosition( int x, int y )
void MyWidget::setBulletPosition( int x, int y )
{
mxLabel->setText( QVariant(x).toString() );
myLabel->setText( QVariant(y).toString() );
}
From CannonField::moveShot()
void CannonField::moveShot()
{
//
QRegion region = shotRect();
++timerCount;
// Get the new shot
QRect shotR = shotRect();
if( shotR.x() > width() || shotR.y() > height() )
{
autoShootTimer->stop();
}
else
{
region = region.unite(shotR);
}
// Repaint the QRegion
update(region);
emit updateBulletPosition( shotRect().topLeft().x(), shotRect().topLeft().y() );
}
Please let me know if I missed anything...I cant think of a reason why this doesnt work.
jacek
20th April 2007, 00:34
Add the Q_OBJECT macro:
class MyWidget : public QWidget
{
Q_OBJECT
public:
...and re-run qmake and make.
marcel
20th April 2007, 17:06
Did you declare the signal updateBulletPosition, in the CannonField class declaration?
Should be something like:
class CanonField : ....
{
...
signals:
void updateBulletPosition( int, int );
...
}
Regards
ShaChris23
20th April 2007, 18:06
Hi Marcel,
Yes, here's my CannonField class declaration:
class CannonField : public QWidget
{
Q_OBJECT
public:
CannonField( QWidget* parent = 0 );
int angle() const { return currentAngle; }
int force() const { return currentForce; }
public slots:
void setAngle( int angle );
void setForce( int force );
void shoot();
private slots:
void moveShot();
signals:
void angleChanged( int newAngle );
void forceChanged( int newForce );
void updateBulletPosition( int x, int y );
protected:
void paintEvent( QPaintEvent* event );
private:
void paintShot( QPainter& painter );
void paintCannon( QPainter& painter );
QRect cannonRect() const;
QRect shotRect() const;
int currentAngle;
int currentForce;
int timerCount;
QTimer* autoShootTimer;
float shootAngle;
float shootForce;
};
ShaChris23
20th April 2007, 18:23
Hmm..this is strange. I put in Q_OBJECT into MyWidget class declaration, and it doesnt complain anymore. But when I press shoot, the program crashes at
qstring.h
here -->
inline int size() const { return d->size; }
under class
class Q_CORE_EXPORT QString
But when I take out Q_OBJECT, the program doesnt crash. Of course, the x y coordinate still doesnt show up when I press the shoot button.
I then looked around a little bit, turns out these 2 lines caused the crash:
void MyWidget::setBulletPosition( int x, int y )
{
mxLabel->setText( QVariant(x).toString() );
myLabel->setText( QVariant(y).toString() );
}
Once I comment out those two lines, it doesnt crash anymore. Do you happen to know why?
I also tried putting a cout debugging like this:
void MyWidget::setBulletPosition( int x, int y )
{
cout << x << " " << y << "\n";
}
and I saw that the x y are "real" numbers, not some garbage values.
I'm using Qt 4.2.3 with VS STUDIO 05.
marcel
20th April 2007, 20:28
Are mxLabel and myLabel valid pointers when you try to set their value?
Do you delete them somehow after you create them and add them to the layout?
Because I can't really see how it could crash in those lines...
Try not setting the actual coordinate. Call the setText methods for a constant string, "1" for example. See what it does then. If it still crashes, then your two pointers gost somehow corrupted.
Regards
ShaChris23
24th April 2007, 00:28
Hi Marcel,
I'm sorry to waste your time...the bug was in my MyWidget's constructor
where
QLabel* mxLabel = new QLabel( this );
QLabel* myLabel = new QLabel( this );
should have been
mxLabel = new QLabel( this );
myLabel = new QLabel( this );
Since I made mxLabel and myLabel part of the class private data members. +_=. So you were right. Sorry about that.
Anyway, how can I make the labels reset to 0 0 when the shot is completely off the screen?
ShaChris23
24th April 2007, 00:29
Also, does anyone know how to do the following?
"Re-paint the cannon to red when the shot is in the air. Then paint the cannon blue when the shot is gone."
Thanks!
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions Inc. All rights reserved.