也许是一个相当愚蠢和新手的问题,但我一直在努力让我的QSerialPort serial;
在我正在制作的整个应用程序中使用。 (呃这令人沮丧地解释)
为了更清楚,我在QSerialPort serial;
中建立了上述MainWindow.cpp
,但当我转换到另一个具有不同类别的表单时(例如operations.cpp
),我不确定如何保留和使用我的serial.*
函数。我的mainwindow.cpp表单只是一个连接设置表单,允许您选择要设置的端口,波特率,数据位,奇偶校验等,一旦按下“打开连接”按钮,我就隐藏了表单({{1 }})和operations.cpp表单出现。
有关我该怎么做的任何线索?
我曾尝试与这些类使用父子关系,但是它只启动了一个新的this->hide();
并且连接丢失了。
答案 0 :(得分:1)
您应该分解出一个执行通信的单独QObject
类,并将其他类连接到它。
设计良好的系统永远不会拥有UI类并直接使用串行端口。参见例如this answer了解如何分离通信和用户界面。
让我们看看您可以对代码进行哪些转换。目前您可能会遇到类似下面的内容:
// 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类中,将它们与端口紧密耦合。让我们通过分解端口操作来解决这个问题:
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
的方法来访问唯一的控制器实例:
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();
}