Results 1 to 13 of 13

Thread: QSerialPort and QThread

  1. #1
    Join Date
    Apr 2017
    Posts
    30
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Windows

    Default QSerialPort and QThread

    Hi all!

    I have a small project:

    mainwindow.cpp
    Qt Code:
    1. MainWindow::MainWindow(QWidget *parent) :
    2. QMainWindow(parent),
    3. ui(new Ui::MainWindow)
    4. {
    5. ui->setupUi(this);
    6.  
    7. ComPort::get().open();
    8.  
    9. thread = new QThread(this);
    10. connect(this, SIGNAL(destroyed(QObject*)), thread, SLOT(quit()));
    11.  
    12. valve = new Valve(7);
    13. connect(valve, SIGNAL(remoteStatus(bool)), this, SLOT(remoteStatus(bool)));
    14.  
    15. valve->moveToThread(thread);
    16.  
    17.  
    18. QTimer *valvesReadTimer = new QTimer(this);
    19. connect(valvesReadTimer, SIGNAL(timeout()), valve, SLOT(getAllStates()));
    20. valvesReadTimer->start(1000);
    21.  
    22. connect(passform, SIGNAL(manualModeEmit(bool)),
    23. this, SLOT(manualMode(bool)));
    24.  
    25.  
    26. emergency = new EmergencyResetOfPressure();
    27. connect(emergency, SIGNAL(openValveSignal(int)), this, SLOT(openValve(int)));
    28. connect(emergency, SIGNAL(closeValveSignal(int)), this, SLOT(closeValve(int)));
    29. //emergency->start();
    30. emergency->moveToThread(emergency);
    31. emergency->start();
    32. thread->start();
    33.  
    34. initActionConnection();
    35.  
    36. }
    37.  
    38. MainWindow::~MainWindow()
    39. {
    40. delete ui;
    41. }
    42.  
    43. void MainWindow::valveSwitch(int id) //переключатель клапанов
    44. {
    45. if (valve->getState(id))
    46. closeValve(id);
    47. else
    48. openValve(id);
    49. }
    50.  
    51. void MainWindow::openValve(int id)
    52. {
    53. QString str = "Клапан №" + QString::number(id+1);
    54. valveButton[id]->setEnabled(false);
    55. if (valve->open(id)) {
    56. if (manualModeState)
    57. valveButton[id]->setEnabled(true);
    58. //valveButton[id]->setPalette(QPalette(Qt::green));
    59. //valveButton[id]->setStyleSheet(VALVE_OPEN_COLOR);
    60. QString style = QString(DEFAULT_STYLE_BUTTON) + QString(DEFAULT_BACKGROUND_BUTTON);
    61. valveButton[id]->setStyleSheet(style);
    62. ui->mainLabel->setText(str + " открыл! :)");
    63. }
    64. else {
    65. if (manualModeState)
    66. valveButton[id]->setEnabled(true);
    67. ui->mainLabel->setText("Не могу открыть " + str);
    68. remoteStatus(0);
    69. }
    70. }
    71. void MainWindow::closeValve(int id)
    72. {
    73. QString str = "Клапан №" + QString::number(id+1);
    74. valveButton[id]->setEnabled(false);
    75. if (valve->close(id)) {
    76. if (manualModeState)
    77. valveButton[id]->setEnabled(true);
    78. //valveButton[id]->setPalette(style()->standardPalette());
    79. valveButton[id]->setStyleSheet("");
    80. ui->mainLabel->setText(str + " закрыл! :)");
    81. }
    82. else {
    83. if (manualModeState)
    84. valveButton[id]->setEnabled(true);
    85. ui->mainLabel->setText("Не могу закрыть " + str);
    86. remoteStatus(0);
    87. }
    88. }
    89.  
    90. void MainWindow::pressureDrop() //Испытание по методу "Спад давления"
    91. {
    92. emergency->begin();
    93.  
    94. ui->mainLabel->setText("Испытание по методу \n Спад давления");
    95. }
    96.  
    97.  
    98. void MainWindow::initActionConnection()
    99. {
    100. //обработка нажатий на кнопки клапанов
    101. QSignalMapper* signalMapper = new QSignalMapper (this); //чтобы можно было обработать ф-ю с аргументом в Слоте
    102. for(int i = 0; i < 7; i++)
    103. signalMapper->setMapping(valveButton[i], i);
    104. for(int i = 0; i < 7; i++)
    105. connect(valveButton[i], SIGNAL(clicked()), signalMapper, SLOT(map()));
    106. connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(valveSwitch(int)));
    107.  
    108.  
    109. connect(ui->pressureTestButton, SIGNAL(clicked(bool)), this, SLOT(pressureDrop())); //опрессовка и испытание на прочность
    110.  
    111. }
    112.  
    113.  
    114. EmergencyResetOfPressure::EmergencyResetOfPressure(QObject *parent) : QThread(parent)
    115. {
    116.  
    117. }
    118.  
    119. EmergencyResetOfPressure::~EmergencyResetOfPressure()
    120. {
    121.  
    122. }
    123.  
    124. void EmergencyResetOfPressure::begin()
    125. {
    126. for (int i = 0; i<7; i++)
    127. {
    128. //sleep(1);
    129. emit openValveSignal(i);
    130. }
    131. for (int i = 0; i<7; i++)
    132. {
    133. //sleep(1);
    134. emit closeValveSignal(i);
    135. }
    136. }
    To copy to clipboard, switch view to plain text mode 

    File for working with valves and port (singleton class)
    Qt Code:
    1. class ComPort : public QObject { //класс синглтон
    2. Q_OBJECT
    3. private:
    4. QString portName;
    5. QSerialPort *serial;
    6. explicit ComPort(QObject *parent = 0);
    7. ~ComPort();
    8.  
    9. //защита от копирования
    10. ComPort(ComPort const&) = delete;
    11. ComPort& operator= (ComPort const&) = delete;
    12.  
    13. int timeoutCount = 0;
    14. int responseCount = 0;
    15.  
    16. public:
    17. QByteArray buffer;
    18. static ComPort& get()
    19. {
    20. static ComPort instance;
    21. return instance;
    22. }
    23.  
    24. void open();
    25. void close();
    26. QByteArray requestResponse(const QByteArray &data);
    27. void write(const QByteArray &data);
    28. bool crcCheck(const QByteArray &data);
    29. private slots:
    30. void readData();
    31. void handleError(QSerialPort::SerialPortError error);
    32. };
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. Valve::Valve(int size, QObject *parent) : QObject(parent) //конструктор
    2. {
    3. valveState.resize(size);
    4. for(int i = 0; i < size; i++)
    5. {
    6. valveState[i] = false;
    7. }
    8. }
    9.  
    10. Valve::~Valve() //деструктор
    11. {
    12.  
    13. }
    14.  
    15. bool Valve::open(int id)
    16. {
    17. arr.resize(7);
    18. arr[0] = 0xAB;
    19. arr[1] = 0x01;
    20. arr[2] = 0x02;
    21. arr[3] = 0x02;
    22. arr[4] = id+1;
    23. arr[5] = 0xFF;
    24. arr[6] = 0x00 - arr[1] - arr[2] - arr[3] - arr[4] - arr[5];
    25.  
    26. QByteArray response = ComPort::get().requestResponse(arr);
    27. if(response[0] == arr[0])
    28. {
    29. qDebug() << "клапан №: " << id+1 << " открыт!";
    30. valveState[id] = true;
    31.  
    32. emit remoteStatus(1);
    33. return 1;
    34. }
    35.  
    36. emit remoteStatus(0);
    37. return 0;
    38. }
    39.  
    40. bool Valve::close(int id)
    41. {
    42. arr.resize(7);
    43. arr[0] = 0xAB;
    44. arr[1] = 0x01;
    45. arr[2] = 0x02;
    46. arr[3] = 0x02;
    47. arr[4] = id+1;
    48. arr[5] = 0x00;
    49. arr[6] = 0x00 - arr[1] - arr[2] - arr[3] - arr[4] - arr[5];
    50.  
    51. QByteArray response = ComPort::get().requestResponse(arr);
    52. if(response[0] == arr[0])
    53. {
    54. qDebug() << "клапан №: " << id+1 << " закрыт!";
    55. valveState[id] = false;
    56.  
    57. emit remoteStatus(1);
    58. return 1;
    59. }
    60.  
    61. emit remoteStatus(0);
    62. return 0;
    63. }
    64.  
    65. /*****************************************
    66.  * Класс для работы с COM портом
    67.  * **************************************/
    68.  
    69. ComPort::ComPort(QObject *parent) : QObject(parent)
    70. {
    71. buffer = "";
    72. serial = new QSerialPort();
    73. connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError)));
    74. }
    75. ComPort::~ComPort()
    76. {
    77.  
    78. }
    79.  
    80. void ComPort::open()
    81. {
    82. if(serial->isOpen())
    83. close();
    84. if(portName != Config::get().getValue("COM/name").toString())
    85. {
    86. qDebug() << "Порт " << portName << "сменился на " << Config::get().getValue("COM/name").toString();
    87. portName = Config::get().getValue("COM/name").toString();
    88. }
    89. serial->setPortName(portName);
    90. if (serial->open(QIODevice::ReadWrite)) {
    91. if (serial->setBaudRate(QSerialPort::Baud115200)
    92. && serial->setFlowControl(QSerialPort::NoFlowControl)) {
    93.  
    94. qDebug() << "Порт открыт";
    95.  
    96. } else {
    97. //QMessageBox::critical(this, "Error", serial->errorString());
    98. qDebug() << QString(serial->errorString());
    99. serial->close();
    100.  
    101. }
    102. } else {
    103. //QMessageBox::critical(this, QObject::tr("Error"), serial->errorString());
    104.  
    105. }
    106. }
    107. QByteArray ComPort::requestResponse(const QByteArray &data)
    108. {
    109. QByteArray readBuf;
    110. qDebug() << "-------------------------";
    111. int attempts = 1;
    112. while (attempts <= REQATTEMPTS) { //3 попытки
    113. if (serial->isWritable())
    114. {
    115. serial->write(data);
    116. qDebug() << "Попытка № " << attempts;
    117. qDebug() << "Запрос: " << data.toHex();
    118. while (serial->waitForReadyRead(WAITFORREADY)) {
    119. readBuf += serial->readAll();
    120. if (crcCheck(readBuf) && data[2] == readBuf[2] ){ //если CRC и команда сошлись -- успех!
    121. qDebug() << "Ответ: " << readBuf.toHex();
    122. responseCount++;
    123. qDebug() << "Кол-во запросов: " << responseCount;
    124. qDebug() << "Кол-во таймаутов: " << timeoutCount;
    125. float percent = timeoutCount * 100;
    126. percent = percent / responseCount;
    127. qDebug() << "Процент косяков: " << QString::number(percent, 'f', 3) << "%";
    128. close();
    129. open();
    130. return readBuf;
    131. }
    132. }
    133. readBuf.clear();
    134. qDebug() << "Таймаут...";
    135. timeoutCount++;
    136. close();
    137. open();
    138. attempts++;
    139. }
    140. else
    141. {
    142. qDebug() << "Порт " << portName << " не пишется!";
    143. return 0;
    144. }
    145.  
    146. }
    147. // close();
    148. // open();
    149. return 0;
    150. }
    151.  
    152. void ComPort::close()
    153. {
    154. serial->close();
    155. qDebug() << "Порт закрыт";
    156. }
    157. void ComPort::write(const QByteArray &data)
    158. {
    159. serial->write(data);
    160. qDebug() << "Запрос: " << data.toHex();
    161. }
    162. void ComPort::readData()
    163. {
    164. buffer = serial->readAll();
    165. if (ComPort::get().crcCheck(buffer))
    166. {
    167. qDebug() << "Ответ: " << buffer.toHex();
    168. qDebug() << "---------------------------";
    169. }
    170. }
    171. void ComPort::handleError(QSerialPort::SerialPortError error)
    172. {
    173. if (error == QSerialPort::ResourceError) {
    174. ComPort::get().close();
    175. qDebug() << "что-то не так!";
    176. }
    177. }
    To copy to clipboard, switch view to plain text mode 

    While working, I get an error:
    QObject: Cannot create children for a parent that is in a different thread.
    (Parent is QSerialPort(0x197b7f8), parent's thread is QThread(0xc16e50), current thread is QThread(0x197c620)
    How can I get rid of this error?
    I hope for any help. Thanks!
    Last edited by maratk1n; 2nd May 2017 at 13:18.

  2. #2
    Join Date
    Apr 2017
    Posts
    30
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSerialPort and QThread

    getAllStates method:
    Qt Code:
    1. bool Valve::getAllStates()
    2. {
    3. arr.resize(5);
    4. arr[0] = 0xAB;
    5. arr[1] = 0x01;
    6. arr[2] = 0x00;
    7. arr[3] = 0x00;
    8. arr[4] = 0x00 - arr[1] - arr[2] - arr[3];
    9.  
    10. QByteArray response = ComPort::get().requestResponse(arr);
    11. if(response[0] == arr[0])
    12. {
    13. QBitArray bitStates(16); //8 на клапана, 8 на фиттинги
    14.  
    15. for (int i = 4; i<6; i++) // конвертируем 4й и 5й байты (HEX) в биты (BIN)
    16. for (int b = 0; b<8; b++)
    17. bitStates.setBit((i-4)*8+b, response.at(i)&(1<<b));
    18.  
    19. //qDebug() << bitStates;
    20.  
    21. for (int i = 0; i < valveState.size(); i++) //обновляем состояния клапанов
    22. valveState[i] = bitStates[i];
    23. for (uint i = 0; i < sizeof(fittingState); i++) //обновляем состояния фиттингов
    24. fittingState[i] = bitStates[i+8];
    25.  
    26. emit remoteStatus(1);
    27. return 1;
    28. }
    29.  
    30. emit remoteStatus(0);
    31. return 0;
    32. }
    To copy to clipboard, switch view to plain text mode 

  3. #3
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,710
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QSerialPort and QThread

    are you allocating objects in your ComPort class?
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  4. #4
    Join Date
    Apr 2017
    Posts
    30
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSerialPort and QThread

    Quote Originally Posted by high_flyer View Post
    are you allocating objects in your ComPort class?
    Only this, if you about this ...

    serial = new QSerialPort();
    Qt Code:
    1. ComPort::ComPort(QObject *parent) : QObject(parent)
    2. {
    3. buffer = "";
    4. serial = new QSerialPort();
    5. connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(handleError(QSerialPort::SerialPortError)));
    6. }
    To copy to clipboard, switch view to plain text mode 

  5. #5
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,489
    Thanks
    252
    Thanked 716 Times in 706 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: QSerialPort and QThread

    ComPort is statically allocated on the stack in your main thread, and the QSerialPort instance it allocates is also in the main thread. You are using it from the Valve thread, so probably in the internals of QSerialPort it is trying to allocate an instance of some QObject-based class for its use while reading. As the error message says, objects created in one thread can't allocate children in a different thread. Time for some re-design.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  6. #6
    Join Date
    Apr 2017
    Posts
    30
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSerialPort and QThread

    Quote Originally Posted by d_stranz View Post
    ComPort is statically allocated on the stack in your main thread, and the QSerialPort instance it allocates is also in the main thread. You are using it from the Valve thread, so probably in the internals of QSerialPort it is trying to allocate an instance of some QObject-based class for its use while reading. As the error message says, objects created in one thread can't allocate children in a different thread. Time for some re-design.
    Thanks for the answer!
    How can I create a single instance of a class to access it from different parts of the program? Not using a singleton ..

  7. #7
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,489
    Thanks
    252
    Thanked 716 Times in 706 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: QSerialPort and QThread

    Not using a singleton ..
    Well, as you have implemented it, ComPort -is- a Singleton. The problem is not the definition of the class as a single instance, it's that the variable contained within the class (QSerialPort) has to further allocate memory in order to do its business. Objects living in one thread can't allocate memory in another thread and that is what is happening in when you try to use your ComPort instance in the Valve thread..

    So I would take a step back and examine why you think you need a single-instance class in this case. Can't each thread have its own instance? If not, how could you use a single instance class along with signals and slots (which can communicate across threads) to accomplish the same purpose.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  8. #8
    Join Date
    Apr 2017
    Posts
    30
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSerialPort and QThread

    Quote Originally Posted by d_stranz View Post
    Well, as you have implemented it, ComPort -is- a Singleton. The problem is not the definition of the class as a single instance, it's that the variable contained within the class (QSerialPort) has to further allocate memory in order to do its business. Objects living in one thread can't allocate memory in another thread and that is what is happening in when you try to use your ComPort instance in the Valve thread..

    So I would take a step back and examine why you think you need a single-instance class in this case. Can't each thread have its own instance? If not, how could you use a single instance class along with signals and slots (which can communicate across threads) to accomplish the same purpose.
    I can make a regular class. But if I create several instances, I will create several instances of the port (QSerialPort). And this is not very good, as it seems to me

  9. #9
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,710
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QSerialPort and QThread

    You could also make your singleton allocate on the heap by changing the get() method:
    Qt Code:
    1. static ComPort* get()
    2. {
    3. static ComPort *instance = nullptr;
    4. if(!instance) {
    5. instance = new ComPort();
    6. }
    7. return instance;
    8. }
    To copy to clipboard, switch view to plain text mode 

    That wont solve any of your problems though.
    I don't think the problem is the fact you are allocating on the stack, just the fact they are not allocated in the same thread.
    You should move your ComPort instance to the thread where Valve is as well (for example).

    A side note:
    Your code is very thread unsafe.
    You have no protection against multiple threads creating race conditions on resources in your classes, this could lead to all kinds of weird behavior which is very hard to debug.
    Writing thread safe code needs very good planning and somewhat different thinking than non threaded code.
    moveToThread() should be done on objects that are as "specific" or as "closed" as possible, and if you need things allocated, it short be when needed and for as short time as possible.
    You should analyze what it is you really need done in another thread, and try to pack that in to an object of its own, without the whole machinery around it which is not needed during the work in the other thread.
    Or even better, ask your self if a threaded configuration is really necessary in your case, or if there are other, easier to maintain ways to do it.

    And as d_stranz said, globlas and singletons *usually* tend to point to a design error.
    Singletons and globals should be avoided as much as possible for many very strong and important reasons.
    Last edited by high_flyer; 5th May 2017 at 22:24.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  10. #10
    Join Date
    Apr 2017
    Posts
    30
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSerialPort and QThread

    Quote Originally Posted by high_flyer View Post
    You could also make your singleton allocate on the heap by changing the get() method:
    Qt Code:
    1. static ComPort& get()
    2. {
    3. static ComPort *instance = nullptr;
    4. if(!instance) {
    5. instance = new ComPort();
    6. }
    7. return instance;
    8. }
    To copy to clipboard, switch view to plain text mode 
    Error:
    Qt Code:
    1. D:\WorkWolder\Libraries\RSProtocol_COMport.h:91: ошибка: invalid initialization of reference of type 'ComPort&' from expression of type 'ComPort*'
    2. return instance;
    3. ^
    To copy to clipboard, switch view to plain text mode 

  11. #11
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,489
    Thanks
    252
    Thanked 716 Times in 706 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: QSerialPort and QThread

    Try to think about the code you are writing, don't just blindly copy it from the forum. high_flyer's code had a small typo. It should be "return *instance;", and you should know enough C++ to see that for yourself.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  12. The following user says thank you to d_stranz for this useful post:

    maratk1n (5th May 2017)

  13. #12
    Join Date
    Apr 2017
    Posts
    30
    Thanks
    9
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QSerialPort and QThread

    Quote Originally Posted by d_stranz View Post
    Try to think about the code you are writing, don't just blindly copy it from the forum. high_flyer's code had a small typo. It should be "return *instance;", and you should know enough C++ to see that for yourself.
    You are absolutely right... Thanks.
    Recently, I'm not myself, my head is spinning.

    This did not solve the problem. Apparently, it is necessary to do through signals and slots.

    P.S. I made a singleton to access a single instance of the port from anywhere in the program. I do not know how else to solve this problem.
    Last edited by maratk1n; 5th May 2017 at 16:36.

  14. #13
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,710
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: QSerialPort and QThread

    high_flyer's code had a small typo.
    Sorry about that. (can happen when you write code here and can't check with a compiler)
    The actual mistake i did was I forgot to change the return reference to a pointer, which I now edited.
    The solution d_stranz offered will work too of course, take your pick.

    This did not solve the problem.
    I told you it wont, I just showed how the allocation on stack vs heap can be solved, its not your problem.
    The problem as d_stranz pointed out is the fact that the QSerialPort() is allocated in the main thread and in turn it allocates stuff further while parenting, and this allocation is taking place in your valve thread causing the serialport to be a parent from a different thread to the object it allocates.

    P.S. I made a singleton to access a single instance of the port from anywhere in the program. I do not know how else to solve this problem.
    That is not what singletons are for.
    Singletons are to FORCE only one instance of an object in the system, or forbid multiple instance of that object.
    Just accessing the same instance does not require a singleton.
    Simply create the object and make it available where you need it.

    As I already suggested in my previous post, one way you maybe be able to get rid of the error is to move the ComPort object to the thread that uses it.
    This wont help you however if you are using it from more than one thread.
    Alternatively you could fully initialize it before you make it available to the worker threads - please note, that I don't know if any operations you call on the serialport might cause it to allocate stuff again, in which case this wont help you either.

    It also looks strange that on one hand you have a singleton - and on the other hand you want to use it in multiple threads.
    This by definition will lead to procedural behavior (well in your case it will lead to undefined behavior since you are not mutexing anything) so the advantage of using threads is fully lost.

    I would dare to say that you simply don't need threads in this case.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

Similar Threads

  1. QSerialPort
    By fmarques in forum Qt Programming
    Replies: 0
    Last Post: 20th April 2016, 16:04
  2. QserialPort
    By arturs in forum Newbie
    Replies: 0
    Last Post: 13th May 2015, 20:37
  3. Qserialport issue in QT4
    By coss_cat in forum Qt Programming
    Replies: 3
    Last Post: 11th December 2013, 18:11
  4. QSerialport in multithread
    By snow_starzz in forum Newbie
    Replies: 3
    Last Post: 3rd December 2013, 10:18
  5. Replies: 1
    Last Post: 4th October 2012, 14:49

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.