目次- 1、プロジェクト作成
- 2、ユーザーインターフェース構築
- 3、機能実装
- 4、アプリケーションのパッケージ化と配布
1、プロジェクト作成
シリアル通信ツールの開発
- Qt Widgets Applicationプロジェクト「serial」を作成
- ベースクラスはWidgetを選択
2、ユーザーインターフェース構築
-
UI設計
- 受信表示領域として、Input WidgetsカテゴリのQPlainTextEditコンポーネントを使用。編集可能に設定し、読み取り専用プロパティを有効にする
- ボーレート選択用のQComboBoxコンポーネントを追加
- 送信入力フィールドとしてQLineEditコンポーネントを配置
- 情報表示領域としてQGroupBoxコンポーネントを使用
- コンポーネントの名前変更
-
UIコード例
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>Widget</class> <widget class="QWidget" name="Widget"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>480</height> </rect> </property> <property name="windowTitle"> <string>Widget</string> </property> <widget class="QWidget" name="layoutWidget"> <property name="geometry"> <rect> <x>31</x> <y>31</y> <width>737</width> <height>385</height> </rect> </property> <layout class="QGridLayout" name="gridLayout_3"> <item row="0" column="0"> <widget class="QPlainTextEdit" name="recvEdit"> <property name="readOnly"> <bool>true</bool> </property> </widget> </item> <item row="1" column="0"> <spacer name="verticalSpacer"> <property name="orientation"> <enum>Qt::Vertical</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>20</width> <height>40</height> </size> </property> </spacer> </item> <item row="2" column="0"> <layout class="QGridLayout" name="gridLayout_2"> <item row="0" column="0"> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QLabel" name="label_2"> <property name="text"> <string>ボーレート</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QComboBox" name="baundrateCb"> <item> <property name="text"> <string>4800</string> </property> </item> <item> <property name="text"> <string>9600</string> </property> </item> <item> <property name="text"> <string>115200</string> </property> </item> </widget> </item> <item row="1" column="0"> <widget class="QLabel" name="label"> <property name="text"> <string>シリアルポート番号</string> </property> </widget> </item> <item row="1" column="1"> <widget class="QComboBox" name="serialCb"/> </item> <item row="2" column="0"> <widget class="QLabel" name="label_5"> <property name="text"> <string>データビット数</string> </property> </widget> </item> <item row="2" column="1"> <widget class="QComboBox" name="dataCb"> <item> <property name="text"> <string>5</string> </property> </item> <item> <property name="text"> <string>6</string> </property> </item> <item> <property name="text"> <string>7</string> </property> </item> <item> <property name="text"> <string>8</string> </property> </item> </widget> </item> <item row="3" column="0"> <widget class="QLabel" name="label_4"> <property name="text"> <string>ストップビット</string> </property> </widget> </item> <item row="3" column="1"> <widget class="QComboBox" name="stopCb"> <item> <property name="text"> <string>1</string> </property> </item> <item> <property name="text"> <string>1.5</string> </property> </item> <item> <property name="text"> <string>2</string> </property> </item> </widget> </item> <item row="4" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> <string>パリティビット</string> </property> </widget> </item> <item row="4" column="1"> <widget class="QComboBox" name="checkCb"> <item> <property name="text"> <string>none</string> </property> </item> </widget> </item> </layout> </item> <item row="0" column="1"> <spacer name="horizontalSpacer_4"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item row="0" column="2"> <layout class="QVBoxLayout" name="verticalLayout_2"> <item> <widget class="QGroupBox" name="groupBox"> <property name="title"> <string>ようこそ、情報表示領域</string> </property> <widget class="QLabel" name="label_6"> <property name="geometry"> <rect> <x>120</x> <y>30</y> <width>161</width> <height>21</height> </rect> </property> <property name="text"> <string>デモ情報...</string> </property> </widget> </widget> </item> <item> <widget class="QLineEdit" name="sendEdit"/> </item> <item> <layout class="QHBoxLayout" name="horizontalLayout_6"> <item> <widget class="QPushButton" name="openBt"> <property name="text"> <string>シリアルを開く</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget class="QPushButton" name="closeBt"> <property name="text"> <string>シリアルを閉じる</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer_2"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget class="QPushButton" name="sendBt"> <property name="text"> <string>送信</string> </property> </widget> </item> <item> <spacer name="horizontalSpacer_3"> <property name="orientation"> <enum>Qt::Horizontal</enum> </property> <property name="sizeHint" stdset="0"> <size> <width>40</width> <height>20</height> </size> </property> </spacer> </item> <item> <widget class="QPushButton" name="clearBt"> <property name="text"> <string>クリア</string> </property> </widget> </item> </layout> </item> </layout> </item> </layout> </item> </layout> </widget> </widget> <layoutdefault spacing="6" margin="11"/> <resources/> <connections/> </ui>
3、機能実装
-
プロジェクトファイルにserialportライブラリを追加
QT += core gui serialport -
シリアルポート情報を取得してUIに表示する
MCUとの接続が必要です
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); QStringList portNames; // QSerialPortInfo::availablePorts()で利用可能なシリアルポートを自動検索 foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { portNames << info.portName(); } // ポートリストをコンボボックスに追加 ui->serialCb->addItems(portNames); } -
各UIコントロールの機能実装
-
シリアルポートオープン時の初期化処理
-
シリアルポートの宣言と生成
-
ヘッダファイル
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QSerialPort> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); QSerialPort *serialPort; private slots: void on_openBt_clicked(); void on_closeBt_clicked(); void on_sendBt_clicked(); void on_clearBt_clicked(); private: Ui::Widget *ui; }; #endif // WIDGET_H -
ソースファイル
#include "widget.h" #include "ui_widget.h" #include <QSerialPortInfo> #include <QMessageBox> Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); // ... serialPort = new QSerialPort(this); // ... } Widget::~Widget() { delete serialPort; delete ui; }
-
-
オープンボタンクリック時の処理
void Widget::on_openBt_clicked() { QSerialPort::BaudRate baudRate; QSerialPort::DataBits dataBits; QSerialPort::StopBits stopBits; QSerialPort::Parity parityBits; // UIから設定値を取得 switch(ui->baundrateCb->currentText().toInt()) { case QSerialPort::Baud4800: baudRate = QSerialPort::Baud4800; break; case QSerialPort::Baud9600: baudRate = QSerialPort::Baud9600; break; case QSerialPort::Baud115200: baudRate = QSerialPort::Baud115200; break; } switch(ui->dataCb->currentText().toInt()) { case QSerialPort::Data5: dataBits = QSerialPort::Data5; break; case QSerialPort::Data6: dataBits = QSerialPort::Data6; break; case QSerialPort::Data7: dataBits = QSerialPort::Data7; break; case QSerialPort::Data8: dataBits = QSerialPort::Data8; break; } int stopTmp = ui->stopCb->currentText().toInt(); if (stopTmp == QSerialPort::OneStop) { stopBits = QSerialPort::OneStop; } else if (stopTmp == QSerialPort::OneAndHalfStop) { stopBits = QSerialPort::OneAndHalfStop; } else if (stopTmp == QSerialPort::TwoStop) { stopBits = QSerialPort::TwoStop; } if (ui->checkCb->currentText() == "none") { parityBits = QSerialPort::NoParity; } // シリアルポートに設定を適用 serialPort->setPortName(ui->serialCb->currentText()); serialPort->setBaudRate(baudRate); serialPort->setDataBits(dataBits); serialPort->setStopBits(stopBits); serialPort->setParity(parityBits); // シリアルポートを開く if (serialPort->open(QIODevice::ReadWrite) == true) { QMessageBox::information(this, "通知", "成功!"); } else { QMessageBox::critical(this, "通知", "失敗!"); } } -
クローズボタンクリック時の処理
void Widget::on_closeBt_clicked() { serialPort->close(); } -
送信ボタンクリック時の処理
void Widget::on_sendBt_clicked() { serialPort->write(ui->sendEdit->text().toLocal8Bit().data()); } -
シリアル受信イベント処理
-
スロット関数の宣言(ヘッダファイル)
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QSerialPort> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT // ... private slots: void serialPortReadyRead_Slot(); // ... }; #endif // WIDGET_H -
シグナルとスロットの接続(コンストラクタ)
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); QStringList portNames; serialPort = new QSerialPort(this); connect(serialPort, SIGNAL(readyRead()), this, SLOT(serialPortReadyRead_Slot())); // ... } -
スロット関数の実装
void Widget::serialPortReadyRead_Slot() { QString buffer = QString(serialPort->readAll()); ui->recvEdit->appendPlainText(buffer); }
-
-
クリアボタンクリック時の処理
void Widget::on_clearBt_clicked() { ui->recvEdit->clear(); }
-
-
4、アプリケーションのパッケージ化と配布
-
Releaseモードでビルドを行う
DLLが不足しているため、実行はできません
- 出力先:プロジェクトフォルダ内、Release拡張子付きのフォルダ
- 例:
build-serial-Desktop_Qt_5_11_1_MinGW_32bit-Release
-
アイコンの変更
.ico形式の画像が必要です
-
アイコンファイルをプロジェクトディレクトリにコピー
-
プロジェクトファイルに以下を追記して再ビルド
RC_ICONS = serial_icon.ico
-
-
ディストリビューション用のパッケージ作成(Qtコンソール使用)
-
新しいフォルダを作成(日本語パス不可)
-
ビルド済みのexeファイルをコピー
-
コマンドプロンプトで移動:
cd /d C:\xxx\xxxD:\Tools\Qt\Qt5.11.1\5.11.1\mingw53_32>cd /d C:\Users\Dandelion\Desktop\SerialTools C:\Users\Dandelion\Desktop\SerialTools>dir ドライブ C のボリューム ラベルは OS です ボリューム シリアル番号は EAE6-1E0A です C:\Users\Dandelion\Desktop\SerialTools のディレクトリ 2023/03/10 02:22 <DIR> . 2023/03/10 02:20 <DIR> .. 2023/03/10 02:17 48,640 serial.exe 1 個のファイル 48,640 バイト 2 個のディレクトリ 63,272,501,248 バイトの空き領域 C:\Users\Dandelion\Desktop\SerialTools> -
windeployqtを使用して必要なDLLを追加:
windeployqt serial.exeC:\Users\Dandelion\Desktop\SerialTools>windeployqt serial.exe C:\Users\Dandelion\Desktop\SerialTools\serial.exe 32 bit, release executable Adding Qt5Svg for qsvgicon.dll Skipping plugin qtvirtualkeyboardplugin.dll due to disabled dependencies (Qt5Qml Qt5Quick). Direct dependencies: Qt5Core Qt5Gui Qt5SerialPort Qt5Widgets All dependencies : Qt5Core Qt5Gui Qt5SerialPort Qt5Widgets To be deployed : Qt5Core Qt5Gui Qt5SerialPort Qt5Svg Qt5Widgets Updating Qt5Core.dll. Updating Qt5Gui.dll. Updating Qt5SerialPort.dll. Updating Qt5Svg.dll. Updating Qt5Widgets.dll. Updating libGLESV2.dll. Updating libEGL.dll. Updating D3Dcompiler_47.dll. Updating opengl32sw.dll. Updating libgcc_s_dw2-1.dll. Updating libstdc++-6.dll. Updating libwinpthread-1.dll. Patching Qt5Core.dll... Creating directory C:/Users/Dandelion/Desktop/SerialTools/iconengines. Updating qsvgicon.dll. Creating directory C:/Users/Dandelion/Desktop/SerialTools/imageformats. Updating qgif.dll. Updating qicns.dll. Updating qico.dll. Updating qjpeg.dll. Updating qsvg.dll. Updating qtga.dll. Updating qtiff.dll. Updating qwbmp.dll. Updating qwebp.dll. Creating directory C:/Users/Dandelion/Desktop/SerialTools/platforms. Updating qwindows.dll. Creating directory C:/Users/Dandelion/Desktop/SerialTools/styles. Updating qwindowsvistastyle.dll. Creating C:\Users\Dandelion\Desktop\SerialTools\translations... Creating qt_ar.qm... Creating qt_bg.qm... Creating qt_ca.qm... Creating qt_cs.qm... Creating qt_da.qm... Creating qt_de.qm... Creating qt_en.qm... Creating qt_es.qm... Creating qt_fi.qm... Creating qt_fr.qm... Creating qt_gd.qm... Creating qt_he.qm... Creating qt_hu.qm... Creating qt_it.qm... Creating qt_ja.qm... Creating qt_ko.qm... Creating qt_lv.qm... Creating qt_pl.qm... Creating qt_ru.qm... Creating qt_sk.qm... Creating qt_uk.qm... C:\Users\Dandelion\Desktop\SerialTools>
-