Inheriting QSerialPort - c++

Perhaps a rather silly and newbie question but I have been struggling with keeping my QSerialPort serial; being used within the entirety of the application I am making. (Ughh this is frustrating to explain)
To be more clear I have the aforementioned QSerialPort serial; established in my MainWindow.cpp, but as I transition to another form which has a different class (for exampleoperations.cpp) I am unsure on how to keep and use my serial.* functions. My mainwindow.cpp form is just a connection settings form which allow you choose the port, baud rate, data bits, parity, etc to be set and once I press my "Open Connection" button, I have the form hidden(this->hide();) and the operations.cpp form appear.
Any clues on what should I do?
---
I had attempted to use Parent-Child relationship with the classes however, it only started a new QSerialPort serial; and the connect was lost.

You should factor out a separate QObject class that performs communications, and connect other classes to it.
A well designed system will never have a UI class own and use a serial port directly. See e.g. this answer for an idea how to separate the communications and the UI.
Let's see what transformations you could do to your code. At present you might have something similar to the below:
// https://github.com/KubaO/stackoverflown/tree/master/questions/serial-owner-41715726
#include <QtWidgets>
#include <QtSerialPort>
class Operations1 : public QWidget {
Q_OBJECT
QVBoxLayout m_layout{this};
QPushButton m_send{"Send"};
QPointer<QSerialPort> m_serial;
public:
Operations1() {
m_layout.addWidget(&m_send);
connect(&m_send, &QPushButton::clicked, this, &Operations1::sendRequest);
}
void sendRequest() {
QByteArray request;
QDataStream ds(&request, QIODevice::WriteOnly);
ds << qint32(44);
m_serial->write(request);
}
void setSerial(QSerialPort * port) {
m_serial = port;
}
};
class MainWindow1 : public QWidget {
Q_OBJECT
QVBoxLayout m_layout{this};
QPushButton m_open{"Open"};
QSerialPort m_serial;
QScopedPointer<Operations1> m_operations;
Operations1 * operations() {
if (!m_operations)
m_operations.reset(new Operations1);
return m_operations.data();
}
public:
MainWindow1() {
m_layout.addWidget(&m_open);
connect(&m_open, &QPushButton::clicked, this, &MainWindow1::open);
}
void open() {
m_serial.setBaudRate(38400);
m_serial.setPortName("/dev/tty.usbserial-PX9A3C3B");
if (!m_serial.open(QIODevice::ReadWrite))
return;
operations()->show();
operations()->setSerial(&m_serial);
}
};
int main1(int argc, char ** argv) {
QApplication app{argc, argv};
MainWindow1 ui;
ui.show();
return app.exec();
}
The serial-port using functionality is spread across the UI classes, coupling them very tightly with the port. Let's fix that by factoring out the port operations:
class Controller2 : public QObject {
Q_OBJECT
QSerialPort m_port;
public:
Controller2(QObject * parent = nullptr) : QObject{parent} {
connect(&m_port, &QIODevice::bytesWritten, this, [this]{
if (m_port.bytesToWrite() == 0)
emit allDataSent();
});
}
Q_SLOT void open() {
m_port.setBaudRate(38400);
m_port.setPortName("/dev/tty.usbserial-PX9A3C3B");
if (!m_port.open(QIODevice::ReadWrite))
return;
emit opened();
}
Q_SIGNAL void opened();
Q_SLOT void sendRequest() {
QByteArray request;
QDataStream ds(&request, QIODevice::WriteOnly);
ds << qint32(44);
m_port.write(request);
}
Q_SIGNAL void allDataSent();
};
class Operations2 : public QWidget {
Q_OBJECT
QVBoxLayout m_layout{this};
QPushButton m_send{"Send"};
QPointer<Controller2> m_ctl;
public:
Operations2(Controller2 * ctl, QWidget * parent = nullptr) :
QWidget{parent},
m_ctl{ctl}
{
m_layout.addWidget(&m_send);
connect(&m_send, &QPushButton::clicked, m_ctl, &Controller2::sendRequest);
}
};
class MainWindow2 : public QWidget {
Q_OBJECT
QVBoxLayout m_layout{this};
QPushButton m_open{"Open"};
QPointer<Controller2> m_ctl;
QScopedPointer<Operations2> m_operations;
Operations2 * operations() {
if (!m_operations)
m_operations.reset(new Operations2{m_ctl});
return m_operations.data();
}
public:
MainWindow2(Controller2 * ctl, QWidget * parent = nullptr) :
QWidget{parent},
m_ctl{ctl}
{
m_layout.addWidget(&m_open);
connect(&m_open, &QPushButton::clicked, m_ctl, &Controller2::open);
connect(m_ctl, &Controller2::opened, this, [this]{
operations()->show();
});
}
};
int main2(int argc, char ** argv) {
QApplication app{argc, argv};
Controller2 controller;
MainWindow2 ui(&controller);
ui.show();
return app.exec();
}
Finally, if you're tired of passing the controller around explicitly, we can implement a method akin to QCoreApplication::instance to get access to the unique controller instance:
class Controller3 : public QObject {
Q_OBJECT
QSerialPort m_port;
static Controller3 * instance(bool assign, Controller3 * newInstance = nullptr) {
static Controller3 * instance;
if (assign)
instance = newInstance;
return instance;
}
public:
Controller3(QObject * parent = nullptr) : QObject{parent} {
connect(&m_port, &QIODevice::bytesWritten, this, [this]{
if (m_port.bytesToWrite() == 0)
emit allDataSent();
});
instance(true, this);
}
~Controller3() {
instance(true);
}
Q_SLOT void open() {
m_port.setBaudRate(38400);
m_port.setPortName("/dev/tty.usbserial-PX9A3C3B");
if (!m_port.open(QIODevice::ReadWrite))
return;
emit opened();
}
Q_SIGNAL void opened();
Q_SLOT void sendRequest() {
QByteArray request;
QDataStream ds(&request, QIODevice::WriteOnly);
ds << qint32(44);
m_port.write(request);
}
Q_SIGNAL void allDataSent();
static Controller3 * instance() {
return instance(false);
}
};
class Operations3 : public QWidget {
Q_OBJECT
QVBoxLayout m_layout{this};
QPushButton m_send{"Send"};
public:
Operations3(QWidget * parent = nullptr) : QWidget{parent}
{
m_layout.addWidget(&m_send);
connect(&m_send, &QPushButton::clicked, Controller3::instance(), &Controller3::sendRequest);
}
};
class MainWindow3 : public QWidget {
Q_OBJECT
QVBoxLayout m_layout{this};
QPushButton m_open{"Open"};
QScopedPointer<Operations3> m_operations;
Operations3 * operations() {
if (!m_operations)
m_operations.reset(new Operations3);
return m_operations.data();
}
public:
MainWindow3(QWidget * parent = nullptr) : QWidget{parent}
{
m_layout.addWidget(&m_open);
connect(&m_open, &QPushButton::clicked, Controller3::instance(), &Controller3::open);
connect(Controller3::instance(), &Controller3::opened, this, [this]{
operations()->show();
});
}
};
int main3(int argc, char ** argv) {
QApplication app{argc, argv};
Controller3 controller;
MainWindow3 ui;
ui.show();
return app.exec();
}

