继承QSerialPort [英] Inheriting QSerialPort

查看:106
本文介绍了继承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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