0

I have some experience with C++ but I'm a Qt beginner just for a few days. Look at my simple application code below, that is "main.cpp" which is only code file in the project. The problem is that when I try to run the application it returns me error that widgets must be created in the GUI thread. How to go around this ?. Is it possible to write this application that it works as I want without additional thread ?. If Yes then How ?. Please help. I can't get it working by myself.

#include <QApplication>
#include <QWidget>
#include <QBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QSpinBox>
#include <QSlider>
#include <QRadioButton>
#include <QFrame>
#include <QLCDNumber>
#include <QProgressBar>
#include "windows.h"

DWORD WINAPI trd1Entry(LPVOID lpParam) ;

int main(int argc, char **argv)
{
    QApplication app(argc, argv) ;
    QWidget *window = new QWidget() ;
    window->resize(500, 400) ;

    QHBoxLayout *layout0 = new QHBoxLayout() ;
    QGridLayout *layout1 = new QGridLayout() ;
    QVBoxLayout *layout2 = new QVBoxLayout() ;
    QVBoxLayout *layout3 = new QVBoxLayout() ;

    QSlider slider0(Qt::Horizontal), slider1(Qt::Horizontal) ;
    QLCDNumber lcd0, lcd1 ;
    QRadioButton rb0, rb1, rb2 ;
    QPushButton pb0("Reset"), pb1("Quit") ;
    QProgressBar progress0 ;
    QSpinBox spin0, spin1 ;

    spin0.setRange(-100, 100) ;
    spin1.setRange(-100, 100) ;
    slider0.setRange(-100, 100) ;
    slider1.setRange(-100, 100) ;

    rb0.setText("reset first") ;
    rb1.setText("reset second") ;
    rb2.setText("reset both") ;

    layout1->addWidget(&slider0, 0, 0) ;
    layout1->addWidget(&spin0, 0, 1) ;
    layout1->addWidget(&spin1, 1, 0) ;
    layout1->addWidget(&slider1, 1, 1) ;
    layout1->addWidget(&lcd0, 2, 0) ;
    layout1->addWidget(&lcd1, 2, 1) ;

    layout2->addWidget(&rb0) ;
    layout2->addWidget(&rb1) ;
    layout2->addWidget(&rb2) ;
    layout2->addWidget(&pb0) ;
    layout2->addWidget(&pb1) ;

    layout0->addLayout(layout1) ;
    layout0->addLayout(layout2) ;

    QFrame *frame = new QFrame() ;
    frame->setLayout(layout0) ;

    layout3->addWidget(frame) ;
    layout3->addWidget(&progress0) ;

    frame->setFrameShape(QFrame::Box) ;
    frame->setFrameShadow(QFrame::Raised) ;
    frame->setLineWidth(1) ;
    frame->move(10, 10) ;

    progress0.setRange(-200, 200) ;

    QObject::connect(&spin0, SIGNAL(valueChanged(int)), &slider0, SLOT(setValue(int))) ;
    QObject::connect(&spin1, SIGNAL(valueChanged(int)), &slider1, SLOT(setValue(int))) ;
    QObject::connect(&slider0, SIGNAL(valueChanged(int)), &spin0, SLOT(setValue(int))) ;
    QObject::connect(&slider1, SIGNAL(valueChanged(int)), &spin1, SLOT(setValue(int))) ;
    QObject::connect(&spin0, SIGNAL(valueChanged(int)), &lcd0, SLOT(display(int))) ;
    QObject::connect(&spin1, SIGNAL(valueChanged(int)), &lcd1, SLOT(display(int))) ;

    QObject::connect(&pb1, SIGNAL(clicked()), &app, SLOT(quit())) ;

    QObject *objs[3] = {&spin0, &spin1, &progress0} ;

    HANDLE trd1Handle = CreateThread(NULL, 0, trd1Entry, objs, 0, NULL) ;
    if(trd1Handle == NULL)
    ExitProcess(0) ;

    window->setLayout(layout3) ;

    window->show() ;
    return app.exec() ;
}

DWORD WINAPI trd1Entry(LPVOID lpParam)
{
    QObject **objs = static_cast<QObject**>(lpParam) ;
    QSpinBox *spin0 = static_cast<QSpinBox*>(objs[0]) ;
    QSpinBox *spin1 = static_cast<QSpinBox*>(objs[1]) ;
    QProgressBar *progress = static_cast<QProgressBar*>(objs[2]) ;
    HANDLE trd1Handle = GetStdHandle(STD_OUTPUT_HANDLE) ;
    if(trd1Handle == INVALID_HANDLE_VALUE)
    return -1 ;
    int total = 0 ;
    while(1)
    {
        total = spin0->value() + spin1->value() ;
        progress->setValue(total) ;
        Sleep(100) ;
    }
    return 0 ;
}
user1978386
  • 237
  • 8
  • 19
  • I want "progress0" to have value set to the sum of values of "spin0" nad "spin1" every time the "spin0" and/or "spin1" values are changed/set – user1978386 May 09 '13 at 20:59
  • use signal slots for such approach – Kamil Klimek May 10 '13 at 08:34
  • Thanks for suggestion. I thought that maybe it has somethiong to do with events but after some additional time spend on studying Qt signals and slots I know how to implement my own signals and slots and I succesfully resolved my own problem – user1978386 May 10 '13 at 11:27
  • I would advice you to go through whole tutorial available in Qt docs – Kamil Klimek May 13 '13 at 07:26

