继承QSerialPort

时间:2017-01-18 09:32:40

标签: c++ qt inheritance multiple-inheritance serial-communication

也许是一个相当愚蠢和新手的问题,但我一直在努力让我的QSerialPort serial;在我正在制作的整个应用程序中使用。 (呃这令人沮丧地解释)

为了更清楚,我在QSerialPort serial;中建立了上述MainWindow.cpp,但当我转换到另一个具有不同类别的表单时(例如operations.cpp),我不确定如何保留和使用我的serial.*函数。我的mainwindow.cpp表单只是一个连接设置表单,允许您选择要设置的端口,波特率,数据位,奇偶校验等,一旦按下“打开连接”按钮,我就隐藏了表单({{1 }})和operations.cpp表单出现。

有关我该怎么做的任何线索?

---

我曾尝试与这些类使用父子关系,但是它只启动了一个新的this->hide();并且连接丢失了。

1 个答案:

答案 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();
}