Slots interrupting each other with just one Thread? - qt

I have a small example using Slots called by mousemovement and mousewheel.
Now i have the problem that when i zoom and move at the same time, first the onZoom-slot is called and before it is finished it is calling the onMouseMoved-slot. That causes the first slot to lock the mutex (in my original program used by another thread) and the second one to wait for it.
How can I prevent the slots to interrupt each other (and why are they doing it in first place since they are in same thread?).
I read something about using Qt::QueuedConnection but that causes an access violation exception.
main.cpp
#include "ppi.h"
#include <QtGui/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
PPI w;
w.show();
return a.exec();
}
ppi.h
#ifndef PPI_H
#define PPI_H
#include <QtGui/QMainWindow>
#include <QGraphicsView>
#include <QDebug>
#include <QWheelEvent>
#include <QgraphicsEllipseItem>
#include <QMouseEvent>
#include <QMutex>
#include <QThread>
#include <QGraphicsSceneMouseEvent>
//#include "ui_ppi.h"
class PPIView : public QGraphicsView
{
Q_OBJECT
public:
PPIView(QWidget * parent = 0)
: QGraphicsView(parent)
{};
~PPIView(){};
private slots:
void wheelEvent(QWheelEvent *event)
{emit zoom(event);};
signals:
void zoom(QWheelEvent *event);
};
class PPIScene : public QGraphicsScene
{
Q_OBJECT
public:
PPIScene(QObject *parent)
: QGraphicsScene(parent)
{};
~PPIScene(){};
private:
void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{emit mouseMoved(event);};
signals:
void mouseMoved(QGraphicsSceneMouseEvent *event);
};
class PPI : public QMainWindow
{
Q_OBJECT
public:
PPI(QWidget *parent = 0, Qt::WFlags flags = 0)
: QMainWindow(parent, flags)
{
//ui.setupUi(this);
//ppiScene is inherited from QGraphicsScene, overriding mouseMoveEvent so it emits mouseMoved();
ppiScene = new PPIScene(this);
gVPPI = new PPIView(this);
gVPPI->setMinimumSize(1024,1024);
gVPPI->show();
test = new QGraphicsEllipseItem(-10, -10, 20, 20);
ppiScene->addItem(test);
gVPPI->adjustSize();
connect(ppiScene, SIGNAL(mouseMoved(QGraphicsSceneMouseEvent*)), this, SLOT(onMouseMoved(QGraphicsSceneMouseEvent*)));
connect(gVPPI, SIGNAL(zoom(QWheelEvent*)), this, SLOT(onZoom(QWheelEvent*)));
//ui.gVPPI is inherited from QGraphicsView, overriding wheelEvent, so it emits zoom()
gVPPI->setScene(ppiScene);
gVPPI->setMouseTracking(true);
};
~PPI(){};
QMutex mutex;
private:
//Ui::ppiClass ui;
PPIScene* ppiScene;
PPIView *gVPPI;
QGraphicsEllipseItem *test;
protected slots:
void onZoom(QWheelEvent *event)
{
qDebug() << "Zoom lock" << QThread::currentThreadId();
mutex.lock();
qDebug() << "Zoom locked";
if(event->delta() > 0)
gVPPI->scale(1.01, 1.01);
else
gVPPI->scale(1/1.01, 1/1.01);
qDebug() << "Zoom unlock";
mutex.unlock();
qDebug() << "Zoom unlocked";
};
void onMouseMoved(QGraphicsSceneMouseEvent *event)
{
qDebug() << "Move lock" << QThread::currentThreadId();
mutex.lock();
qDebug() << "move locked";
test->setPos(test->pos()+event->scenePos()-event->lastScenePos());
qDebug() << "Move unlock";
mutex.unlock();
qDebug() << "Move unlocked";
};
};
#endif // PPI_H
Output qDebug():
Move lock 0x1514
move locked
Move unlock
Move unlocked
Move lock 0x1514
move locked
Move unlock
Move unlocked
Zoom lock 0x1514
Zoom locked
Move lock 0x1514

