Qt(QTextBrowser)点击链接打开浏览器/文件夹/文件

该博客介绍了如何在Qt的QTextBrowser组件中设置链接,以便点击文件路径能直接打开文件或文件夹,点击浏览器链接则跳转到网页。通过设置QTextBrowser的属性并连接信号槽处理点击事件,实现了便捷的链接操作功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在一些软件中,可能需要一个信息输出框,用来输出软件运行过程中产生的各种信息,如下图vs中的输出。有时可能会遇到输出一个文件路径,或者是一个浏览器路径,如果在输入框中点击这个字符串便能直接打开,会方便很多。在Qt的QTextBrowser中,就支持这样的操作。

 

打开文件/文件夹

auto text_browser = new QTextBrowser(this);
text_browser->setFocusPolicy(Qt::NoFocus);
text_browser->setOpenLinks(false);
text_browser->setOpenExternalLinks(false);

// 点击打开文件夹/文件
text_browser->append("<a href=\"file:///C:/Users/wangjun/Documents\">Open Documents Path</a>");
text_browser->append("<a href=\"file:///C:/Users/wangjun/Desktop\">Open Desktop Path</a>");
text_browser->append("");
text_browser->append("<a href=\"file:///C:/Users/wangjun/Downloads/test.txt\">Open Text File</a>");


auto main_layout = new QVBoxLayout();
main_layout->addWidget(text_browser);
this->centralWidget()->setLayout(main_layout);

connect(text_browser, &QTextBrowser::anchorClicked, this, [=](const QUrl &link) 
{ 
	auto path = link.path();
	path.remove(0, 1);
	QFileInfo info(path);

	if(info.isDir())
		QDesktopServices::openUrl(link);
	else if(info.isFile())
		QDesktopServices::openUrl(QUrl::fromLocalFile(path));
});

 

打开浏览器链接

auto text_browser = new QTextBrowser(this);
text_browser->setFocusPolicy(Qt::NoFocus);
text_browser->setOpenLinks(true);
text_browser->setOpenExternalLinks(true);

// 点击打开浏览器
QString browser_url = "https://y.qq.com/";
QString content_word = QStringLiteral("This is a browser url test: ");
QString word = QStringLiteral("Click to jump to the browser");
QString texts = QStringLiteral("%1<a style='color:#5998FF;text-decoration:none;'href=\"%2\">%3</a>").arg(content_word).arg(browser_url).arg(word);
text_browser->append(texts);

auto main_layout = new QVBoxLayout();
main_layout->addWidget(text_browser);
this->centralWidget()->setLayout(main_layout);

 

注意

如果不设置下面这两行代码,那么打开文件/文件夹时,QTextBrowser中的内容会被重定向,即打开文本文件时,内容变为文本的内容,打开文件夹时,内容变为空。

text_browser->setOpenLinks(false);
text_browser->setOpenExternalLinks(false);

如果需要打开浏览器链接,那么这两个需要设置为true

