PDA

View Full Version : How to draw a circle with spinbox coordinates



rdelgado
6th August 2010, 20:34
Hi,

I'm trying to make a simple drawing application and I am having some trouble.
My app have 1 drawingarea, 2 spinboxes, 2 buttons (one of the the quit button).
All I want to do is to start the program and show nothing in the drawing area. Then, using the spinboxes, set the X and Y coordinates of a circle. Then when I press the Action button, I want the circle to be displayed in the location given before.
I made the program buy what happens is that the circle is always drawing in the same position I give it initially. I don't know why it won't get the right position from the spinboxes before drawing.
I'll appreciate any help or suggestion.

I'll put the code of my program. Excuse me the words in spanish within the code.

This is the main.cpp file:



#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QWidget>

#include "spinvariable.h"
#include "areadibujo.h"

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

signals:

public slots:

};

MiWidget::MiWidget(QWidget *parent) :
QWidget(parent)
{
QPushButton *quit = new QPushButton("Quit");
QPushButton *accion = new QPushButton("Accion");

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

spinvariable *spin1 = new spinvariable;
spinvariable *spin2 = new spinvariable;

spin1->setLabel("Valor X:");
spin1->setValue(10);
spin1->setRange(0, 100);


spin2->setLabel("Valor Y:");
spin2->setValue(20);
spin2->setRange(0, 100);

areadibujo *area = new areadibujo;

QObject::connect(spin1, SIGNAL(valueChanged(int)), area, SLOT(setposicionX(int)));
QObject::connect(spin2, SIGNAL(valueChanged(int)), area, SLOT(setposicionY(int)));
QObject::connect(area, SIGNAL(cambiox(int)), spin1, SLOT(setValue(int)));
QObject::connect(area, SIGNAL(cambioy(int)), spin2, SLOT(setValue(int)));

QObject::connect(accion, SIGNAL(clicked()), area, SLOT(accion()));

QVBoxLayout *marcovertical = new QVBoxLayout;
QHBoxLayout *marcohorizontal = new QHBoxLayout;

marcovertical->addWidget(area);
marcovertical->addStretch();
marcohorizontal->addWidget(spin1);
marcohorizontal->addWidget(spin2);
marcohorizontal->addStretch();
marcovertical->addLayout(marcohorizontal);
marcovertical->addWidget(accion);
marcovertical->addWidget(quit);
setLayout(marcovertical);
}


int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MiWidget widget;
widget.setGeometry(0, 0, 500, 500);
widget.show();
return app.exec();
}


This is the spinvariable class:

spinvariable.h



#ifndef SPINVARIABLE_H
#define SPINVARIABLE_H

#include <QWidget>

class QSpinBox;
class QLabel;

class spinvariable : public QWidget
{
Q_OBJECT

public:
spinvariable(QWidget *parent = 0);
int value() const;

signals:
void valueChanged(int newValue);

public slots:
void setLabel(char *nombre);
void setValue(int value);
void setRange(int Rmin, int Rmax);

private:
QSpinBox *spinbox;
QLabel *label;
};

#endif // SPINVARIABLE_H


spinvariable.cpp


#include <QSpinBox>
#include <QLabel>
#include <QHBoxLayout>
#include "spinvariable.h"

spinvariable::spinvariable(QWidget *parent) :
QWidget(parent)
{
spinbox = new QSpinBox;
label = new QLabel;

QHBoxLayout *layout = new QHBoxLayout;

layout->addWidget(label);
layout->addWidget(spinbox);

setLayout(layout);
}

void spinvariable::setValue(int value)
{
spinbox->setValue(value);
}

void spinvariable::setRange(int Rmin, int Rmax)
{
spinbox->setRange(Rmin, Rmax);
}

int spinvariable::value() const
{
return spinbox->value();
}

void spinvariable::setLabel(char *nombre)
{
label->setText(nombre);
}


This is the areadibujo class (drawingarea):

areadibujo.h



#ifndef AREADIBUJO_H
#define AREADIBUJO_H

#include <QWidget>

class areadibujo : public QWidget
{
Q_OBJECT
public:
areadibujo(QWidget *parent = 0);

signals:
void cambiox(int nuevox);
void cambioy(int nuevoy);

public slots:
void accion();
void setposicionX(int x);
void setposicionY(int y);

protected:
void paintEvent(QPaintEvent *event);

private:
void pintaCirculo(QPainter &painter);
int apretar;

int posicionX, posicionY;
};

#endif // AREADIBUJO_H


areadibujo.cpp


#include <QPaintEvent>
#include <QPainter>
#include "areadibujo.h"

areadibujo::areadibujo(QWidget *parent) :
QWidget(parent)
{
setPalette(QPalette(QColor(255, 255, 255)));
setAutoFillBackground(true);
setFixedSize(500, 450);
posicionX=10;
posicionY=20;
apretar=0;
}

void areadibujo::paintEvent(QPaintEvent *)
{
QPainter painter(this);

if(apretar==1)
{
pintaCirculo(painter);
}
}