You can use QObject::blockSignals to block signals for specific object,
but I think you have wrong idea about how your code works.
There is one GUI thread, and if signals + slots in the same GUI thread,
as in your case, then they called in sequence order. And if PPI::onZoom will called in another thread context then you have problem here, because of usage of things like ui.gVPPI->scale in non GUI thread is not allowed and may cause crash on assert, or just crash, or randomly works, UB as it is.
The situation when you see that slot 1 was called, then before finish of slot 1 slot 2 is called is likely because of you call some function inside slot 1 that call another function etc and some function deep inside call signal 2, which emit call of slot 2, just set breakpoints in your debugger and findout what is going on.

It doesn't make sense to use any form of locking in a single GUI thread that doesn't cooperate with other threads. Everything in the GUI thread is already serialized for you. You're fighting an imaginary problem. As long as your code is executing, nothing else will execute behind your back in the same thread.
onZoom-slot is called and before it is finished it is calling the onMouseMoved-slot
This is false. Nothing of the sort happens in the code you show. Perhaps ui.gVPPI->scale() is reentering the event loop. You really need to show a self-contained example: your problem is in the code you don't show.
How can I prevent the slots to interrupt each other
It's already prevented for you. You need to do nothing.
in my original program used by another thread
Generally speaking, objects living in the GUI thread cannot have methods directly invoked from other threads.
Most of the time, throwing a second thread at a problem makes you end up with two problems. Properly designed non-blocking code will work correctly, if perhaps a bit slow, even when run in a single thread. That'd be your point of departure - you then move objects to other threads simply to spread the work around. Ideally, though, async processing should be done by running work asynchronously through QtConcurrent::run.

I managed to set up my debugger and the problem seems QGraphicsView::scale() is calling QgraphicsScene::mouseMoveEvent() deep inside directly. So I need to introduce a variable which tells the mouseMoveEvent, whether it was called from QGraphicsView::scale() or from physical mouse movement.
protected slots:
void onZoom(QWheelEvent *event)
{
qDebug() << "Zoom lock" << QThread::currentThreadId();
mutex.lock();
qDebug() << "Zoom locked";
scale = true;
if(event->delta() > 0)
gVPPI->scale(1.01, 1.01);
else
gVPPI->scale(1/1.01, 1/1.01);
scale = false;
qDebug() << "Zoom unlock";
mutex.unlock();
qDebug() << "Zoom unlocked";
};
void onMouseMoved(QGraphicsSceneMouseEvent *event)
{
if(scale == false)
{
qDebug() << "Move lock" << QThread::currentThreadId();
mutex.lock();
qDebug() << "move locked";
}
test->setPos(test->pos()+event->scenePos()-event->lastScenePos());
if(scale == false)
{
qDebug() << "Move unlock";
mutex.unlock();
qDebug() << "Move unlocked";
}
};

Related

In a Qt console application, why is a QTimer required for the code to exit properly?