#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H ----------------------------------------------- #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } 以上两个是.h和.cpp代码 --------------------------------------------------------- <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>932</width> <height>628</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <widget class="QPushButton" name="pb_connect"> <property name="geometry"> <rect> <x>40</x> <y>20</y> <width>89</width> <height>25</height> </rect> </property> <property name="text"> <string>连接</string> </property> </widget> <widget class="QPushButton" name="pb_led0"> <property name="geometry"> <rect> <x>40</x> <y>70</y> <width>89</width> <height>25</height> </rect> </property> <property name="text"> <string>led0_on</string> </property> </widget> <widget class="QPushButton" name="pb_led1"> <property name="geometry"> <rect> <x>40</x> <y>110</y> <width>89</width> <height>25</height> </rect> </property> <property name="text"> <string>led1_on</string> </property> </widget> <widget class="QPushButton" name="pb_led2"> <property name="geometry"> <rect> <x>40</x> <y>150</y> <width>89</width> <height>25</height> </rect> </property> <property name="text"> <string>led2_on</string> </property> </widget> <widget class="QPushButton" name="pb_feng"> <property name="geometry"> <rect> <x>40</x> <y>190</y> <width>89</width> <height>25</height> </rect> </property> <property name="text"> <string>feng_on</string> </property> </widget> <widget class="QPushButton" name="pb_buzzer"> <property name="geometry"> <rect> <x>140</x> <y>20</y> <width>89</width> <height>25</height> </rect> </property> <property name="text"> <string>蜂鸣器_on</string> </property> </widget> <widget class="QPushButton" name="pb_humiture"> <property name="geometry"> <rect> <x>140</x> <y>70</y> <width>89</width> <height>25</height> </rect> </property> <property name="text"> <string>温湿度_on</string> </property> </widget> <widget class="QPushButton" name="pb_photosensitive"> <property name="geometry"> <rect> <x>140</x> <y>110</y> <width>89</width> <height>25</height> </rect> </property> <property name="text"> <string>光敏_on</string> </property> </widget> <widget class="QPushButton" name="pb_infrared"> <property name="geometry"> <rect> <x>140</x> <y>150</y> <width>89</width> <height>25</height> </rect> </property> <property name="text"> <string>人体红外_on</string> </property> </widget> <widget class="QPushButton" name="pb_camera"> <property name="geometry"> <rect> <x>140</x> <y>190</y> <width>89</width> <height>25</height> </rect> </property> <property name="text"> <string>摄像头_on</string> </property> </widget> <widget class="QTextBrowser" name="textBrowser"> <property name="geometry"> <rect> <x>350</x> <y>10</y> <width>421</width> <height>211</height> </rect> </property> </widget> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>932</width> <height>28</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui> 以上是.ui代码 --------------------------------------------------------- 目前项目进度: 当前项目结构如下: DXM1txst: DXM1txst.pro Headers: fsmpBeeper.h fsmpElectric.h fsmpEvents.h fsmpFan.h fsmpLed.h fsmpLight.h fsmpProximity.h fsmpsevensegLed.h fsmpTempHum.h fsmpvibrator.h mainwindow.h Sources: main.cpp mainwindow.cpp Forms: mainwindow.ui qtcreator内:ui界面中已经有组件:pb_connect(连接按钮)、pb_led0(电灯1开关按钮)、pb_led1(电灯2开关按钮)、pb_led2(电灯3开关按钮)、pb_feng(风扇开关按钮)、pb_buzzer(蜂鸣器开关按钮)、pb_humiture(温湿度传感器开关按钮)、pb_photosensitive(光敏传感器开关按钮)、pb_infrared(人体红外传感器开关按钮)、pb_camera(摄像头开关按钮)、textBrowser(用于接收和发布的消息显示)。 华清远见元宇宙实验中心物联网仿真系统内:所需的所以硬件的3D场景设计完毕,M4网关单元的Mqtt配置为: 地址:mqtt.yyzlab.com.cn 端口:1883 与应用层、云端交互的Topic: 订阅:1752365375766/APP2AIOTSIM 发布:1752365375766/AIOTSIM2APP 与硬件交互的Topic: 订阅:1752365382482/Device2AIOTSIM 发布:1752365382482/AIOTSIM2Device 与华清远见元宇宙实验中心物联网仿真系统内硬件开关发布的控制码为:电灯0开:{"lamp":true,"id":0},电灯0关:{"lamp":false,"id":0},电灯1开:{"lamp":true,"id":1},电灯1关:{"lamp":false,"id":1},电灯2开:{"lamp":true,"id":2},电灯2关:{"lamp":false,"id":2},风扇开:{"fan":true,"id":0},风扇关:{"fan":false,"id":0},人体红外传感器开:{"infrared ":true,"id":0},人体红外传感器关:{"infrarrared ":false,"id":0},温湿度传感器:{"tem":38.8,"hum":65.7,"id":0},光敏传感器:{"light":43037.0,"id":0} Stm32mp157开发板:所有需要的硬件部署完毕,硬件的.h代码如下(硬件的.h代码已经放入qtcreator项目下的Headers文件夹下,且硬件的所有.h文件内代码都不能再进行修改): fsmpBeeper.h: #ifndef FSMPBEEPER_H #define FSMPBEEPER_H /*************************************************************************** * * 类名:fsmpBeeper * 功能说明:扩展板 蜂鸣器 * 公有函数: * fsmpBeeper() * bool setRate(uint32_t rate) 设置频率 * bool start(void) 启动蜂鸣器 * bool stop(void) 关闭蜂鸣器 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include <linux/input.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> /* FSMP开发板(linux)蜂鸣器操作类 v0 2023/1/9 by 张城 */ class fsmpBeeper:public QObject{ Q_OBJECT public: explicit fsmpBeeper(const char *device = "/dev/input/event0", QObject *parent = nullptr) :QObject(parent) { event.type = EV_SND; time.tv_sec = 1; time.tv_usec = 0; event.time = time; beeper_fd = ::open(device,O_RDWR); if(beeper_fd < 0) { perror("open_beeper"); return; } }; ~fsmpBeeper() { ::close(beeper_fd); } /* * Description: 设置频率值 * input: rate 频率 * output: null * return: 成功true/失败false */ bool setRate(uint32_t rate = 1000) { if(rate > 0) { event.code = SND_TONE; event.value = rate; return true; } return false; } /* * Description: start设备 * input: null * output: null * return: 成功true/失败false */ bool start(void) { int ret = write(beeper_fd, &event, sizeof(struct input_event)); if(ret < 0) { perror("write"); return false; } return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool stop(void) { struct input_event event; event.type = EV_SND; event.code = SND_BELL; event.value = 0000; time.tv_sec = 1; time.tv_usec = 0; event.time = time; int ret = write(beeper_fd, &event, sizeof(struct input_event)); if(ret < 0) { perror("write"); return false; } return true; } private: int beeper_fd; //设备文件描述符 struct input_event event; struct timeval time; }; #endif // FSMPBEEPER_H ------------------------------------------------------- fsmpElectric.h: #ifndef ELC_H #define ELC_H /*************************************************************************** * * 类名:fsmpElectric * 功能说明:扩展板 电气信息检测 * 公有函数: * fsmpElectric() * float voltagemV(void) 获取电压mv(旋钮控制) * float currentmA(void) 获取电流ma(板载设备真实电流) * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include <linux/input.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <stdint.h> #include <QDebug> class fsmpElectric:public QObject{ Q_OBJECT public: explicit fsmpElectric(QObject *parent = nullptr) :QObject(parent) { } ~fsmpElectric(){ } float voltagemV(void) { electric_fd1 = open("/sys/bus/iio/devices/iio:device3/in_voltage1_raw",O_RDONLY|O_NONBLOCK); if(electric_fd1 < 0) { perror("open"); return -1; } char buf[10] = {0}; int ret = read(electric_fd1,buf,sizeof(buf)); if(ret < 0) { perror("read"); return -1; } int val = 0; sscanf(buf,"%d",&val); ::close(electric_fd1); return (float)3300 * val / 65536; } float currentmA(void) { electric_fd0 = open("/sys/bus/iio/devices/iio:device3/in_voltage0_raw",O_RDONLY|O_NONBLOCK); if(electric_fd0 < 0) { perror("open"); return -1; } char buf[10] = {0}; int ret = read(electric_fd0,buf,sizeof(buf)); if(ret < 0) { perror("read"); return -1; } int val = 0; sscanf(buf,"%d",&val); ::close(electric_fd0); return ((((float)3300 * val) /65536)/(10 + 100*1000 + 1000)) * 1000 / 0.1; } private: int electric_fd0; //设备文件描述符 int electric_fd1; //设备文件描述符 }; #endif // ELC_H ------------------------------------------------------- fsmpEvents.h: #ifndef ENV_H #define ENV_H /*************************************************************************** * * 类名:fsmpEvents * 功能说明:扩展板 按钮、人体红外、光闸管、火焰 * 公有函数: * fsmpEvents() * 信号: * void lightTriggered(); 光闸管阻隔 * void flameDetected(); 火焰检测 * void peopleDetected(bool); 人体红外发现true/离开false * void keyPressed(int keynum); 按键按下 keynum: 1、2、3 * void keyRelessed(int keynum); 按键释放 keynum: 1、2、3 * * *************************************************************************/ #include <QObject> #include <linux/input.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QTimer> #include <linux/gpio.h> #include <sys/ioctl.h> #include <QDebug> #include <QProcess> #include <QThread> #include <stdio.h> #include <stdlib.h> class fsmpEvents:public QObject{ Q_OBJECT signals: /* edge trigle !!!*/ void lightTriggered();//光电开关 void flameDetected();//火焰检测 void peopleDetected(bool);//人体红外 void keyPressed(int keynum); void keyRelessed(int keynum); public: explicit fsmpEvents(QObject *parent = nullptr):QObject(parent) { this->gpio_F_open(); this->gpio_E_open(); fs_timer = new QTimer(this); connect(fs_timer,SIGNAL(timeout()),this,SLOT(time_out())); fs_timer->start(10); }; private: bool gpio_F_open(const char *device = "/dev/gpiochip5") { int ret; int fd = open(device,O_RDONLY|O_NONBLOCK); if(fd < 0) { fprintf(stderr,"open"); return false; } event_req.lineoffset = 9; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_FALLING_EDGE|GPIOEVENT_REQUEST_RISING_EDGE; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } key_1_fd = event_req.fd; int flags = fcntl(key_1_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(key_1_fd,F_SETFL,flags); event_req.lineoffset = 8; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } key_3_fd = event_req.fd; flags = fcntl(key_3_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(key_3_fd,F_SETFL,flags); #if 0 event_req.lineoffset = 5; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } fire_fd = event_req.fd; flags = fcntl(fire_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(fire_fd,F_SETFL,flags); #endif // fire req.lineoffsets[0] = 5; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "fire"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } fire_fd = req.fd; // key2 req.lineoffsets[0] = 7; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "key2"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } key_2_fd = req.fd; // people req.lineoffsets[0] = 12; req.flags = GPIOHANDLE_REQUEST_INPUT; // strcpy(req.consumer_label, "key2"); req.lines = 1; memcpy(req.default_values, &data, sizeof(req.default_values)); ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req); if (ret == -1) { fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIO_GET_LINEHANDLE_IOCTL", ret, strerror(errno)); } people_fd = req.fd; return true; } bool gpio_E_open(const char *device = "/dev/gpiochip4") { int ret; int fd = open(device,O_RDONLY|O_NONBLOCK); if(fd < 0) { fprintf(stderr,"open"); return false; } event_req.lineoffset = 15; //TODO event_req.handleflags = GPIOHANDLE_REQUEST_INPUT; event_req.eventflags = GPIOEVENT_REQUEST_BOTH_EDGES; ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &event_req); // event测试的时候用这个 if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue GET LINEHANDLE IOCTL (%d)\n", ret); } light_trigger_fd = event_req.fd; int flags = fcntl(light_trigger_fd,F_GETFL,0); flags |= O_NONBLOCK; fcntl(light_trigger_fd,F_SETFL,flags); return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool close(void); public slots: void time_out() { static int key_1_flag = 0; static int key_2_flag = 0; static int key_3_flag = 0; static int light_trigger_flag = 0; static int people_flag = 0; static int flame_flag = 0; //捕获key_1按下 read(key_1_fd,&event_data,sizeof (event_data)); if(event_data.id == 2) { key_1_flag = 1; emit(this->keyPressed(1)); //qDebug()<<"key_1 pressed"; event_data.id = 0; } else if(event_data.id == 1 && key_1_flag==1) { key_1_flag = 0; emit keyRelessed(1); //qDebug()<<"key_1 relessed"; } event_data.id = 0; //捕获key_2按下 int ret = ioctl(key_2_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } //qDebug() << "==========" << data.values[0]; if(data.values[0] ==0&&key_2_flag==0) { emit(this->keyPressed(2)); key_2_flag = 1; //qDebug()<<"key_2 pressed"; } else if(data.values[0] ==1&&key_2_flag==1) { key_2_flag = 0; emit keyRelessed(2); //qDebug()<<"key_2 relessed"; } //event_data.id = 0; //捕获key_3按下 read(key_3_fd,&event_data,sizeof (event_data)); //qDebug() << "key3 "<< event_data.id; if(event_data.id == 2 && key_3_flag==0) { key_3_flag = 1; emit(this->keyPressed(3)); //qDebug()<<"key_3 pressed"; event_data.id = 0; } else if(event_data.id == 1 && key_3_flag==1) { key_3_flag = 0; emit keyRelessed(3); //qDebug()<<"key_3 relessed"; } event_data.id = 0; //捕获光电开关 read(light_trigger_fd,&event_data,sizeof (event_data)); if(event_data.id == 1 && light_trigger_flag==0) { //qDebug()<<"light triggered"; light_trigger_flag = 1; emit(this->lightTriggered()); } else light_trigger_flag = 0; event_data.id = 0; //捕获people coming ret = ioctl(people_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } if(data.values[0] ==1&&people_flag==0) { emit(this->peopleDetected(true)); people_flag = 1; //qDebug()<<"people coming"; } else if(data.values[0] ==0&&people_flag==1) { people_flag = 0; emit(this->peopleDetected(false)); //qDebug()<<"people leave"; } #if 0 //捕获火焰检测 read(fire_fd,&event_data,sizeof (event_data)); qDebug() << "------------------"<<event_data.id; if(event_data.id == 2 && flame_flag == 0) { qDebug()<<"flamedetection on"; flame_flag = 1; emit(this->flameDetected(true)); event_data.id = 0; } else if(event_data.id == 0 && flame_flag == 1) { qDebug()<<"flamedetection off"; flame_flag = 0; emit(this->flameDetected(false)); event_data.id = 0; } #endif //捕获key_2按下 ret = ioctl(fire_fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data); if (ret == -1) { ret = -errno; fprintf(stderr, "Failed to issue %s (%d), %s\n", "GPIOHANDLE_GET_LINE_VALUES_IOCTL", ret, strerror(errno)); exit(ret); } //qDebug() << data.values[0]; if(data.values[0] ==1&&flame_flag==0) { emit(this->flameDetected()); flame_flag = 1; //qDebug()<<"flame on"; } else flame_flag = 0; } private: struct gpiohandle_request req; struct gpiohandle_data data; struct gpiochip_info chip_info; struct gpioevent_request event_req; struct gpioevent_data event_data; struct gpiod_chip *gpiochip5; struct gpiod_line *gpioline5_7; int key_1_fd; //设备文件描述符 int key_2_fd; int key_3_fd; int light_trigger_fd; int people_fd; int fire_fd; QTimer * fs_timer; }; #endif //ENV_H ------------------------------------------------------- fsmpFan.h: #ifndef FAN_H #define FAN_H /*************************************************************************** * * 类名:fsmpFan * 功能说明:扩展板 风扇控制 * 公有函数: * fsmpFan() * void start(void) 开启风扇) * void stop(void) 关闭风扇 * void setSpeed(int speed) 设置风扇速度(0-255) * 信号: * 无 * * *************************************************************************/ #include <QObject> #include <linux/input.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> class fsmpFan:public QObject{ Q_OBJECT public: explicit fsmpFan(QObject *parent = nullptr):QObject(parent) { const char *device = "/sys/class/hwmon/hwmon1/pwm1"; fan_fd = ::open(device,O_WRONLY|O_TRUNC); if(fan_fd < 0) { perror("open fan"); return; } fan_speed = 0; }; ~fsmpFan(){ ::close(fan_fd); } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ void stop(void) { write(fan_fd,"0",strlen("0")); } /* * Description: start设备 * input: null * output: null * return: 成功true/失败false */ void start(void) { char speedstr[100] = {0}; sprintf(speedstr, "%d", fan_speed); write(fan_fd, speedstr, strlen(speedstr)); } /* * Description: 控制风扇转速 * intput: speed 转速 * output: null * return: null */ void setSpeed(int speed) { fan_speed = speed%255; } private: int fan_fd; //设备文件描述符 int fan_speed; }; #endif // FAN_H ------------------------------------------------------- fsmpLeds.h: #ifndef LED_H #define LED_H /*************************************************************************** * * 类名:fsmpLeds * 功能说明:扩展板 3颗灯泡 * 公有函数: * fsmpLeds() * bool on(lednum x) 开灯 lednum: fsmpLeds::LED1/fsmpLeds::LED2/fsmpLeds::LED3 * bool off(lednum x) 关灯 lednum: fsmpLeds::LED1/fsmpLeds::LED2/fsmpLeds::LED3 * 信号: * 无 * * *************************************************************************/ #include <QObject> #include <linux/input.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> class fsmpLeds:public QObject{ Q_OBJECT public: enum lednum{ LED1, LED2, LED3 }; explicit fsmpLeds(QObject *parent = nullptr) :QObject(parent) { led_fd1 = ::open("/sys/class/leds/led1/brightness",O_WRONLY|O_TRUNC); if(led_fd1 < 0) { perror("open led1"); return ; } led_fd2 = ::open("/sys/class/leds/led2/brightness",O_WRONLY|O_TRUNC); if(led_fd2 < 0) { perror("open led2"); return ; } led_fd3 = ::open("/sys/class/leds/led3/brightness",O_WRONLY|O_TRUNC); if(led_fd3 < 0) { perror("open led3"); return ; } } ~fsmpLeds() { ::close(led_fd1); ::close(led_fd2); ::close(led_fd3); } /* * Description: 开启设备,默认/sys/class/leds/led1/brightness * input: lednum * output: null * return: 成功true/失败false */ bool on(lednum x) { int fd; if(x == LED1) fd = led_fd1; else if(x == LED2) fd = led_fd2; else if(x == LED3){ fd = led_fd3; } int ret = write(fd,"1",1); if(ret < 0) { return false; } return true; } /* * Description: 关闭设备 * input: null * output: null * return: 成功true/失败false */ bool off(lednum x) { int fd; if(x == LED1) fd = led_fd1; else if(x == LED2) fd = led_fd2; else if(x == LED3){ fd = led_fd3; } int ret = write(fd,"0",1); if(ret < 0) { return false; } return true; } private: int led_fd1; //设备文件描述符 int led_fd2; //设备文件描述符 int led_fd3; //设备文件描述符 }; #endif // LED_H ------------------------------------------------------- fsmpLight.h: #ifndef LIGHT_H #define LIGHT_H /*************************************************************************** * * 类名:fsmpLight * 功能说明:扩展板 光照强度检测 * 公有函数: * fsmpLight() * double getValue(void) 获取光照强度 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include <linux/input.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QDebug> class fsmpLight:public QObject{ Q_OBJECT public: explicit fsmpLight(QObject *parent = nullptr) :QObject(parent) { light_fd = ::open("/sys/bus/iio/devices/iio:device1/in_illuminance_input",O_RDONLY|O_NONBLOCK); if(light_fd < 0) { perror("open"); return; } } ~fsmpLight() { ::close(light_fd); } /* * Description: 获取光照强度 * input: null * output: null * return: current light */ double getValue(void) { char buf[10] = {0}; int ret = read(light_fd,buf,10); if(ret < 0) { perror("read"); return false; } double num; sscanf(buf, "%lf", &num); lseek(light_fd, 0, SEEK_SET); return num; } private: int light_fd; //设备文件描述符 }; #endif // LIGHT_H ------------------------------------------------------- fsmpProximity.h: #ifndef FSMPPROXIMITY_H #define FSMPPROXIMITY_H /*************************************************************************** * * 类名:fsmpProximity * 功能说明:扩展板 红外接近传感器(和光照传感器一起) * 公有函数: * fsmpProximity() * double getValue(void) 获取接近情况(0-2048越接近数据越大) * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include <linux/input.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <QDebug> class fsmpProximity:public QObject{ Q_OBJECT public: explicit fsmpProximity(QObject *parent = nullptr) :QObject(parent) { proximity_fd = ::open("/sys/bus/iio/devices/iio:device1/in_proximity_raw",O_RDONLY|O_NONBLOCK); if(proximity_fd < 0) { perror("open"); return; } } ~fsmpProximity() { ::close(proximity_fd); } /* * Description: 获取distence * input: null * output: null * return: current light */ int getValue(void) { char buf[10] = {0}; int ret = read(proximity_fd,buf,10); if(ret < 0) { perror("read"); return false; } int num; sscanf(buf, "%d", &num); lseek(proximity_fd, 0, SEEK_SET); return num; } private: int proximity_fd; //设备文件描述符 }; #endif // FSMPPROXIMITY_H ------------------------------------------------------- fsmpSevensegLed.h: #ifndef FSMPSEVENSEGLED_H #define FSMPSEVENSEGLED_H /*************************************************************************** * * 类名:fsmpSevensegLed * 功能说明:扩展板 七段数码管 * 公有函数: * fsmpSevensegLed() * void display(int value) 显示4位以内整数 * void display(const char *str) 显示4位字符,注:仅支持 a、b、c、d、e * * 信号: * 无 * * *************************************************************************/ #include <stdint.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/types.h> #include <linux/spi/spidev.h> #include <QThread> #include <stdlib.h> #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) class fsmpSevensegLed:public QThread{ Q_OBJECT public: explicit fsmpSevensegLed(QObject *parent = nullptr) :QThread(parent) { memset(data, 0, sizeof(data)); device = "/dev/spidev0.0"; bits = 8; speed = 400000; delay = 0; } void display(int value) { data[3] = value%10; data[2] = value/10%10; data[1] = value/100%10; data[0] = value/1000%10; } //"abcde" void display(const char *str) { data[3] = (strlen(str)-1 >= 0)?(str[strlen(str)-1] - 'a')+10:0; data[2] = (strlen(str)-2 >= 0)?(str[strlen(str)-2] - 'a')+10:0; data[1] = (strlen(str)-3 >= 0)?(str[strlen(str)-3] - 'a')+10:0; data[0] = (strlen(str)-4 >= 0)?(str[strlen(str)-4] - 'a')+10:0; } private: void run() { int ret = 0; int fd; fd = open(device, O_RDWR); //打开设备文件 if (fd < 0) pabort("can't open device"); /* * spi mode //设置spi设备模式 */ ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); //写模式 if (ret == -1) pabort("can't set spi mode"); /* * bits per word //设置每个字含多少位 */ ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); //写每个字含多少位 if (ret == -1) pabort("can't set bits per word"); /* * max speed hz //设置速率 */ ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); //写速率 if (ret == -1) pabort("can't set max speed hz"); //打印模式,每字多少位和速率信息 printf("spi mode: %d\n", mode); printf("bits per word: %d\n", bits); printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); //transfer(fd); //传输测试 int i = 0; int pos = 0; unsigned char buf[2]; while(1) { pos = 1 << (i % 4); buf[0] = pos; buf[1] = num[data[i]]; if (write(fd, buf, 2) < 0) perror("write"); i++; if (i == 4) { i = 0; } usleep(3500); } } static void pabort(const char *s) { perror(s); abort(); } const char *device; uint8_t mode; uint8_t bits; uint32_t speed; uint16_t delay; int data[4]; unsigned char num[20] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71}; }; #endif // FSMPSEVENSEGLED_H ------------------------------------------------------- fsmpTempHum.h: #ifndef TEMPHUM_H #define TEMPHUM_H /*************************************************************************** * * 类名:fsmpTempHum * 功能说明:扩展板 温度湿度 * 公有函数: * fsmpTempHum() * double temperature(void) 提取温度 * double humidity(void) 提取湿度 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include <linux/input.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <stdint.h> #include <QDebug> class fsmpTempHum:public QObject{ Q_OBJECT public: explicit fsmpTempHum(QObject *parent = nullptr) :QObject(parent) { } double temperature(void) { int temp_raw = 0; int temp_offset = 0; float temp_scale = 0; open_device_int("iio:device0","in_temp_raw",&temp_raw); open_device_int("iio:device0","in_temp_offset",&temp_offset); open_device_float("iio:device0","in_temp_scale",&temp_scale); return (temp_raw + temp_offset) * temp_scale / 1000; } double humidity(void) { int hum_raw = 0; int hum_offset = 0; float hum_scale = 0; open_device_int("iio:device0","in_humidityrelative_raw",&hum_raw); open_device_int("iio:device0","in_humidityrelative_offset",&hum_offset); open_device_float("iio:device0","in_humidityrelative_scale",&hum_scale); return (hum_raw + hum_offset) * hum_scale / 1000; } private: bool open_device_int(const char *device, const char *filename, int *val) { int ret = 0; int fd; char temp[128] = {0}; sprintf(temp, "/sys/bus/iio/devices/%s/%s", device, filename); fd = open(temp,O_RDONLY|O_NONBLOCK); if(fd < 0) { perror("open"); return false; } char buf[10] = {0}; ret = read(fd,buf,sizeof(buf)); if(ret < 0) { perror("read"); return false; } sscanf(buf,"%d",val); ::close(fd); return true; } bool open_device_float(const char *device, const char *filename, float *val) { int ret = 0; int fd; char temp[128] = {0}; sprintf(temp, "/sys/bus/iio/devices/%s/%s", device, filename); fd = open(temp,O_RDONLY|O_NONBLOCK); if(fd < 0) { perror("open"); return false; } char buf[10] = {0}; ret = read(fd,buf,sizeof(buf)); if(ret < 0) { perror("read"); return false; } sscanf(buf,"%f",val); ::close(fd); return true; } private: int temp_hum_fd;; //设备文件描述符 }; #endif // TEMPHUM_H ------------------------------------------------------- fsmpVibrator.h: #ifndef VIBRATOR_H #define VIBRATOR_H /*************************************************************************** * * 类名:fsmpVibrator * 功能说明:扩展板 振动马达 * 公有函数: * fsmpVibrator() * bool setParameter(int strong_magnitude, int timems) 设置振动强度(0-0xffff)及时长(ms) * bool start(void) 启动马达 * bool stop(void) 停止马达 * * 信号: * 无 * * *************************************************************************/ #include <QObject> #include <linux/input.h> #include <string.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <QIODevice> #include <sys/ioctl.h> #include <QDebug> class fsmpVibrator:public QObject{ Q_OBJECT public: explicit fsmpVibrator(QObject *parent = nullptr) :QObject(parent) { vibrator_fd = ::open("/dev/input/event1", O_RDWR|O_NONBLOCK); if(vibrator_fd < 0) { perror("open vibrator"); } } ~fsmpVibrator() { ::close(vibrator_fd); } /* * Description:设置 * input:频率 * output:null * return:成功true/失败false */ bool setParameter(int strong_magnitude = 0xFFFF, int timems = 5000) { //qDebug()<<strong_magnitude<<timems; effect.type = FF_RUMBLE, effect.id = -1, effect.u.rumble.strong_magnitude = strong_magnitude; effect.u.rumble.weak_magnitude = 0; effect.replay.length = timems; effect.replay.delay = 0; if (ioctl(vibrator_fd, EVIOCSFF, &effect) < 0) { printf("Error creating new effect: %s\n", strerror(errno)); return false; } return true; } bool start(void) { struct input_event play = { .type = EV_FF, .code = (__U16_TYPE)effect.id, .value = 1 }; int ret = write(vibrator_fd, (const void*) &play, sizeof(play)); if(ret < 0) { perror("vibrator on"); return false; } //qDebug()<<"start"; return true; } bool stop(void) { struct input_event play = { .type = EV_FF, .code = (__U16_TYPE)effect.id, .value = 0 }; int ret = write(vibrator_fd, (const void*) &play, sizeof(play)); if(ret < 0) { perror("vibrator off"); return false; } //qDebug()<<"stop"; return true; } private: int vibrator_fd;//设备文件描述符 struct ff_effect effect; }; #endif // VIBRATOR_H ------------------------------------------------------- 项目目的: 在Linux下通过qtcreator编写后通过st-mp1构建部署到远程Linux主机后,在Stm32mp157开发板上能够控制本身的硬件同时也能同步控制华清远见元宇宙实验中心物联网仿真系统内的模拟硬件。并且通过Desktop Qt5.12.12 GCC64bit构建部署到Deploy Configuration时,能够控制Stm32mp157开发板上的硬件同时也能同步控制华清远见元宇宙实验中心物联网仿真系统内的模拟硬件。 设计要求: 1. 通过点击pb_connect(连接按钮)按钮可以连接到云端mqtt,连接成功则弹出小窗提示连接成功并自动绑定订阅与发布功能、连接失败则弹出小窗提示连接失败,弹出的小窗有一个确定键,点击确定关闭小窗。 2. 点击按钮pb_led0打开Stm32mp157开发板上的LD1灯且同步打开华清远见元宇宙实验中心物联网仿真系统内的电灯0,此时按钮pb_led0上的文本(初始化为led0_on)变更为led0_off。再次点击按钮pb_led0时关闭Stm32mp157开发板上的LD1灯且同步关闭华清远见元宇宙实验中心物联网仿真系统内的电灯0,此时按钮pb_led0上的文本(此时为led0_off)变更为led0_on。按钮pb_led1和pb_led2也是相同理论。 3. 点击按钮pb_feng打开Stm32mp157开发板上的风扇且同步打开华清远见元宇宙实验中心物联网仿真系统内的风扇,此时按钮pb_feng上的文本(初始化为feng_on)变更为feng_off。再次点击按钮pb_feng时关闭Stm32mp157开发板上的风扇且同步关闭华清远见元宇宙实验中心物联网仿真系统内的风扇,此时按钮pb_feng上的文本(此时为feng_off)变更为feng_on。 4. 点击按钮pb_buzzer打开Stm32mp157开发板上的蜂鸣器,此时按钮pb_buzzer上的文本(初始化为:蜂鸣器_on)变更为蜂鸣器_off。再次点击按钮pb_buzzer时关闭Stm32mp157开发板上的蜂鸣器,此时按钮pb_buzzer上的文本(此时为:蜂鸣器_off)变更为蜂鸣器_on。 5. 点击按钮pb_humiture时,打开Stm32mp157开发板上的温湿度传感器并将数据显示在textBrowser组件上。此时按钮pb_humiture上的文本(初始化为:温湿度_on)变更为温湿度_off。再次点击按钮pb_humiture时关闭Stm32mp157开发板上的温湿度传感器,此时按钮pb_humiture上的文本(此时为:温湿度_off)变更为温湿度_on。(需添加功能:打开Stm32mp157开发板上的温湿度传感器后,当温度超过30度时蜂鸣器会立即开启,低于30度或者直接点击按钮pb_buzzer都可关闭蜂鸣器) 6. 点击按钮pb_photosensitive时,打开Stm32mp157开发板上的光敏传感器并将数据显示在textBrowser组件上。此时按钮pb_photosensitive上的文本(初始化为:光敏_on)变更为光敏_off。再次点击按钮pb_photosensitive时关闭Stm32mp157开发板上的光敏传感器,此时按钮pb_photosensitive上的文本(此时为:光敏_off)变更为光敏_on。 7. 点击按钮pb_infrared时,打开Stm32mp157开发板上的人体红外传感器并将数据显示在textBrowser组件上。此时按钮pb_infrared上的文本(初始化为:人体红外_on)变更为人体红外_off。再次点击按钮pb_infrared时关闭Stm32mp157开发板上的人体红外传感器,此时按钮pb_infrared上的文本(此时为:人体红外_off)变更为人体红外_on。 8. 点击按钮pb_camera时打开Stm32mp157开发板上的摄像头并将采集到的图像在屏幕界面的右侧显示出来(目前项目中没有设计用于显示摄像头采集图像显示的组件,需要添加)。此时按钮pb_camera上的文本(初始化为:摄像头_on)变更为摄像头off。再次点击按钮pb_camera时关闭Stm32mp157开发板上的摄像头,此时按钮pb_camera上的文本(此时为:摄像头_off)摄像头_on,并关闭摄像头采集的图像显示界面。 结合以上代码及要求,进行完整详细的项目开发,如有需要可以添加项目结构内缺失的文件(项目结构内缺失硬件的.cpp文件),硬件.h文件不可进行修改。整合后将项目的所有文件发我,让我复制粘贴就能直接使用
最新发布
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值