haze
30th June 2010, 12:30
Hi! I'm fairly new to Qt, C++ and OOP all together, but I'm working on a project as a part of a summerjob.
I'm developing a small custom widget which will graphically display a recived value (something akin to a speedometer), and what I have made so far works to certain degree... untill I try to use more than one instance of the widget in a UI. The first instance displays correctly, but the graphical items in the second one doesn't seem to initialize. On the other hand it seems like the second instance recives input which is actually only connected to the input-slot on the first instance. My gut-feeling says it's something to do with what inherits what?
All in all, I feel a bit confused. What precautions do you have to take when you're writing a widget meant to be reused several times in a GUI?
The widget is built so that it can be loaded directly into QtDesigner as a plugin and I use svg-graphics (just mentioning if this could be related to the problem). I've programmed it in QtCreator.
The widget itself is a huge mess of stuff, so I wrote a smaller example illustrating the basics of how I've made the it and which also demonstrates the same problem. It compiles without any warnings.
In short: I can't get two instances of a selfmade widget to work in a UI, while one single one works. Example code below:
displayclass.h
#ifndef DISPLAYCLASS_H
#define DISPLAYCLASS_H
#include <QtGui/QWidget>
#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsSvgItem>
#include <QGraphicsItem>
#include <QSvgRenderer>
#include <QTimer>
#include <QDebug>
//#include <qdesignerexportwidget.h>
#include <QLabel>
class /*QDESIGNER_WIDGET_EXPORT*/ displayclass : public QWidget
{
Q_OBJECT
public:
displayclass(QWidget *parent = 0);
QSvgRenderer *svgRend;
QGraphicsScene *scene;
QGraphicsView *view;
QLabel *label;
QGraphicsRectItem *rectangle;
QGraphicsSvgItem *arrow;
QTimer *timer;
void UpdateAll(double rotation, int save_angle);
void DisplaySquare(double rotation);
void DisplayArrow();
void DisplayLabel(double rotation);
public slots:
void Input(int rotation);
private slots:
void Timer();
};
#endif
displayclass.cpp
#include "displayclass.h"
displayclass::displayclass(QWidget *parent) :
QWidget(parent)
{
//Definitions
scene = new QGraphicsScene(QRect(0, 0, 300, 300),this);
svgRend = new QSvgRenderer(QLatin1String(":/arrow.svg"),this);
view = new QGraphicsView(this);
arrow = new QGraphicsSvgItem();
rectangle = new QGraphicsRectItem(0,0,100,100);
label = new QLabel(this);
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(Timer()));
timer->start(30);
scene->setSceneRect(0,0,300,300);
view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
view->setGeometry(QRect(0, 0, 350, 350));
view->setScene(scene);
view->show();
UpdateAll(0,0);
}
void displayclass::UpdateAll(double rotation, int save_angle)
{
static double rot=0;
if(save_angle==1)
{
rot=rotation;
}
else
{
DisplaySquare(rot);
DisplayArrow();
DisplayLabel(rot);
}
}
void displayclass::DisplaySquare(double rotation)
{
static int rectangle_activated=0;
if(rectangle_activated==0)
{
rectangle->setBrush( Qt::red );
rectangle->setPos(0,0);
qDebug()<<rectangle->pos();
rectangle_activated=1;
scene->addItem(rectangle);
}
rectangle->setRotation(rotation);
}
void displayclass::DisplayArrow()
{
static int arrow_activated=0;
if(arrow_activated==0)
{
arrow->setParentItem(rectangle);
arrow->setSharedRenderer(svgRend);
arrow->setPos(0,0);
}
}
void displayclass::DisplayLabel(double rotation)
{
static bool label_activated=0;
if(label_activated==0)
{
label->setParent(this);
label->setGeometry((scene->width()/2)-25,(scene->height()/2)-(label->height()/2),50,25);
label->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
label->setAutoFillBackground(1);
label->setStyleSheet("QLabel { border-width: 2px; border-radius: 4px; border-style: solid; border-color: darkGray; background-color: white;}");
label_activated=1;
}
label->setText(QString::number(rotation));
}
void displayclass::Timer()
{
UpdateAll(0,0);
}
void displayclass::Input(int rotation)
{
UpdateAll(rotation,1);
}
I also attached a picture of how it looks when I use two instances in a quickly put together application.
Both of the instances are declared like so in ui_mainwindow of the application:
displayclass1 = new displayclass(centralWidget);
displayclass1->setObjectName(QString::fromUtf8("displayclass1"));
displayclass1->setGeometry(QRect(40, 60, 211, 231));
displayclass2 = new displayclass(centralWidget);
displayclass2->setObjectName(QString::fromUtf8("displayclass2"));
displayclass2->setGeometry(QRect(350, 60, 201, 231));
Hmm, anything else I should specify if it could be helpful?
Thanks for any help in advance! :D (oh and sorry for any bad English!)
Any comments about obvious c++/Qt basics I've missed are also welcome!
I'm developing a small custom widget which will graphically display a recived value (something akin to a speedometer), and what I have made so far works to certain degree... untill I try to use more than one instance of the widget in a UI. The first instance displays correctly, but the graphical items in the second one doesn't seem to initialize. On the other hand it seems like the second instance recives input which is actually only connected to the input-slot on the first instance. My gut-feeling says it's something to do with what inherits what?
All in all, I feel a bit confused. What precautions do you have to take when you're writing a widget meant to be reused several times in a GUI?
The widget is built so that it can be loaded directly into QtDesigner as a plugin and I use svg-graphics (just mentioning if this could be related to the problem). I've programmed it in QtCreator.
The widget itself is a huge mess of stuff, so I wrote a smaller example illustrating the basics of how I've made the it and which also demonstrates the same problem. It compiles without any warnings.
In short: I can't get two instances of a selfmade widget to work in a UI, while one single one works. Example code below:
displayclass.h
#ifndef DISPLAYCLASS_H
#define DISPLAYCLASS_H
#include <QtGui/QWidget>
#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsSvgItem>
#include <QGraphicsItem>
#include <QSvgRenderer>
#include <QTimer>
#include <QDebug>
//#include <qdesignerexportwidget.h>
#include <QLabel>
class /*QDESIGNER_WIDGET_EXPORT*/ displayclass : public QWidget
{
Q_OBJECT
public:
displayclass(QWidget *parent = 0);
QSvgRenderer *svgRend;
QGraphicsScene *scene;
QGraphicsView *view;
QLabel *label;
QGraphicsRectItem *rectangle;
QGraphicsSvgItem *arrow;
QTimer *timer;
void UpdateAll(double rotation, int save_angle);
void DisplaySquare(double rotation);
void DisplayArrow();
void DisplayLabel(double rotation);
public slots:
void Input(int rotation);
private slots:
void Timer();
};
#endif
displayclass.cpp
#include "displayclass.h"
displayclass::displayclass(QWidget *parent) :
QWidget(parent)
{
//Definitions
scene = new QGraphicsScene(QRect(0, 0, 300, 300),this);
svgRend = new QSvgRenderer(QLatin1String(":/arrow.svg"),this);
view = new QGraphicsView(this);
arrow = new QGraphicsSvgItem();
rectangle = new QGraphicsRectItem(0,0,100,100);
label = new QLabel(this);
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(Timer()));
timer->start(30);
scene->setSceneRect(0,0,300,300);
view->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
view->setGeometry(QRect(0, 0, 350, 350));
view->setScene(scene);
view->show();
UpdateAll(0,0);
}
void displayclass::UpdateAll(double rotation, int save_angle)
{
static double rot=0;
if(save_angle==1)
{
rot=rotation;
}
else
{
DisplaySquare(rot);
DisplayArrow();
DisplayLabel(rot);
}
}
void displayclass::DisplaySquare(double rotation)
{
static int rectangle_activated=0;
if(rectangle_activated==0)
{
rectangle->setBrush( Qt::red );
rectangle->setPos(0,0);
qDebug()<<rectangle->pos();
rectangle_activated=1;
scene->addItem(rectangle);
}
rectangle->setRotation(rotation);
}
void displayclass::DisplayArrow()
{
static int arrow_activated=0;
if(arrow_activated==0)
{
arrow->setParentItem(rectangle);
arrow->setSharedRenderer(svgRend);
arrow->setPos(0,0);
}
}
void displayclass::DisplayLabel(double rotation)
{
static bool label_activated=0;
if(label_activated==0)
{
label->setParent(this);
label->setGeometry((scene->width()/2)-25,(scene->height()/2)-(label->height()/2),50,25);
label->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
label->setAutoFillBackground(1);
label->setStyleSheet("QLabel { border-width: 2px; border-radius: 4px; border-style: solid; border-color: darkGray; background-color: white;}");
label_activated=1;
}
label->setText(QString::number(rotation));
}
void displayclass::Timer()
{
UpdateAll(0,0);
}
void displayclass::Input(int rotation)
{
UpdateAll(rotation,1);
}
I also attached a picture of how it looks when I use two instances in a quickly put together application.
Both of the instances are declared like so in ui_mainwindow of the application:
displayclass1 = new displayclass(centralWidget);
displayclass1->setObjectName(QString::fromUtf8("displayclass1"));
displayclass1->setGeometry(QRect(40, 60, 211, 231));
displayclass2 = new displayclass(centralWidget);
displayclass2->setObjectName(QString::fromUtf8("displayclass2"));
displayclass2->setGeometry(QRect(350, 60, 201, 231));
Hmm, anything else I should specify if it could be helpful?
Thanks for any help in advance! :D (oh and sorry for any bad English!)
Any comments about obvious c++/Qt basics I've missed are also welcome!