I've wrote this code looking at examples online of how I'm supposed to run a console program that doesn't just run and quit and one that does. Based on a Qt console application. This one here, I wanted it to quit. I've understood pretty much everthing excepth the QTimer::singleShot line. If the line is commented out, the application will run but will not quit. If it is left, the application will run and quit as expected. Can anyone explain to me why?
dostuff.h
#ifndef DOSTUFF_H
#define DOSTUFF_H
#include <QObject>
#include <iostream>
class DoStuff: public QObject
{
Q_OBJECT
public :
DoStuff(QObject *parent = 0);
public slots:
void run();
signals:
void finished();
};
#endif // DOSTUFF_H
And the implementation dostuff.cpp
#include "dostuff.h"
DoStuff::DoStuff(QObject *parent):QObject(parent)
{
}
void DoStuff::run(){
for (int i = 0; i < 10000; i++){
std::cout << "Processing " << i << std::endl;
}
emit(finished());
}
My main.cpp
#include <QCoreApplication>
#include <QTimer>
#include "dostuff.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
DoStuff *dostuff = new DoStuff(&a);
QObject::connect(dostuff,SIGNAL(finished()),&a,SLOT(quit()));
dostuff->run();
// WHY THIS??
QTimer::singleShot(10,dostuff,SLOT(run()));
return a.exec();
}
QTimer is not required to exit properly; You just need to provide a way to get your application to break the event loop at some point. In GUI application, Qt does that automatically when the last window is closed.
In Console applications, you can:
Either run your application without an event loop (if you have a straight-forward simple control flow in your application).
Or (if you require an event loop to handle some events or cross thread signal/slots) you need to have some event that makes your application break the event loop and quit. This event should only be triggered when the application has finished its job.
The code sample you have in your question is really simple, and does not require an event loop to run properly. The only effect the QTimer has in your code is that it delays execution for 10 ms. Here is the same code sample without running an event loop:
#include <QtCore>
class DoStuff: public QObject
{
Q_OBJECT
public :
DoStuff(QObject *parent = 0) : QObject(parent) {}
public slots:
void run() {
for (int i = 0; i < 10000; i++){
qInfo() << "Processing " << i;
}
emit finished();
}
signals:
void finished();
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
DoStuff dostuff;
QObject::connect(&dostuff, &DoStuff::finished,
&a, &QCoreApplication::quit);
dostuff.run();
return 0; //no event loop required
}
#include "main.moc"
If you start an event loop, you may notice that the quit slot does not work when not using QTimer::singleShot. The reason for this is that quit is called before the event loop is even started (and the call has no effect at all). That's why according to the docs, it is recommended to connect to quit using a queued connection:
It's good practice to always connect signals to this slot using a QueuedConnection. If a signal connected (non-queued) to this slot is emitted before control enters the main event loop (such as before "int main" calls exec()), the slot has no effect and the application never exits. Using a queued connection ensures that the slot will not be invoked until after control enters the main event loop.
So, if you want to have an event loop in your code above, you just need to connect using a Qt::QueuedConnection:
#include <QtCore>
class DoStuff: public QObject
{
Q_OBJECT
public :
DoStuff(QObject *parent = 0) : QObject(parent) {}
public slots:
void run() {
for (int i = 0; i < 10000; i++){
qInfo() << "Processing " << i;
}
emit finished();
}
signals:
void finished();
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
DoStuff dostuff;
QObject::connect(&dostuff, &DoStuff::finished,
&a, &QCoreApplication::quit,
Qt::QueuedConnection);
// ^^^^^^^^^^^^^^^^
// use a queued connection
dostuff.run();
return a.exec(); //start an event loop
}
#include "main.moc"
Timer is needed to postpone execution. Since you want to have a running event loop, a.exec() has to be called, then the timer executes your code. When your code finishes running, it triggers finished signal, that is tied to QCoreApplication::quit - that's the needed exit for event loop running inside a.exec().
Btw, you have to remove: dostuff->run(); from your code.

Can't write to Qt5 textEdit box with ui->control->setText(message)

I am trying to put the data passed to a mainwindow.cpp function on the screen with the typical ui->control->setText(message) without success. The same line works if it is in a timer loop or a button function but not from display_that_data function
"MainWindow::display_that_data()" is called from myudp.cpp with the following lines
MainWindow show_tlm;
show_tlm.display_that_data(data_source, buf_copy);
mainwindow.cpp (updated to include emitting a signal for a SIGNAL/SLOT connection)
The SIGNAL/SLOT connection is set up in the constructor with the following line
connect (this, SIGNAL (showdata_signal()), this, SLOT(showdata_slot()));
void MainWindow::display_that_data(QByteArray data_source, QByteArray tlmBuf){
QString msg ;
msg = " in display_that_data";
qDebug() << msg ;
ui->tlm_vals->setText(msg);
//generate a signal which will trigger showdata_slot
emit showdata_signal();
msg = " in display_that_data after emit showdata_signal()";
qDebug() << msg ;
}
void MainWindow::showdata_slot() {
QString msg = "showdata_slot called";
qDebug() << msg ;
ui->tlm_vals->setText(msg);
}
Runtime debug messages show that code is making it to the showdata_slot but it is still not writing to the ui->tlm_vals
" in display_that_data"
"showdata_slot called"
" in display_that_data after emit showdata_signal()"
but.... neither one of the ui->tlm_vals->setText(msg) lines are putting text on the ui
"MainWindow::realtimeDataSlot()" is called by at timer timout signal as follows:
void MainWindow::setupRealtimeDataDemo(QCustomPlot *customPlot) {
// setup a timer that repeatedly calls MainWindow::realtimeDataSlot
connect(&dataTimer, SIGNAL(timeout()), this, SLOT(realtimeDataSlot()));
dataTimer.start(1000);
}
void MainWindow::realtimeDataSlot(){
QString temp = QString("%1").arg(epochTime, 10, 10, QChar('0'));
ui->tlm_vals->setText(temp);
}
And this works perfectly (of course I have to disable it to see if showdata_slot is writing to the ui)
I thought the problem was a needed SIGNAL and SLOT connection to trigger the write to the ui but generating a SIGNAL/SLOT connection (which debug shows as working) still does not write to the ui from the slot function.
For completeness mainwindow.h contains the following
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void setupRealtimeDataDemo(QCustomPlot *customPlot);
void display_that_data (QByteArray data_source, QByteArray tlmBuf);
private slots:
void realtimeDataSlot();
void showdata_slot();
private:
Ui::MainWindow *ui;
QTimer dataTimer;
What am I missing/doing wrong?
Somewhere deeply embedded in Qt there is a difference between gui mouse click generated event and code generated event and this somehow caues Qt behavior to vary with the same lines of code. I will repost a more more "root level" question on this topic.