1 Answers1

2

Below is the code which fully explain and resolve my problem. If this is usefull for someone or You like the method I resolved the problem then please vote

main.cpp:

#include <QApplication>
#include <QWidget>
#include <QBoxLayout>
#include <QGridLayout>
#include <QPushButton>
#include <QSpinBox>
#include <QSlider>
#include <QRadioButton>
#include <QFrame>
#include <QLCDNumber>
#include <QProgressBar>
#include "qspinstransmit.h"

int main(int argc, char **argv)
{
    QApplication app(argc, argv) ;
    QWidget *window = new QWidget() ;
    window->resize(500, 400) ;

    QHBoxLayout *layout0 = new QHBoxLayout() ;
    QGridLayout *layout1 = new QGridLayout() ;
    QVBoxLayout *layout2 = new QVBoxLayout() ;
    QVBoxLayout *layout3 = new QVBoxLayout() ;

    QSlider slider0(Qt::Horizontal), slider1(Qt::Horizontal) ;
    QLCDNumber lcd0, lcd1 ;
    QRadioButton rb0, rb1, rb2 ;
    QPushButton pb0("Reset"), pb1("Quit") ;
    QProgressBar progress0 ;
    QSpinBox spin0, spin1 ;
    QSpinsTransmit *transmit = new QSpinsTransmit(&spin0, &spin1) ;

    spin0.setRange(-100, 100) ;
    spin1.setRange(-100, 100) ;
    slider0.setRange(-100, 100) ;
    slider1.setRange(-100, 100) ;

    rb0.setText("reset first") ;
    rb1.setText("reset second") ;
    rb2.setText("reset both") ;

    layout1->addWidget(&slider0, 0, 0) ;
    layout1->addWidget(&spin0, 0, 1) ;
    layout1->addWidget(&spin1, 1, 0) ;
    layout1->addWidget(&slider1, 1, 1) ;
    layout1->addWidget(&lcd0, 2, 0) ;
    layout1->addWidget(&lcd1, 2, 1) ;

    layout2->addWidget(&rb0) ;
    layout2->addWidget(&rb1) ;
    layout2->addWidget(&rb2) ;
    layout2->addWidget(&pb0) ;
    layout2->addWidget(&pb1) ;

    layout0->addLayout(layout1) ;
    layout0->addLayout(layout2) ;

    QFrame *frame = new QFrame() ;
    frame->setLayout(layout0) ;

    layout3->addWidget(frame) ;
    layout3->addWidget(&progress0) ;

    frame->setFrameShape(QFrame::Box) ;
    frame->setFrameShadow(QFrame::Raised) ;
    frame->setLineWidth(1) ;
    frame->move(10, 10) ;

    progress0.setRange(-200, 200) ;

    QObject::connect(&spin0, SIGNAL(valueChanged(int)), &slider0, SLOT(setValue(int))) ;
    QObject::connect(&spin1, SIGNAL(valueChanged(int)), &slider1, SLOT(setValue(int))) ;
    QObject::connect(&slider0, SIGNAL(valueChanged(int)), &spin0, SLOT(setValue(int))) ;
    QObject::connect(&slider1, SIGNAL(valueChanged(int)), &spin1, SLOT(setValue(int))) ;
    QObject::connect(&spin0, SIGNAL(valueChanged(int)), &lcd0, SLOT(display(int))) ;
    QObject::connect(&spin1, SIGNAL(valueChanged(int)), &lcd1, SLOT(display(int))) ;

    QObject::connect(&pb1, SIGNAL(clicked()), &app, SLOT(quit())) ;

    QObject::connect(transmit, SIGNAL(valueChanged(int)), &progress0, SLOT(setValue(int))) ;

    window->setLayout(layout3) ;

    window->show() ;
    return app.exec() ;
}

qspinstransmit.h:

#ifndef QSPINSTRANSMIT_H
#define QSPINSTRANSMIT_H

#include <QSpinBox>

class QSpinsTransmit: public QObject
{

    Q_OBJECT

    private:
    QSpinBox *spin0, *spin1 ;

    public:
    QSpinsTransmit(QSpinBox *spin0 = NULL, QSpinBox *spin1 = NULL) ;

    signals:
    void valueChanged(int) ;

    public slots:
    void valuesSum() ;
} ;

#endif // QSPINSTRANSMIT_H

qspinstransmit.cpp:

#include "qspinstransmit.h"

QSpinsTransmit::QSpinsTransmit(QSpinBox *spin0, QSpinBox *spin1)
{
    this->spin0 = spin0 ;
    this->spin1 = spin1 ;
    connect(spin0, SIGNAL(valueChanged(int)), SLOT(valuesSum())) ;
    connect(spin1, SIGNAL(valueChanged(int)), SLOT(valuesSum())) ;
}

void QSpinsTransmit::valuesSum()
{
    emit valueChanged(spin0->value() + spin1->value()) ;
}
user1978386
  • 237
  • 8
  • 19