继承QSerialPort [英] Inheriting QSerialPort
问题描述
也许是一个相当愚蠢的新手问题,但是我一直在努力使我的QSerialPort serial;
在正在编写的整个应用程序中使用. (嗯,这令人沮丧,无法解释)
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)
更清楚地说,我在我的MainWindow.cpp
中建立了上述QSerialPort serial;
,但是当我过渡到具有不同类的另一种形式(例如operations.cpp
)时,我不确定如何保留和使用我的serial.*
功能.我的mainwindow.cpp表单只是一个连接设置表单,它允许您选择要设置的端口,波特率,数据位,奇偶校验等,一旦按下打开连接"按钮,我就隐藏了该表单(this->hide();
),然后显示operation.cpp表单.
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?
我曾尝试对这些类使用Parent-Child关系,但是,它仅启动了一个新的QSerialPort serial;
,并且连接断开.
I had attempted to use Parent-Child relationship with the classes however, it only started a new QSerialPort serial;
and the connect was lost.
推荐答案
您应该分解出一个单独的QObject
类来执行通信,并将其他类连接到该类.
You should factor out a separate QObject
class that performs communications, and connect other classes to it.
一个设计良好的系统永远不会拥有自己的UI类,而将直接使用串行端口.参见例如此答案以了解如何将通信和UI分开.
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();
}
使用功能的串行端口分布在UI类中,使它们与端口紧密耦合.让我们通过排除端口操作来解决此问题:
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();
}
最后,如果您厌倦了显式传递控制器,我们可以实现类似于QCoreApplication::instance
的方法来访问唯一的控制器实例:
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();
}
这篇关于继承QSerialPort的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!