Related

Qt multi-threaded display synchronization problem

We developed an image processing and display program based on Qt. We use sub-threads for image processing and the main thread as UI display. In order to display synchronization, we use the Qt::BlockingQueuedConnection parameter when connecting the signal-slot. There are other threads that may overwrite the image data, so we use locks.
code show as below:
class ProcessThread : public QThread
{
Q_OBJECT
public:
ProcessThread(QObject *parent = nullptr);
void run() override
{
int i=0;
while (1)
{
if(isQuit)break;
mutex.lock();
QString filename=QString("/home/%1.bmp").arg((i++)%2000);
data=imread(filename.toStdString());
//dosomthing...
emit processCompleted(&data);
mutex.unlock();
}
}
void setIsQuit(bool v){isQuit=v;}
signals:
void processCompleted(const Mat *data);
private:
bool isQuit=false;
Mat data;
QMutex mutex;
};
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr): QWidget(parent)
{
thread=new ProcessThread();
connect(thread,SIGNAL(processCompleted(const Mat *)),
this,SLOT(processCompleted(const Mat *)),Qt::BlockingQueuedConnection);
thread->start();
}
~Widget()
{
thread->setIsQuit(true);
thread->quit();
thread->wait();
delete thread;
}
void paintEvent(QPaintEvent *event) override
{
Q_UNUSED(event)
QPainter p(this);
p.drawImage(QPoint(0,0),image);
}
private slots:
void processCompleted(const Mat *data)
{
if(data!=nullptr)
{
if(data->channels()==1)
{
image=QImage(data->data,
data->cols,
data->rows,
data->step,
QImage::Format_Grayscale8);
}
else
{
image=QImage(data->data,
data->cols,
data->rows,
data->step,
QImage::Format_RGB888);
}
}
else
{
image=QImage();
}
repaint();
}
private:
QImage image;
ProcessThread *thread;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
When I exit the program, it will be stuck in thread->wait() in the ~Widget() function; it cannot continue to execute;
If I comment out thread->wait(); it will not get stuck when exiting, but it will prompt: "QMutex: destroying locked mutex" and "QThread: Destroyed while thread is still running" errors;
If the Qt::BlockingQueuedConnection parameter is not used when connecting the signal-slot, the first problem above will not occur, but the display will not be synchronized.
We need to display synchronization, how can we do that? Thanks!

