I've created a small QT application that redraws a circle at a random position.
What I would like to do is repeat the method a predetermined number of times that draws the circle every second using a QTimer.
I am not sure how to go about to this.
Here is my main.cpp
int main(int argc, char *argv[]) {
// initialize resources, if needed
// Q_INIT_RESOURCE(resfile);
srand (time(NULL));
QApplication app(argc, argv);
widget f;
f.show();
return app.exec();
}
widget.cpp
#include "widget.h"
widget::widget()
{
widget.setupUi(this);
}
void widget::paintEvent(QPaintEvent * p)
{
QPainter painter(this);
//**code
printcircle(& painter); //paints the circle
//**code
}
void paintcircle(QPainter* painter)
{
srand (time(NULL));
int x = rand() %200 + 1;
int y = rand() %200 + 1;
QRectF myQRect(x,y,30,30);
painter->drawEllipse(myQRect);
}
widget::~widget()
{}
widget.h
#ifndef _WIDGET_H
#define _WIDGET_H
class widget : public QWidget {
Q_OBJECT
public:
widget();
virtual ~widget();
public slots:
void paintEvent(QPaintEvent * p);
private:
Ui::widget widget;
};
#endif /* _WIDGET_H */
How would I go about creating a Qtimer to repeat the printcricle() method.
Thanks
You can create a timer in your widget class constructor as:
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1000);
I.e. it will call the widget's paint event every second.
Right, there are a couple of things to modify in your code in order to accomplish this:
Forward declare a QTimer
Add a QTimer member
Include the QTimer header.
Set a continuous QTimer in the constructor of your widget class.
Make sure you set the connection to the update slot so that a repaint is scheduled by the event loop.
You need to add a counter for the predetermined times as there is no such feature built into QTimer.
You need to initialise that variable to zero.
You need to increment that in each slot call.
You need to stop emitting the timeout signal for the QTimer.
In order to achieve all that above, your code would become something like this:
widget.cpp
#include "widget.h"
#include <QTimer>
// Could be any number
const static int myPredeterminedTimes = 10;
widget::widget()
: m_timer(new QTimer(this))
, m_count(0)
{
widget.setupUi(this);
connect(m_timer, SIGNAL(timeout()), SLOT(update()));
timer->start(1000);
}
void widget::paintEvent(QPaintEvent * p)
{
QPainter painter(this);
//**code
printcircle(& painter); //paints the circle
//**code
}
void widget::paintcircle(QPainter* painter)
{
srand (time(NULL));
int x = rand() %200 + 1;
int y = rand() %200 + 1;
QRectF myQRect(x,y,30,30);
painter->drawEllipse(myQRect);
}
widget::~widget()
{}
widget.h
#ifndef _WIDGET_H
#define _WIDGET_H
class QTimer;
class widget : public QWidget {
Q_OBJECT
public:
widget();
virtual ~widget();
public slots:
void paintEvent(QPaintEvent * p);
private:
Ui::widget widget;
private:
QTimer *m_timer;
int m_count;
};
#endif /* _WIDGET_H */
Related
I have a QGraphicsView in a QDockWidget, in which I'm displaying a PNG image. If I create a QPixMapItem in the dockwidget's constructor, and call a dockwidget's member function (a public slot) from within the constructor to display the image, it works fine.
However, if I invoke the slot from my MainWindow (a class called 'IView') via a signal, then the image does not show. What am I doing wrong?
Dockwidget construcor:
IvConfDockWidget::IvConfDockWidget(IView *parent) :
QDockWidget(parent),
ui(new Ui::IvConfDockWidget)
{
ui->setupUi(this);
MyGraphicsView *zoomGraphicsView = new MyGraphicsView();
MyGraphicsScene *zoomScene = new MyGraphicsScene();
ui->zoomLayout->addWidget(zoomGraphicsView);
QPixmap zoomPixmap = QPixmap("/home/mischa/logo.png");
QGraphicsPixmapItem *zoomPixmapItem = new QGraphicsPixmapItem(zoomPixmap);
updateZoomWindowReceived(zoomPixmapItem); // does not work if called from MainWindow
}
Here is the public slot:
void IvConfDockWidget::updateZoomWindowReceived(QGraphicsPixmapItem *zoomPixmapItem)
{
zoomGraphicsView->resetMatrix();
zoomScene->clear();
zoomScene->addItem(zoomPixmapItem);
zoomGraphicsView->setScene(zoomScene);
zoomGraphicsView->show();
}
If I comment out updateZoomWindowReceived() in the constructor, and call it via a signal from my MainWindow, then the graphics does not show. Here is the code in my MainWindow:
IvConfDockWidget *icdw = new IvConfDockWidget;
connect(this, &IView::updateZoomWindow, icdw, &IvConfDockWidget::updateZoomWindowReceived);
QPixmap zoomPixmap = QPixmap("/home/mischa/logo.png");
icdw->zoomGraphicsView->resetMatrix();
QGraphicsPixmapItem *newItem = new QGraphicsPixmapItem(zoomPixmap);
emit updateZoomWindow(newItem);
And for completeness, my derived versions of QGraphicsView and QGraphicsScene:
#define MYGRAPHICSVIEW_H
#include <QGraphicsView>
#include <QDebug>
#include <QMouseEvent>
#include <QScrollBar>
class MyGraphicsView : public QGraphicsView
{
Q_OBJECT
private:
QPointF rightDragStartPos;
QPointF rightDragCurrentPos;
QPointF rightDragEndPos;
QPointF leftDragStartPos;
QPointF leftDragCurrentPos;
QPointF leftDragEndPos; // unused
QPointF middleDragStartPos;
QPointF middleDragCurrentPos;
QPointF middleDragEndPos;
bool rightButtonPressed = false;
bool leftButtonPressed = false;
bool middleButtonPressed = false;
QPoint previousMousePoint;
bool _pan = false;
int _panStartX = 0;
int _panStartY = 0;
public:
explicit MyGraphicsView();
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
QScrollBar *sxbar = nullptr;
QScrollBar *sybar = nullptr;
QString middleMouseMode = "DragMode";
int x = 0;
int y = 0;
signals:
void currentMousePos(QPointF);
void rightDragTravelled(QPointF);
void middleDragTravelled(QPointF pointStart, QPointF pointEnd);
void middleWCSTravelled(QPointF pointStart, QPointF pointEnd);
void middleWCSreleased();
void leftDragTravelled(QPointF pointStart, QPointF pointEnd);
void rightPress();
void leftPress(QPointF pointStart);
void middlePress(QPointF point);
void leftButtonReleased();
void rightButtonReleased();
void middleButtonReleased();
void middlePressResetCRPIX();
public slots:
void updateMiddleMouseMode(QString mode);
};
#endif // MYGRAPHICSVIEW_H
and
#ifndef MYGRAPHICSSCENE_H
#define MYGRAPHICSSCENE_H
#include <QObject>
#include <QGraphicsScene>
#include <QKeyEvent>
class MyGraphicsScene : public QGraphicsScene
{
Q_OBJECT
public:
MyGraphicsScene();
signals:
void itemDeleted();
protected:
void keyReleaseEvent(QKeyEvent * keyEvent);
};
#endif // MYGRAPHICSSCENE_H
I figured it out. My MainWindow uses a hybrid drive/RAM data model which can be in different states, and it happened that in one of the states the signal was never emitted. Once I fixed that, the behavior is as desired.
Sorry for the noise.
I am creating object from QGraphicsRectItem and adding to the Qgraphicscene(scene).
I want to get every movement(pos) of object(qgraphicsrectitem) so that I subclassed Qgraphicsrectitem. But in this class I am getting some errors.
How can I get object position changed in scene ?
error:
'staticMetaObject' is not a member of 'QGraphicsRectItem'
{ &QGraphicsRectItem::staticMetaObject, qt_meta_stringdata_ItemHandler.data
ItemHandler.h
#include <QObject>
#include <QGraphicsRectItem>
class ItemHandler : public QGraphicsRectItem, public QObject
{
Q_OBJECT
public:
ItemHandler(QGraphicsItem *parent = 0 );
~ItemHandler();
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
signals:
void objectHandlePosChanged(QPointF value);
};
ItemHandler.cpp
#include "itemhandler.h"
ItemHandler::ItemHandler(QGraphicsItem *parent) : QGraphicsRectItem(parent)
{
setFlag(QGraphicsItem::ItemSendsGeometryChanges);
}
ItemHandler::~ItemHandler()
{
}
QVariant ItemHandler::itemChange(QGraphicsItem::GraphicsItemChange change,
const QVariant &value)
{
QPointF newPos = value.toPointF();
emit objectHandlePosChanged(newPos);
}
In you header file, inherit first from QObject, as follows:
#include <QObject>
#include <QGraphicsRectItem>
class ItemHandler : public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
ItemHandler(QGraphicsItem *parent = 0 );
~ItemHandler();
protected:
QVariant itemChange(GraphicsItemChange change, const QVariant &value);
signals:
void objectHandlePosChanged(QPointF value);
};
And this is my test main function (sorry it's just a sandbox):
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow* mywindow = new MainWindow();
QGraphicsScene scene;
ItemHandler *item = new ItemHandler;
item->setRect(10.0, 10.0, 10.0, 10.0);
scene.addItem(item);
QApplication::connect(item, SIGNAL(objectHandlePosChanged(QPointF)), mywindow, SLOT(moved(QPointF)));
QGraphicsView view(&scene);
view.setFixedSize(250, 250);
view.setWindowTitle("QGraphicsItem Test");
item->setPos(-100, -100);
item->setPos(-200, -200);
view.show();
return app.exec();
}
I just used an empty MainWindow that is never displayed to have a slot to connect to the signal, there's no point in having a MainWindow: it was already there and I modified it instead of creating a new class. The example works, fires the signal and displays the rectangle.
I am writing to ask for advice on how best to implement my code using QT library. I have a class called Action class that every one second retrieve the PC time (with gettimeofday), this value shall be displayed in the GUI. So I have a class widget that defines all the widgets necessary for the GUI. The value (expressed in seconds) will be displayed with a QLineEdit.
So my question is, how I have to implement Signal and slot to update the value in QLineEdit?
Should I emit a signal every time the function retreiveTimetoSend is called?
action.h
class Action: public object
{
Q_OBJECT
private:
Qtimer timer;
unisgned int timetosend;
private:
void retreiveTimetoSend();
public:
Action();
~Action();
public slots:
void doWork();
}
action.cpp
void retreiveTimetoSend()
{
struct timeval Now;
unsigned int Sec;
gettimeofday(&Now, NULL);
Sec = Now.tv_sec;
time.value =Sec;
}
void Action::Action()
{
timer.setInterval(1000);
connect(&timer, SIGNAL(timeout()), this, SLOT (doWork()));
timer.start();
}
void Action::doWork()
{
retreiveTimetoSend()
}
widget.h
class widgets: public QWidget
{
Q_OBJECT
private:
QLineEdit *displayTime;
public:
widget(action *w_test);
}
widget.cpp
widgets::widgets(action *w_test)
{
displayTime= new QLineEdit();
displayTime->setText(QString::number(w_test->timetosend,10));
displayTC->setStyleSheet("color: blue; background-color: red");
}
main.cpp
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Action *test = new Action;
Thread *threadtest = new QThread;
test->moveToThread(threadtest);
QObject::connect(threadtest, SIGNAL(started()), test ,SLOT(doWork()));
widget *mainwindows = new widget(test);
mywindow->show();
threadtest->start();
return app.exec();
}
Instead using gettimeofday use QTime::currentTime then convert it to string (chose the format) and emit result. This signal should be connected to slot QLineEdit::setText.
Using thread is completely obsolete here.
In a program which calculates abritary precision numbers.
I have an action on the taskbar.
QAction* button_stop_continue.
I've set the icon green icon in the beginning of the program, when calculations are being executed it should turn red and so on.
I've already tried something like this:
connect(this, SIGNAL(startedComputing()), this, SLOT(turnIconRed()));
connect(this, SIGNAL(finishedComputing()), this, SLOT(turnIconGreen()));
the function turnIconRed is looking similar to this:
void turnIconRed()
{
button_stop_continue->setIcon(QIcon("images/red-light.png"));
}
I've come up with some incredibly-ugly algorithms :S. Isn't there a straight-forward way to deal with that on Qt? Any ideas?
Thanks.
I would subclass QAction and add some logic for the states in which it can be. It is never a good idea to hardcode the color of something into the name of a method. By subclassing QAction, the look and feel of it is encapsulated.
This could be something like this:
Header file:
class StateAction : public QAction
{
Q_OBJECT
public:
explicit StateAction(QObject *parent = 0);
public slots:
void start();
void stop();
void pause();
};
Implementation file:
StateAction::StateAction(QObject *parent) :
QAction(parent)
{
this->stop();
}
void StateAction::start()
{
this->setIcon(QIcon(":/states/start.png"));
}
void StateAction::stop()
{
this->setIcon(QIcon(":/states/stop.png"));
}
void StateAction::pause()
{
this->setIcon(QIcon(":/states/pause.png"));
}
Now, in your MainWindow you can use that custom QAction simply by connecting its slots to the right signals:
Header file:
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void startedComputing();
void finishedComputing();
void pausedComputing();
private:
void createActions();
void createToolbars();
void createConnections();
StateAction *m_stateAction;
};
Implementation file:
...
void MainWindow::createConnections()
{
connect(this, SIGNAL(startedComputing()), m_stateAction, SLOT(start()));
connect(this, SIGNAL(finishedComputing()), m_stateAction, SLOT(stop()));
connect(this, SIGNAL(pausedComputing()), m_stateAction, SLOT(pause()));
}
I've found a solution using QToolButton here it is:
Header : FenPrincipale.h
#ifndef FENPRINCIPALE_H
#define FENPRINCIPALE_H
#include <QWidget>
#include <QVBoxLayout>
#include <QToolButton>
#include <QToolBar>
#include <QAction>
#include <QTextEdit>
class FenPrincipale : public QWidget {
Q_OBJECT
public:
FenPrincipale();
private slots:
void goComputing();
void stopComputing();
private:
QAction* actionDemarrer; // Start computing
QAction* actionArreter; // Stop computing
QToolBar* toolBarActions;
QToolButton* boutonAction; // this button holds the appropriate action
QVBoxLayout* layoutPrincipale;
QTextEdit* resultat; // show result
};
...
Implementation : FenPrincipale.cpp
#include "FenPrincipale.h"
FenPrincipale::FenPrincipale() : QWidget()
{
this->setFixedSize(400, 200);
// create actions
actionDemarrer = new QAction(QIcon("bouton-vert.png"), "demarrer", this);
actionArreter = new QAction(QIcon("bouton-rouge.png"), "arreter", this);
boutonAction = new QToolButton;
boutonAction->setDefaultAction(actionDemarrer);
// create toolbar
toolBarActions = new QToolBar(this);
toolBarActions->addWidget(boutonAction);
// create result widget
resultat = new QTextEdit(this);
// create layout
layoutPrincipale = new QVBoxLayout(this);
layoutPrincipale->addWidget(toolBarActions);
layoutPrincipale->addWidget(resultat);
this->setLayout(layoutPrincipale);
// make connections
QObject::connect(actionDemarrer, SIGNAL(triggered()), this, SLOT(goComputing()));
QObject::connect(actionArreter, SIGNAL(triggered()), this, SLOT(stopComputing()));
}
void FenPrincipale::goComputing()
{
resultat->setText("Computing...");
boutonAction->setDefaultAction(actionArreter);
}
void FenPrincipale::stopComputing()
{
resultat->setText("Partial result : {?}");
boutonAction->setDefaultAction(actionDemarrer);
}
...
Main
#include <QApplication>
#include "FenPrincipale.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
FenPrincipale fenetre;
fenetre.show();
return app.exec();
}
I have created a library which has following interface and callback.
I wanted to Implent it using QT Signal and Slot.
Is is possible to replace IWifiCameraDiscovery with Signal and slot
class IWifiCameraDiscovery
{
public:
virtual int InitialiseWiFiDiscovery(IWifiCameraEnumerationCallback*) = 0;
virtual void UnInitialiseWiFiDiscovery() = 0;
virtual int EnumerateWiFiDevice() = 0;
};
class IWifiCameraEnumerationCallback
{
public:
virtual void onWiFiDeviceDiscovered( WiFiDeviceInfo* pDeviceInfo,unsigned short nNoOfDevice) = 0;
virtual void onDiscoveryTimeout() = 0;
};
Yes, in a quite straightforward way.
class IWifiCameraDiscovery
{
public:
virtual int InitialiseWiFiDiscovery() = 0;
virtual void UnInitialiseWiFiDiscovery() = 0;
virtual int EnumerateWiFiDevice() = 0;
signals:
void onWiFiDeviceDiscovered(WiFiDeviceInfo* pDeviceInfo, unsigned short nNoOfDevice);
void onDiscoveryTimeout();
};
In your implementation, instead of calling the callbacks directly:
callback.onWiFiDeviceDiscovered(pDevInfo, x);
You would emit a signal:
emit onWiFiDeviceDiscovered(pDevInfo, x);
And you would use QObject::connect to connect these signals to your actual receivers (slots) on the other end. Be aware that emitting a signal is more expensive than calling a virtual function.
try this simple example
#include <QApplication>
#include <QFont>
#include <QPushButton>
#include <QWidget>
class MyWidget : public QWidget
{
public:
MyWidget(QWidget *parent = 0);
};
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
setFixedSize(200, 120);
QPushButton *quit = new QPushButton(tr("Quit"), this);
quit->setGeometry(62, 40, 75, 30);
quit->setFont(QFont("Times", 18, QFont::Bold));
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
}
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
you can use like this
class IWifiCameraDiscovery
{
public slots:
void UnInitialiseWiFiDiscovery();
signals:
void EnumerateWiFiDevice();
}