void areadibujo::pintaCirculo(QPainter &painter)
{
painter.setPen(Qt::NoPen);
painter.setBrush(Qt::blue);
painter.drawEllipse(posicionX,posicionY,10,10);
}

void areadibujo::accion()
{
update();
apretar=1;
}

void areadibujo::setposicionX(int x)
{
posicionX=x;
emit cambiox(posicionX);
}

void areadibujo::setposicionY(int y)
{
posicionY=y;
emit cambioy(posicionY);
}


I can't see how to make it work.
I am using the cannonball Qt tutorial as an example.

Thanks you.

R. D.

Lykurg
6th August 2010, 22:09
Hi,

it because you connect a signal valueChanged of your class spinvariable with the setter, but you never emit such a signal! You obviously think this should be from your spinbox, but it is in your container class and the signal is not forwarded, so you have to write in your constructor:
QObject::connect(spinbox, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int)));then it will work.

Note: your last two connections of
QObject::connect(spin1, SIGNAL(valueChanged(int)), area, SLOT(setposicionX(int)));
QObject::connect(spin2, SIGNAL(valueChanged(int)), area, SLOT(setposicionY(int)));
QObject::connect(area, SIGNAL(cambiox(int)), spin1, SLOT(setValue(int)));
QObject::connect(area, SIGNAL(cambioy(int)), spin2, SLOT(setValue(int)));
don't make sense with your actual code. You can skip them.

Lykurg

rdelgado
7th August 2010, 16:23
Hi,

it because you connect a signal valueChanged of your class spinvariable with the setter, but you never emit such a signal! You obviously think this should be from your spinbox, but it is in your container class and the signal is not forwarded, so you have to write in your constructor:
Qt Code:


QObject::connect(spinbox, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int)));


That won't work, since there is no valueChanged() signal for the MiWidget widget.
The thing is that when I press the Accion button, it should update the posicionX and posicionY variables and put it in the pintaCirculo() event... I can't make it work yet.

Thanks for the help!

tbscope
7th August 2010, 16:45
Not in MiWidget, but in SpinVariable.

You do not emit a signal at the moment from SpinVariable.

rdelgado
8th August 2010, 14:20
Not in MiWidget, but in SpinVariable.

You do not emit a signal at the moment from SpinVariable.


Sorry but I don't understand.
I emit it right here, I think:



QObject::connect(spin1, SIGNAL(valueChanged(int)), area, SLOT(setposicionX(int)));
QObject::connect(spin2, SIGNAL(valueChanged(int)), area, SLOT(setposicionY(int)));


Right there, when the spinbox value is changed it should trigger the setposicion functions.

Thanks for the help!

Lykurg
8th August 2010, 14:29
There you only connect! In your class SpinVariable you have to add a signal forwarding as said:
spinvariable::spinvariable(QWidget *parent) :
QWidget(parent)
{
spinbox = new QSpinBox;
label = new QLabel;

QHBoxLayout *layout = new QHBoxLayout;

layout->addWidget(label);
layout->addWidget(spinbox);

setLayout(layout);
QObject::connect(spinbox, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int)));
}
The
QObject::connect(spin1, SIGNAL(valueChanged(int)), area, SLOT(setposicionX(int)));never came to action, since such a signal is never emitted!

tbscope
8th August 2010, 14:29
spinvariable::spinvariable(QWidget *parent) :
QWidget(parent)
{
spinbox = new QSpinBox;
label = new QLabel;

QHBoxLayout *layout = new QHBoxLayout;

layout->addWidget(label);
layout->addWidget(spinbox);

setLayout(layout);

QObject::connect(spinbox, SIGNAL(valueChanged(int)), this, SIGNAL(valueChanged(int)));
}

Edit: too late again ;-)

rdelgado
9th August 2010, 15:11
Hi!

It worked! Thank you very much.

Now, I am a little confused. Why do I have to connect the valueChanged() signal of the spinbox to itself?
Is it because I am using a PushButton to trigger and event?
I mean, I've been reading and doing a lot of Qt tutorials and this is the first time I see that. I followed the cannonball tutorial to write my program and if you check it you'll see they don't do that. Whenever the slider is moved in their program, it updates the variable values in the cannonball drawing area.

I thought that whenever a spinbox or a slider is changed, it emits its valueChanged() signal, and the only thing you have to do is to connect it to whatever you want to do.

So if you please can clarify me that I'll appreciate.

Thanks again!

Lykurg
9th August 2010, 20:42
You don't connect the signal to itself. To use a signal you need direct access to the object. In MiWidget you cant access your spinbox, you only can access your class spinvariable. It has a spinbox inside, but that don't matter, for the connect it is only a widget and a widget has no value changed signal. So you have to forward the signal. From the spinbox to the class spinvariable and from there to your MiWidget.

Another option would be to declare a public pointer to your spinbox but that would be a bad design.

rdelgado
9th August 2010, 21:57
Hi,

Now I see it, as you said, from the spinbox to the class, and from there to MiWidget!
I get it now. In the others examples I looked, all the spinboxes and sliders where part of the same class.

Thank you very much for the help. I'll keep learning!