Qt: Program crashes when it emits signals

I am using VTK and Qt, and I need to know, when which mouse-button is pressed or released.
That for I created a new class, which inherits QObject and vtkInteractorStyleTrackballCamera:
class CModelMouseInteractorStyle :
public vtkInteractorStyleTrackballCamera,
public QObject
{
public:
CModelMouseInteractorStyle();
virtual void OnLeftButtonDown()
{
std::cout << "Pressed left mouse button." << std::endl;
// Forward events
vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
// emit signal
emit leftButtonDown();
}
virtual void OnLeftButtonUp()
{
std::cout << "Released left mouse button." << std::endl;
// Forward events
vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
// emit signal
emit leftButtonUp();
}
// I have similar functions for right and middle mouse-button
...
signals:
void leftButtonDown();
void leftButtonUp();
// and similar signals, too
...
};
I get the right couts whenever a button is pressed/released and I can interact with my scene as I want to, but only as long as I don't emit any signals.
As soon as I emit a signal in on of the functions, I get a symbol lookup error and the whole program crashes.
Am I doing something wrong? Do I have forgotten any thing?
I am using Qt4.7.4 and Vtk5.8.

Qt SIGNAL and SLOT in hierarcy, not threads (yet)

OK, I'm a total beginner but I'm missing something here. Been all over the Qt documentation/examples and everything I can dig up through Google. All similar information is slightly different in context...
I'm just starting out with Qt SIGNALS and SLOTS, I'm successful with gui examples and within a class. Now I want to connect a SIGNAL in a child class with a SLOT in a sibling class with the Connect defined in the parent main. Ultimately my aim is to receive iamges in a class handling a QTcpSocket and emit the data as char* to be handled (saved or displayed) by another class.
For now I've just created the most basic version of the arrangement in a Console app as a learning exercise. I've got a sender class...
sender.h
#ifndef SENDER_H
#define SENDER_H
#include <QObject>
class sender : public QObject
{
Q_OBJECT
public:
sender(QObject *parent = 0);
~sender();
signals:
void output(int data);
public slots:
void test(int data);
private:
};
#endif // SENDER_H
sender.cpp
#include <iostream>
#include "sender.h"
sender::sender(QObject *parent)
: QObject(parent)
{
std::cout << "Created sender" << std::endl;
int stuff = 47;
std::cout << "stuff = " << stuff << std::endl;
connect(this, SIGNAL(output(int)), this, SLOT(test(int)));
emit output(stuff);
}
void sender::test(int data)
{
std::cout << "Got to test, data = " << data << std::endl;
}
sender::~sender()
{
std::cout << "Destroying sender" << std::endl;
}
...and a receiver class...
receiver.h
#ifndef RECEIVER_H
#define RECEIVER_H
#include <QObject>
class receiver : public QObject
{
Q_OBJECT
public:
receiver(QObject *parent = 0);
~receiver();
public slots:
void input (int data);
private:
};
#endif // RECEIVER_H
receiver.cpp
#include <iostream>
#include "receiver.h"
receiver::receiver(QObject *parent)
: QObject(parent)
{
std::cout << "Created receiver" << std::endl;
}
void receiver::input(int data)
{
std::cout << "Got data as = " << data << std::endl;
}
receiver::~receiver()
{
std::cout << "Destroying receiver" << std::endl;
}
My main looks like this...
main.cpp
#include <QtCore/QCoreApplication>
#include <iostream>
#include "sender.h"
#include "receiver.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
receiver myReceiver;
sender mySender;
if (QObject::connect(&mySender, SIGNAL(output(int)),
&myReceiver, SLOT(input(int))))
{
std::cout << "Got here so connect returned true" << std::endl;
}
return a.exec();
}
I've added the cout outputs and the sender::test function to try and figure out what's happening.
For me, this compiles cleanly and runs without any warnings or errors but while the sender::test SLOT gets called the receiver::input SLOT doesn't. The test on the connect in main returns true and neither sender or receiver are destroyed prematurely. Console output is...
Created receiver
Created sender
stuff = 47
Got to test, data = 47
Got here so connect returned true
So the SIGNAL is emitted, the SIGNAL and SLOT parameters match, I've got the Q_OBJECT macros in both sender.h and receiver.h, and both inherit from and #include QObject.
What's wrong???
P.S. I'm running 4.8.3 and IDE is VS2010 with Qt plugin.
The answer is quite simple: you are sending signal before you've connected it to the receiver and after you've connected it to itself. So your output is absolutely correct.
Do all emits only after everything has been connected. Here the instantiation of sender happens before sender and receiver are connected, and that's where the emit was done.