How to manage mainwindow from QThread in Qt

My problem is the following one: I have 2 classes (mainwindow and mythread), I run the thread from the mainwindow and I would like to display some QLabel of my mainwindow from mythread :
mythread.cpp :
void mythread::run()
{
while(1)
{
this->read();
}
}
void mythread::read()
{
RF_Power_Control(&MonLecteur, TRUE, 0);
status = ISO14443_3_A_PollCard(&MonLecteur, atq, sak, uid, &uid_len);
if (status != 0){
//display Qlabel in mainwindow
}
}
mainwindow.cpp :
_thread = new mythread();
_thread->start();
You should use Qt's signal/slot mechanism. The thread will emit a signal, that new data has been read. Any interested object can connect to that signal, and perform actions depending on it.
This also works across thread-boundaries, as in your example. In Qt, it is required that only the main-thread interacts with UI elements.
Here is an outline:
// Your mainwindow:
class MyWindow : public QMainWindow {
Q_OBJECT
// as needed
private slots:
void setLabel(const QString &t) { m_label->setText(t); }
};
// Your thread
class MyThread: public QThread {
Q_OBJECT
// as needed
signals:
void statusUpdated(const QString &t);
};
// in your loop
if (status != 0) {
emit statusUpdated("New Status!");
}
// in your mainwindow
_thread = new MyThread;
connect(_thread, &MyThread::statusUpdated, this, &MyWindow::setLabel);
_thread->start();

Expand cursor length QLineEdit?