Cannot get QSystemTrayIcon to work correctly with activation reason

I am using Ubuntu 12.04 and, while I can create a tray icon with a usable menu, I cannot control its actions:
trayIcon = new QSystemTrayIcon(this);
trayIcon->setIcon(QIcon(":/icons/Pictures/icon.png"));
trayIcon->setToolTip(QString("Hello there..."));
connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),this,SLOT(clickSysTrayIcon(QSystemTrayIcon::ActivationReason)));
connect(this,SIGNAL(minimized()),this,SLOT(hide()),Qt::QueuedConnection);
QMenu *changer_menu = new QMenu;
Show_action = new QAction(tr("S&how"),this);
Show_action->setIconVisibleInMenu(true);
connect(Show_action, SIGNAL(triggered()), this, SLOT(showClicked()));
changer_menu->addAction(Show_action);
changer_menu->addSeparator();
Quit_action = new QAction(tr("&Quit"), this);
Quit_action->setIconVisibleInMenu(true);;
connect(Quit_action, SIGNAL(triggered()), this, SLOT(close_minimize()));
changer_menu->addAction(Quit_action);
trayIcon->setContextMenu(changer_menu);
trayIcon->show();
The clickSysTrayIcon(QSystemTrayIcon::ActivationReason) is the following:
void MainWindow::clickSysTrayIcon(QSystemTrayIcon::ActivationReason reason)
{
//reason is a variable that holds the type of activation or click done on the icon tray
qDebug() << "I'm in!";
}
and, defined at the header file as:
private Q_SLOTS:
void clickSysTrayIcon(QSystemTrayIcon::ActivationReason reason);
However, I cannot get the "I'm in!" message to be shown. I've tried to make it work with left/right clicks, with middle click and with mouse wheel, but I never see this message being outputed.
What is wrong?
EDIT: It seems that something's wrong with the specific system, Ubuntu 12.04, because it doesn't use tray icons any more and only indicators. So, there's a program which uses the tray icons and they convert them into indicators. But, then the features of indicators are gone. I know that it's the system to blame, because the same program, under the very same code, works perfectly under Lubuntu 12.04 with the LXDE desktop.
I blame Ubuntu for this. The sni-qt package doesn't do a very good migration from tray icons to indicators, providing that indicators can interact on click, on roller etc. It's a shame!
Any solutions to this problem?
My bounty ends, so if there's someone who can address the problem I would be thankful!
Bring up the issue to the people that have the most influence on the projects.
https://help.ubuntu.com/community/ReportingBugs#How_to_report_bugs
https://bugreports.qt.io/
Work-Around
I would make a floating frameless qwidget on top of the indicator area where your indicator gets painted, and then add the appropriate mouseEvent functions on to it.
Here is starting point for this style of work-around. I don't know how kosher this is, but it works pretty well in Windows. I know there are some UI tweaks and tools for Windows that use this style of layered elements, like DisplayFusion and TeamViewer. I haven't tested it in Ubuntu yet, but it should work the same way.
#include <QtGui/QWidget>
#include <QMenu>
#include <QSystemTrayIcon>
#include <QMouseEvent>
#include <QPixmap>
#include <QAction>
#include <QDebug>
#include <QPaintEvent>
#include <QPainter>
#include <QApplication>
#include <QTimerEvent>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0)
: QWidget(parent)
{
// setup this widget to be borderless, transparent around the image
// and always on top
// and not to have a presence in the "visible window list"
this->setWindowFlags( Qt::WindowStaysOnTopHint |
Qt::FramelessWindowHint | Qt::Tool);
this->setAttribute(Qt::WA_TranslucentBackground);
// necessary if you want to track when you enter and leave the widget's rect with the mouse
this->setMouseTracking(true);
m_trayIcon = new QSystemTrayIcon(this);
m_trayIcon->setIcon(QIcon("icon1.ico"));
m_trayIcon->setToolTip(QString("Hello there..."));
m_changer_menu = new QMenu;
m_show_action = new QAction(tr("S&how"),this);
m_show_action->setIconVisibleInMenu(true);
connect(m_show_action, SIGNAL(triggered()), this, SLOT(showClicked()));
m_changer_menu->addAction(m_show_action);
m_changer_menu->addSeparator();
m_quit_action = new QAction(tr("&Quit"), this);
m_quit_action->setIconVisibleInMenu(true);;
connect(m_quit_action, SIGNAL(triggered()), this, SLOT(close_minimize()));
m_changer_menu->addAction(m_quit_action);
m_trayIcon->setContextMenu(m_changer_menu);
m_trayIcon->show();
QPixmap p("icon2.ico");
m_pix = p.scaled(QSize(m_trayIcon->geometry().width(),
m_trayIcon->geometry().height()),
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
this->move(m_trayIcon->geometry().x() ,m_trayIcon->geometry().y());
this->resize(m_trayIcon->geometry().width(), m_trayIcon->geometry().height());
// qDebug() << m_trayIcon->geometry();
// qDebug() << this->geometry();
// This assumes that the notification is stationary. If you want it to move
// with the tray icon underneath, you will need to subclass QSystemTrayIcon
// and track its move and resize and probably also its show and hide events
// raise itself 15x a second
this->startTimer(1000/15);
}
~Widget(){ }
public slots:
void mouseDoubleClickEvent(QMouseEvent *)
{
qDebug() << Q_FUNC_INFO;
}
void mouseReleaseEvent(QMouseEvent * me)
{
qDebug() << Q_FUNC_INFO;
switch(me->button())
{
case Qt::LeftButton:
qDebug() << "Left Click";
break;
case Qt::RightButton:
qDebug() << "Right Click";
m_changer_menu->popup(this->geometry().topLeft() + me->pos());
break;
default:
qDebug() << "other click";
break;
}
}
void showClicked()
{
qDebug() << Q_FUNC_INFO;
}
void close_minimize()
{
qDebug() << Q_FUNC_INFO;
qApp->exit();
}
void paintEvent(QPaintEvent *)
{
QPainter aPainter(this);
aPainter.drawPixmap(rect(), m_pix);
}
void timerEvent(QTimerEvent *)
{
if(!m_changer_menu->isVisible())
this->raise();
}
private:
QPixmap m_pix;
QSystemTrayIcon * m_trayIcon;
QMenu * m_changer_menu;
QAction * m_quit_action;
QAction * m_show_action;
};
and here is the main function...
#include <QtGui/QApplication>
#include "widget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}

Resources