I'd like to take a normal QLineEdit, and change the shape of the cursor. So with a subclass like so:
class myLineEdit : public QLineEdit
{
Q_OBJECT
signals:
public:
explicit myLineEdit(QWidget * parent = 0)
{
}
protected:
};
And make it so that the cursor is several pixels wide, like that of a Linux terminal. By default, the cursor to indicate text position is very slim.
I assume I need to override something in the paintevent()? What exactly in the paintevent would be responsible for drawing the single pixel blinking line QLineEdit() defaults to? I could not find this information in the documentation.
Use a Qproxystyle:
#include <QtWidgets>
class LineEditStyle: public QProxyStyle
{
Q_OBJECT
Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth)
public:
using QProxyStyle::QProxyStyle;
int cursorWidth() const{
if(m_cursor_width < 0)
return baseStyle()->pixelMetric(PM_TextCursorWidth);
return pixelMetric(PM_TextCursorWidth);
}
void setCursorWidth(int cursorWidth){
m_cursor_width = cursorWidth;
}
int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const override
{
if(metric == PM_TextCursorWidth)
if(m_cursor_width > 0)
return m_cursor_width;
return QProxyStyle::pixelMetric(metric, option, widget);
}
private:
int m_cursor_width = -1;
};
class LineEdit: public QLineEdit
{
Q_OBJECT
public:
LineEdit(QWidget *parent = nullptr):
QLineEdit(parent)
{
LineEditStyle *new_style = new LineEditStyle(style());
new_style->setCursorWidth(10);
setStyle(new_style);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
LineEdit w;
w.show();
return a.exec();
}
#include "main.moc"

Qt Qml connect to a signal of a QObject property of a Context Property

So this may seem like a strange setup. I have a C++ object that inherits from QObject called "MasterGuiLogic" for simplicity. It is created with a pointer to another object called "MainEventBroker" which as you might guess handles all of my applications events. The MasterGuiLogic object is registered with qml as a context property so that it's properties can be used anywhere in my qml. So main.cpp looks like this:
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
MasterEventBroker *MainEventBroker = new MasterEventBroker();
MasterGuiLogic *MainGuiLogic = new MasterGuiLogic(*MainEventBroker);
qmlRegisterUncreatableType<MasterGuiLogic>("GrblCom", 1, 0, "MasterGuiLogic", "");
qmlRegisterUncreatableType<GuiLogic_SerialCom>("GrblCom", 1, 0, "GuiLogic_SerialCom", "");
QQmlApplicationEngine engine;
QQmlContext* context = engine.rootContext();
context->setContextProperty("MasterGuiLogic", &(*MainGuiLogic));
engine.load(QUrl(QLatin1String("qrc:/QmlGui/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
MasterGuiLogic creates an instance of another class called SerialCom, which is set as a Q_PROPERTY so that it's properties and public slots can be reached in qml through the MasterGuiLogic property.
MasterGuiLogic.h:
class MasterGuiLogic : public QObject
{
Q_OBJECT
Q_PROPERTY(GuiLogic_SerialCom* serialCom READ serialCom CONSTANT)
public:
MasterEventBroker *eventBroker;
explicit MasterGuiLogic(MasterEventBroker &ev, QObject *parent = nullptr);
GuiLogic_SerialCom* serialCom() const {
return Gui_SerialCom;
}
private:
GuiLogic_SerialCom *Gui_SerialCom;
MasterGuiLogic.cpp:
MasterGuiLogic::MasterGuiLogic(MasterEventBroker &ev, QObject *parent) : QObject(parent)
{
this->eventBroker = &ev;
this->Gui_SerialCom = new GuiLogic_SerialCom(this);
}
SerialCom.h:
//Forward Declare our parent
class MasterGuiLogic;
class GuiLogic_SerialCom : public QObject
{
Q_OBJECT
Q_PROPERTY(QStringList portNames READ portNames NOTIFY portNamesChanged)
Q_PROPERTY(bool connectedToPort READ connectedToPort NOTIFY connectedToPortChanged)
public:
MasterGuiLogic *parent;
explicit GuiLogic_SerialCom(MasterGuiLogic *parent = nullptr);
std::map<QString, QSerialPortInfo> portsMap;
QStringList portNames() {
return _portNames;
}
bool connectedToPort() {
return _connectedToPort;
}
private:
QStringList _portNames;
bool _connectedToPort = false;
signals:
void portNamesChanged(const QStringList &);
void connectedToPortChanged(const bool &);
public slots:
void connectToPort(const QString portName);
void disconnectFromPort(const QString portName);
};
SerialCom.cpp:
GuiLogic_SerialCom::GuiLogic_SerialCom(MasterGuiLogic *parent) : QObject(qobject_cast<QObject *>(parent))
{
this->parent = parent;
QList<QSerialPortInfo> allPorts = QSerialPortInfo::availablePorts();
for (int i = 0; i < allPorts.size(); ++i) {
this->_portNames.append(allPorts.at(i).portName());
this->portsMap[allPorts.at(i).portName()] = allPorts.at(i);
}
emit portNamesChanged(_portNames);
}
void GuiLogic_SerialCom::connectToPort(const QString portName) {
//TODO: Connect To Port Logic Here;
//Set Connected
this->_connectedToPort = true;
emit connectedToPortChanged(this->_connectedToPort);
qDebug() << portName;
}
void GuiLogic_SerialCom::disconnectFromPort(const QString portName) {
//TODO: DisConnect To Port Logic Here;
//Set DisConnected
this->_connectedToPort = false;
emit connectedToPortChanged(this->_connectedToPort);
qDebug() << portName;
}
So from qml it's pretty easy to read any of these properties and even send signals from qml to c++
For example, this works just fine:
connectCom.onClicked: {
if (MasterGuiLogic.serialCom.connectedToPort === false) {
MasterGuiLogic.serialCom.connectToPort(comPort.currentText);
} else {
MasterGuiLogic.serialCom.disconnectFromPort(comPort.currentText);
}
}
The problem is, I can't seem to find a way to connect to signals that are emitted from SerialCom. I thought I would be able to do something like this:
Connections: {
target: MasterGuiLogic.serialCom;
onConnectedToPortChanged: {
if (MasterGuiLogic.serialCom.connectedToPort === false) {
connectCom.text = "Disconnect";
comPort.enabled = false;
} else {
connectCom.text = "Connect";
comPort.enabled = true;
}
}
}
This should listen to the boolean property on SerialCom to change, but I get the following error:
QQmlApplicationEngine failed to load component
qrc:/QmlGui/main.qml:21 Type Page1 unavailable
qrc:/QmlGui/Page1.qml:49 Invalid attached object assignment
This just means that I can't "connect" using the target line above. Is there any other way I can connect to signals from a Q_PROPERTY of type QObject inside a ContextProperty?
First of all what should &(*MainGuiLogic) mean?
You are dereferencing and referencing again the MainGuiLogic? Why?
context->setContextProperty("MasterGuiLogic", MainGuiLogic); will be enought.
But registering MasterGuiLogic as Type and adding the Object named MasterGuiLogic can overide themself in QML world.
Set it like context->setContextProperty("MyGuiLogic", MainGuiLogic); to eleminate this behavior.
Also don't pass references between C++ and QML worlds like:
void connectedToPortChanged(**const bool &**);.
Just use atomic type and values (const bool);
and give it a name, to be able to use it as named value in QML:
void connectedToPortChanged(bool connected)
Here is an example with the structure like yours, which works. Just click in window and look in output console.
test.h:
#ifndef TEST_H
#define TEST_H
#include <QObject>
class GuiLogic_SerialCom : public QObject
{
Q_OBJECT
public:
GuiLogic_SerialCom(){}
signals:
void connectedToPortChanged(bool connected);
public slots:
void connectToPort(const QString & portName);
};
class MasterGuiLogic : public QObject
{
Q_OBJECT
public:
MasterGuiLogic();
Q_PROPERTY(GuiLogic_SerialCom * serialCom READ serialCom CONSTANT)
GuiLogic_SerialCom* serialCom() const {return test;}
Q_INVOKABLE void generate_signal();
private:
GuiLogic_SerialCom * test;
};
#endif // TEST_H
test.cpp:
#include "test.h"
#include <QDebug>
MasterGuiLogic::MasterGuiLogic()
{
this->test = new GuiLogic_SerialCom();
}
void MasterGuiLogic::generate_signal()
{
qDebug() << __FUNCTION__ << "Calling serialcom to gen signal";
this->test->connectToPort("88");
}
void GuiLogic_SerialCom::connectToPort(const QString &portName)
{
qDebug() << __FUNCTION__ << "got signal" << portName;
emit this->connectedToPortChanged(true);
}
main.cpp:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "test.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterUncreatableType<MasterGuiLogic>("GrblCom", 1, 0, "MasterGuiLogic", "");
qmlRegisterUncreatableType<GuiLogic_SerialCom>("GrblCom", 1, 0, "GuiLogic_SerialCom", "");
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty(QStringLiteral("Test"), new MasterGuiLogic());
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
main.qml:
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3
import GrblCom 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
MouseArea
{
anchors.fill: parent
onClicked:
{
Test.generate_signal();
}
}
Connections
{
target: Test.serialCom
onConnectedToPortChanged:
{
console.log("Got signal from SerialCom in QML. passed bool value is: " + connected);
}
}
}
Ok, I found the problem... The provided answers, while indeed helpful for other reasons, were not the correct solution. After going over the code by #Xplatforms, I couldn't figure out what the difference was between what I was doing and what he did.... until I saw this in my own code:
Connections: {
target: MasterGuiLogic.serialCom;
onConnectedToPortChanged: {
...
}
}
There isn't supposed to be a colon(:) there...
Connections {
target: MasterGuiLogic.serialCom;
onConnectedToPortChanged: {
...
}
}
Never try programming while sleepy...lol

Thread executed only once

I try to implement this: when app is started I need to create multiple threads that would use the same QDialog window to get messages from user. When thread is started, it asks user for input and if button OK pressed, it prints the message to console. I can't figure out why but I get dialog window only once and after that it prints my one message to console and application finishes.
Here's how I describe dialog window:
#include <QtWidgets>
class MyDialog : public QDialog
{
Q_OBJECT
public:
QWaitCondition* condition;
explicit MyDialog(QWidget *parent = 0);
signals:
void got_message(QString);
public slots:
void show_message_input();
void show_message();
private:
QLabel* message_label;
QVBoxLayout* vbox;
QHBoxLayout* hbox;
QLineEdit* message_input;
QDialogButtonBox* dialog_buttons;
};
MyDialog::MyDialog(QWidget *parent) : QDialog(parent)
{
setModal(true);
message_label = new QLabel("Message");
message_input = new QLineEdit();
dialog_buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
hbox = new QHBoxLayout();
hbox->addWidget(message_label);
hbox->addWidget(message_input);
vbox = new QVBoxLayout();
vbox->addLayout(hbox);
vbox->addWidget(dialog_buttons);
setLayout(vbox);
connect(dialog_buttons, SIGNAL(accepted()), this, SLOT(accept()));
connect(dialog_buttons, SIGNAL(rejected()), this, SLOT(reject()));
condition = new QWaitCondition();
}
void MyDialog::show_message_input()
{
int result = this->exec();
if (result == QDialog::Accepted)
{
emit got_message(message_input->text());
condition->wakeAll();
}
}
Here's MyThread class:
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(int id, MyDialog* window, QObject *parent = 0);
signals:
void show_input();
public slots:
void print_message(QString);
private:
static QMutex mutex;
static QMutex mutex2;
MyDialog* window;
int id;
void run();
void get_captcha_value();
};
QMutex MyThread::mutex;
QMutex MyThread::mutex2;
MyThread::MyThread(int id, MyDialog* window, QObject *parent) :
QThread(parent)
{
this->id = id;
this->window = window;
connect(this, SIGNAL(show_input()), this->window, SLOT(show_message_input()));
}
void MyThread::get_captcha_value()
{
QMutexLocker lock(&mutex);
connect(this->window, SIGNAL(got_message(QString)), SLOT(print_message(QString)));
emit show_input();
mutex2.lock();
window->condition->wait(&mutex2);
mutex2.unlock();
}
void MyThread::run()
{
mutex.lock();
qDebug() << "Starting thread " << id;
mutex.unlock();
get_captcha_value();
mutex.lock();
qDebug() << "Finishing thread " << id;
mutex.unlock();
}
void MyThread::print_message(QString message)
{
qDebug() << message;
QObject::disconnect(this, SLOT(print_message(QString)));
}
And main function:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyDialog* window = new MyDialog();
QList<MyThread*> threads;
for(int i = 0; i < 5; i++)
{
MyThread* thread = new MyThread(i, window);
threads << thread;
thread->start();
}
return a.exec();
}
The first problem you have is that you're inheriting from QThread. Unless you're wanting to re-write how Qt handles threading, you're doing it wrong!.
What you need to do is have a class that inherits from QObject and move the instances to a new thread. The main problem from inheriting QThread is that it can cause confusion about thread affinity (which thread an object is running on).
Also, creating more threads than processor cores is just a waste of resources.
I suggest you read this article on how to use Qt threading and stop inheriting from QThread.
Finally, the use of QMutex is to protect multiple threads accessing the same data simultaneously. You should be able to remove all of them in the code you've shown. Emitting signals with data from one thread to be received by a slot on another thread is the preferred method in Qt.