关于qt:Qt-设置objectname样式不生效

Qt在对children调用show后,再设置objectname,objectname款式选择器定义的款式不失效 代码如下: //mainwindow.h#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include <QObject>#include <QVBoxLayout>#include <QWidget>class Frame : public QWidget { Q_OBJECT public: Frame(QWidget* parent = nullptr) : QWidget(parent) { setAttribute(Qt::WA_StyledBackground); m_layout = new QVBoxLayout(this); m_content = new QWidget(this); m_content->setObjectName("Content"); m_layout->addWidget(m_content); } void showContent() { m_content->show(); } private: QWidget* m_content; QVBoxLayout* m_layout;};class MainWindow : public QMainWindow { public: MainWindow(QWidget* parent = nullptr) : QMainWindow(parent) { frame = new Frame(this); this->setCentralWidget(frame); frame->showContent(); resize(600, 400); this->setObjectName("MainWindow"); } private: Frame* frame;};#endif // MAINWINDOW_H//main.cpp#include <QApplication>#include "mainwindow.h"int main(int argc, char* argv[]) { QApplication a(argc, argv); qApp->setStyleSheet("Frame #Content{background-color:red;} #MainWindow Frame #Content{background-color:blue;}"); MainWindow w; w.show(); return a.exec();}依照款式设定,蓝色的款式匹配权重应高于红色,应该显示蓝色才对,然而实际上显示确是红色,如下图所示: ...

February 27, 2024 · 1 min · jiezi

关于qt:麒麟操作系统-kylinos-从入门到精通-研发环境-第五十篇-通过源码编译QT-SDK与打包

0.根底环境类别:笔记本型号:中国长城 NF14C硬件平台:飞腾处理器(ArmV8 指令集)零碎:河汉麒麟操作系统 V10 SP1(2203) 关键词:信创,麒麟零碎,linux,c++,c,飞腾,qt,qt5,qt6,qtsdk编译 1.背景QT是Linux下或嵌入式环境下,支流的跨平台软件开发平台,丰盛和成熟的生态工具,许多开源软件都是基于QT所研发,零碎仓库或商店内置的版本大部分状况下都满足咱们的需要。然而局部软件对QT SDK (qmake)均有版本要求,因而本文通过几天的实际,试错,为大家提供一个可供参考的过程。 2.QT5.15.8 SDK编译装置过程2.1 参考资料2.1.1 官网参考资料1.https://doc.qt.io/qt-5/linux-building.html2.https://wiki.qt.io/Building_Qt_5_from_Git3.https://doc.qt.io/qt-5/configure-options.html 2.1.2 其余参考资料1.http://c.biancheng.net/view/3851.html国内镜像网站这里给大家举荐几个国内驰名的 Qt 镜像网站,次要是各个高校的: 中国科学技术大学:http://mirrors.ustc.edu.cn/qtproject/ 清华大学:https://mirrors.tuna.tsinghua.edu.cn/qt/ 北京理工大学:http://mirror.bit.edu.cn/qtproject/ 中国互联网络信息中心:https://mirrors.cnnic.cn/qt/2.2 QTSDK源代码下载https://download.qt.io/archive/qthttps://download.qt.io/archive/qt/6.3/6.3.1/single/文件夹阐明 2.3 环境筹备留神:arm64官网没有发行,只能下载本人编译。编译时请保证系统洁净(我在一台装过QT5.12的电脑上总会呈现一些谬误,在洁净的零碎上很顺利)。 2.3.1 移除本人手动装置的QT5以及相干的creator(前面再装即可)sudo apt-get remove qt5-default qt5-doc qt5-doc-html qtbase5-doc-html qtbase5-examples qt5-qmake qt5-qmake-bin -y #卸载现有QT5,不然在make时容易呈现各种谬误,还找不到起因,放弃环境尽量洁净。如果这些操作还不行,为保障成功率就想方法弄一个洁净初装的零碎进行解决。sudo autoremove #卸载不必要的依赖2.3.2 依据官网阐明装置相干依赖依据官网应用GIT从源码构建,装置相干依赖 sudo apt-get install build-essential perl python3 git -ysudo apt-get install '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev -y sudo apt-get install flex bison gperf libicu-dev libxslt-dev ruby ruby-dev -ysudo apt-get install libxcursor-dev libxcomposite-dev libxdamage-dev libxrandr-dev libxtst-dev libxss-dev libdbus-1-dev libevent-dev libfontconfig1-dev libcap-dev libpulse-dev libudev-dev libpci-dev libnss3-dev libasound2-dev libegl1-mesa-dev gperf bison -ysudo apt-get install libasound2-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev libgstreamer-plugins-bad1.0-dev -ysudo apt install clang libclang-dev -yqtweb还可能用到nodejs,通过nvm-cli装置node,参考:专栏第十五篇 https://segmentfault.com/a/1190000041978634 ...

April 4, 2023 · 1 min · jiezi

关于qt:QT-将enum打包成dll报link2001无法解析的外部符号

应用QT的插件零碎,定义了某命名空间下的枚举类型,导出为库,而后应用该库,用qDebug打印的时候,报错,如下所示: namespace EnumTestNameSpace { Q_NAMESPACE enum class Test { A = 0x00000001, B, C, D }; Q_ENUM_NS(Test)} // namespace EnumTestNameSpaceEnumTestNameSpace::Test b = EnumTestNameSpace::Test::B;//qDebug() << b; // no right link 2001:无奈解析的内部符号qDebug()<<(int)b;// right 强转过来就没问题qDebug() << (b == EnumTestNameSpace::Test::B);//right 失常进行枚举比拟没问题起因剖析:思考是因为跨dll了,而后这个中央qt没有进行解决,moc进行编译的时候,qDebug须要应用qmetaobject,找不到就报错了,该问题的影响范畴应该是除枚举根本应用外的扩大用法。 解决办法:1.应用程序间接援用xxx.h,QT会对其进行预编译2.对于枚举类,须要扩大用法的,应用class进行封装,不要应用namespace class Enum_EXPORT EnumTestClass : public QObject { Q_OBJECT public: enum class Test { A = 0x00000001, B, C, D }; Q_ENUM(Test)}; // namespace EnumTestClass

February 16, 2023 · 1 min · jiezi

关于qt:QT-svg-报错-Image-filename-is-empty-link-xxx-is-undefined

在QT我的项目里应用PS导出的svg,能够失常显示,然而会报正告,如下所示: 起因是ps生成的svg是1.2版本的,而QT对于svg仅反对到1.2 miny版本,并不像浏览器一样对svg是全版本反对的 1.2版本(不反对) 1.0版本(反对) 解决方案:1.想方法导出1.1版本的svg2.导出png格局,不应用svg格局3.将已有的1.2版本svg转换为1.1版本的svg

February 14, 2023 · 1 min · jiezi

关于qt:Y-分钟速成-Qt-Framework

源代码下载: learnqt-cn.cpp Qt Qt是一个广为人知的框架,用于开发跨平台软件,该软件能够在各种软件和硬件平台上运行,代码简直没有变动,同时具备本机应用程序的能力和速度。尽管Qt最后是用C++,但也有其余语言的端口: PyQt, QtRuby, PHP-Qt, 等等. Qt 非常适合应用图形用户界面 (GUI) 创立应用程序。本教程是对于如何用C++去实现。 /* * 让咱们从最经典的开始 */// Qt框架的所有标头均以大写字母'Q'结尾#include <QApplication>#include <QLineEdit>int main(int argc, char *argv[]) { // 创立一个对象来管理应用程序范畴内的资源 QApplication app(argc, argv); // 创立行编辑widgets并在屏幕上显示 QLineEdit lineEdit("Hello world!"); lineEdit.show(); // 启动应用程序的事件循环 return app.exec();}Qt与 GUI 相干的局部与widgets及其之间的connection无关。 浏览更多无关widgets的信息 /* * 让咱们创立一个标签和一个按钮。 * 按下按钮时应显示一个标签。 * Qt代码自身就能够阐明问题。 */ #include <QApplication>#include <QDialog>#include <QVBoxLayout>#include <QPushButton>#include <QLabel>int main(int argc, char *argv[]) { QApplication app(argc, argv); QDialog dialogWindow; dialogWindow.show(); // 增加垂直布局 QVBoxLayout layout; dialogWindow.setLayout(&layout); QLabel textLabel("Thanks for pressing that button"); layout.addWidget(&textLabel); textLabel.hide(); QPushButton button("Press me"); layout.addWidget(&button); // 按下按钮时显示暗藏标签 QObject::connect(&button, &QPushButton::pressed, &textLabel, &QLabel::show); return app.exec();}留神,QObject :: connect局部。 此办法用于将一个对象的SIGNAL连贯到另一个对象的SLOTS。 ...

December 20, 2022 · 1 min · jiezi

关于qt:Y-分钟速成-Qt-Framework

源代码下载: learnqt-cn.cppQt Qt是一个广为人知的框架,用于开发跨平台软件,该软件能够在各种软件和硬件平台上运行,代码简直没有变动,同时具备本机应用程序的能力和速度。尽管Qt最后是用C++,但也有其余语言的端口: PyQt, QtRuby, PHP-Qt, 等等. Qt 非常适合应用图形用户界面 (GUI) 创立应用程序。本教程是对于如何用C++去实现。 /* * 让咱们从最经典的开始 */// Qt框架的所有标头均以大写字母'Q'结尾#include <QApplication>#include <QLineEdit>int main(int argc, char *argv[]) { // 创立一个对象来管理应用程序范畴内的资源 QApplication app(argc, argv); // 创立行编辑widgets并在屏幕上显示 QLineEdit lineEdit("Hello world!"); lineEdit.show(); // 启动应用程序的事件循环 return app.exec();}Qt与 GUI 相干的局部与widgets及其之间的connection无关。 浏览更多无关widgets的信息 /* * 让咱们创立一个标签和一个按钮。 * 按下按钮时应显示一个标签。 * Qt代码自身就能够阐明问题。 */ #include <QApplication>#include <QDialog>#include <QVBoxLayout>#include <QPushButton>#include <QLabel>int main(int argc, char *argv[]) { QApplication app(argc, argv); QDialog dialogWindow; dialogWindow.show(); // 增加垂直布局 QVBoxLayout layout; dialogWindow.setLayout(&layout); QLabel textLabel("Thanks for pressing that button"); layout.addWidget(&textLabel); textLabel.hide(); QPushButton button("Press me"); layout.addWidget(&button); // 按下按钮时显示暗藏标签 QObject::connect(&button, &QPushButton::pressed, &textLabel, &QLabel::show); return app.exec();}留神,QObject :: connect局部。 此办法用于将一个对象的SIGNAL连贯到另一个对象的SLOTS。 ...

December 20, 2022 · 1 min · jiezi

关于qt:在vs2022中对于QT5的简单使用

背景vs2022配置了QT5.14.2, 而后尝试手写了一下qt程序, 问题遇到的问题如下 1.新建程序的时候,如果抉择了类型为widget程序vs就默认启用qt creator的接口,生成ui文件 而我不想用ui间接手写, 所以须要创立qt empty application 2.创立了我的项目之后,援用 #include <QWidget>显示无奈关上此文件,意思就是找不到这个库 而后也就是咱们得配置一下 点击我的项目 右键 属性 在vc++中的 蕴含目录和库目录,将qt的对应版本的include和lib给蕴含进来 3.而后再配置了vs配置了qt的前提下,勾选qt的设置,抉择须要的qt Modules 一个窗体程序,个别抉择这几个就行, 这个附加上qt5 各个模块都是干嘛的 参见上面的链接 https://blog.csdn.net/qq_2639... 而后咱们就能够开始写程序了 这里能够贴一下代码 width.h #pragma once#ifndef WIDGET_H#define WIDGET_H#include <qwidget.h>class Widget : public QWidget{ Q_OBJECT;public: Widget(QWidget* parent = 0); ~Widget();private: void setupUI(); void openFile(); void outputFile();private slots: void slot_testBtn_clicked();};#endif //WIDGET_Hwidget.cpp #if _MSC_VER >= 1600 // MSVC2015 > 1899, MSVC_VER = 14.0#pragma execution_character_set("utf-8")#endif#include "widget.h"#include <qboxlayout.h>#include <qpushbutton.h>#include <qdebug.h>#include <qfiledialog.h>#include <qmessagebox.h>#include <qfile.h>#include <qtextedit.h>#include <iostream>using namespace std;Widget::Widget(QWidget* parent) :QWidget(parent) { setupUI();}Widget::~Widget(){}void Widget::setupUI() { QVBoxLayout* mainLayout = new QVBoxLayout; mainLayout->setMargin(0); mainLayout->setSpacing(0); QPushButton* testBtn = new QPushButton("抉择"); //QTextEdit textEdit = new QTextEdit(this); connect(testBtn, SIGNAL(clicked(bool)), this, SLOT(slot_testBtn_clicked())); mainLayout->addWidget(testBtn); mainLayout->addStretch(); this->setLayout(mainLayout);}void Widget::openFile() { QString path = QFileDialog::getOpenFileName(this, tr("Open File"), ".", tr("Text File(*.txt)")); if (!path.isEmpty()) { QFile file(path); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMessageBox::warning(this, tr("Read Fifle"), tr("Cannot open file:\n%1").arg(path)); return; } qDebug() << file.fileName(); file.close(); } }void Widget::outputFile() {}void Widget::slot_testBtn_clicked() { qDebug() << tr("点击抉择按钮"); this->openFile();}main.cpp ...

November 26, 2022 · 1 min · jiezi

关于qt:QT-日期字符串或时间戳转QDateTime性能测试

QT里将字符串或工夫戳转换为QDateTime不同办法性能比拟(release编译下) 环境:Qt:6.2.3(MSVC 2019, 64 bit)QtCreator:7.0.2c++:17boost:1.8 办法:1.应用QDateTime自带的fromString办法不思考如下函数,因为Qt::TextDate解析形式限度死了字符串格局,必须为"ddd MMM d HH:mm:ss yyyy" QDateTime QDateTime::fromString(QStringView string, Qt::DateFormat format = Qt::TextDate) 应用如下函数 QDateTime QDateTime::fromString(QStringView string, QStringView format, QCalendar cal = QCalendar())2.应用substring按字符串格局进行字符串截取,而后调用QDateTime构造方法3.将字符串传给boost库的posix_time的fromstring,而后调用QDateTime构造方法4.应用工夫戳形式 论断substring->工夫戳->QDateTime::fromString->Boost_posix_time; 10000条 100000条 测试代码#include <QCoreApplication>#include <QDateTime>#include <QSharedPointer>#include <boost/date_time/gregorian/gregorian.hpp>#include <boost/date_time/posix_time/posix_time.hpp>using namespace boost::posix_time;const static std::string dateTimeStdStr = "2022/10/12 08:10:13";const static QString dateTimeFormat = "yyyy/MM/dd HH:mm:ss";const static qint64 dateTimeStamp = 1669362601364;QString printResult(QList<qint64> list) { qint64 total = 0; QString result = ""; for (int i = 0; i < list.size(); i++) { result += QString("%1ms,").arg(list.at(i)); total += list.at(i); } result += QString("均匀:%1ms").arg(total / list.size()); return result;}int main(int argc, char* argv[]) { QCoreApplication a(argc, argv); // init data int size = 100000, testTimes = 10; QMap<QString, void (*)()> funcMap; QMap<QString, QList<qint64>> consumeTimeMap; QVector<QString> vector = {"String:调用QDateTime::fromString办法转换", "String:substring截取交给QDateTime结构", "String:传给boost的fromstring,再交给QDateTime结构", "Int工夫戳:调用QDateTime::fromMSecsSinceEpoch办法转换"}; funcMap.insert(vector.at(0), []() { QDateTime temp = QDateTime::fromString(dateTimeStdStr.c_str(), dateTimeFormat); }); funcMap.insert(vector.at(1), []() { int year = atoi(dateTimeStdStr.substr(0, 4).c_str()); int month = atoi(dateTimeStdStr.substr(5, 2).c_str()); int day = atoi(dateTimeStdStr.substr(8, 2).c_str()); int hour = atoi(dateTimeStdStr.substr(11, 2).c_str()); int minute = atoi(dateTimeStdStr.substr(14, 2).c_str()); int second = atoi(dateTimeStdStr.substr(17, 2).c_str()); QDateTime temp = QDateTime(QDate(year, month, day), QTime(hour, minute, second)); }); funcMap.insert(vector.at(2), []() { const std::locale loc = std::locale(std::locale::classic(), new time_input_facet("%Y-%m-%d %H:%M:%S")); std::istringstream is(dateTimeStdStr); is.imbue(loc); boost::posix_time::ptime t; is >> t; tm pt_tm = to_tm(t); QDateTime dateTime = QDateTime(QDate(pt_tm.tm_year, pt_tm.tm_mon, pt_tm.tm_mday), QTime(pt_tm.tm_hour, pt_tm.tm_min, pt_tm.tm_sec)); }); funcMap.insert(vector.at(3), []() { QDateTime dateTime = QDateTime::fromMSecsSinceEpoch(dateTimeStamp); }); // start test qDebug() << QString("开始测试,数据量为%1,测试次数为%2").arg(size).arg(testTimes); for (int i = 0; i < vector.size(); i++) { QString key = vector.at(i); QList<qint64> consumeTimeList; for (int j = 0; j < testTimes; j++) { qint64 startTime = QDateTime::currentMSecsSinceEpoch(); void (*func)() = funcMap.value(key); for (int k = 0; k < size; k++) { func(); } qint64 endTime = QDateTime::currentMSecsSinceEpoch(); consumeTimeList.push_back(endTime - startTime); } consumeTimeMap.insert(key, consumeTimeList); } for (int i = 0; i < vector.size(); i++) { QString key = vector.at(i); qDebug() << QString("测试%1完结,执行状况(%2)").arg(key).arg(printResult(consumeTimeMap.value(key))); } return a.exec();}

November 25, 2022 · 2 min · jiezi

关于qt:Qt中使用TCP接收报文

假如有一个TCP服务端,会向连贯到它的TCP客户端周期(或随机)发送一个报文。报文由定长的报文头和不定长的报文体(数据局部)组成,报文体是一张图片,每个字节示意图片中一个像素的灰度值。咱们的工作就是读取报文,解析图片内容,保留或显示图片。报文头的格局如下: #define FLAG 0x12131415struct Header{ quint32 flag; // 报文标识 quint32 length; // 报文长度 quint32 width; // 图片宽度 quint32 height; // 图片高度}flag是报文标识,用来辨认报文的开始;length是报文的总长度,通过它能够晓得报文何时完结;width和height示意图片的高度和宽度,用来将报文体数据解析为图片。 首先结构一个QTcpScoket用于和服务端建设TCP连贯,期待接收数据。 QTcpSocket *socket = new QTcpSocket(this);socket->setReadBufferSize(BUF_SIZE);connect(socket, SIGNAL(readyRead()), this, SLOT(slotReadData()));测试发现,如果服务端一次发送的报文长度很长(例如10086字节),会被宰割成多个包发送。上面是通过tcpdump命令抓包失去的: 14:47:27.438893 IP ...... length 144814:47:27.438916 IP ...... length 144814:47:27.438920 IP ...... length 144814:47:27.438922 IP ...... length 144814:47:27.438980 IP ...... length 144814:47:27.438983 IP ...... length 144814:47:27.438985 IP ...... length 1398此例中,10068个字节被宰割成7个包。在QTcpSocket接管到数据后,每个包会对应地发射一次readyRead()信号。也就是说,在槽函数中,只能读取整个报文的一部分。因而须要定义一些成员变量,来保留数据读取过程中的状态。 private: QTcpSocket *mSocket; char mBuf[BUF_SIZE]; // 数据读取缓冲区 qint64 mSize = 0; // 已读取数据的长度 Header mHeader; // 报文头 bool mHeadValid = false; // 报文头是否无效接下来咱们开始读取数据,有两种思路。 ...

November 18, 2022 · 2 min · jiezi

关于qt:写一个只触发一次槽函数的Qt-connect函数

在之前的Qt我的项目中,我发现常常会用到槽函数只须要执行一次的状况。也就是说,槽函数执行一次后,就须要disconnect对应的连贯。然而,真正操作起来实际上挺麻烦的,或者说不优雅。因为你须要把之前connect时产生的QMetaObject::Connection对象保存起来,而保留它不能用局部变量,通常须要保留到类的成员变量中,或者其余生命周期足够长的中央,以避免在disconnect它的时候,它曾经生效了。总之,须要使用者本人保护,因此减少了使用者的累赘。 如果有一个办法可能在槽函数执行实现后主动disconnect掉连贯就好了。我在网上找了一段时间,却没有找到适合的解决方案,相干探讨也比拟少,可能这不是一个很常见的需要吧。不过还是在GitHub上找到了一个相干的库:https://github.com/misje/once,然而看它的源码,感觉比较复杂。它针对QObject::connect函数的每种状况,写了对应的实现,总感觉太简单了,应该存在一种更通用的办法。 最近在浏览了《C++ Primer》模板相干的章节后,我忽然想到兴许用完满转发相干的货色能够简化实现。于是试着写了一下,貌似真得能够,代码如下: ConnectionUtil.h: #pragma once#include <QObject>#include <QMap>namespace ConnectionUtil{ typedef QMetaObject::Connection Conn; struct ConnKey {}; extern QMap<ConnKey*, QPair<Conn, Conn>> connMap; class ReceiverObj : public QObject { Q_OBJECT public: explicit ReceiverObj(ConnKey *connKey) : key(connKey) {} public slots: void slot(); private: ConnKey *key; }; // 解决信号为SIGNAL(...)的状况 template <typename Sender, typename ...Args> void connect(Sender &&sender, const char *signal, Args &&...args) { ConnKey *connKey = new ConnKey; Conn conn1 = QObject::connect(std::forward<Sender>(sender), signal, std::forward<Args>(args)...); Conn conn2 = QObject::connect(std::forward<Sender>(sender), signal, new ReceiverObj(connKey), SLOT(slot())); connMap.insert(connKey, qMakePair(std::move(conn1), std::move(conn2))); } // 解决其余状况 template <typename Sender, typename Signal, typename ...Args> void connect(Sender &&sender, Signal &&signal, Args &&...args) { ConnKey *connKey = new ConnKey; Conn conn1 = QObject::connect(std::forward<Sender>(sender), std::forward<Signal>(signal), std::forward<Args>(args)...); Conn conn2 = QObject::connect(std::forward<Sender>(sender), std::forward<Signal>(signal), [connKey] { ReceiverObj(connKey).slot(); }); connMap.insert(connKey, qMakePair(std::move(conn1), std::move(conn2))); }}ConnectionUtil.cpp: ...

September 3, 2022 · 1 min · jiezi

关于qt:QT-自定义控件-事件分发器过滤器

自定义控件 自定义label:新建控件label 右键晋升为 //.h#ifndef CUSTOMLABEL_H#define CUSTOMLABEL_H#include <QWidget>#include <QLabel>class customLabel : public QLabel{ Q_OBJECTpublic: explicit customLabel(QWidget *parent = nullptr);signals:public slots:};#endif // CUSTOMLABEL_H//.cpp#include "customlabel.h"customLabel::customLabel(QWidget *parent) : QLabel(parent){}事件散发器:用于事件的散发,能够进行事件拦挡的操作。事件散发器返回布尔类型:bool event(QEvent ev),如果返回值为true,代表用户本人解决该事件,否者交给基类实现事件。应用步骤:重写event事件 事件过滤器:能够在程序散发到event事件之前再做一次高级拦挡。事件散发器返回布尔类型:bool eventfilter(QObjectobj,QEvent ev),如果返回值为true,代表用户本人解决该事件,否者交给基类实现事件。应用两个步骤:1.给控件装置事件过滤器;2.重写eventfilter事件。 #ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>QT_BEGIN_NAMESPACEnamespace Ui { class MainWindow; }QT_END_NAMESPACEclass MainWindow : public QMainWindow{ Q_OBJECTpublic: MainWindow(QWidget *parent = nullptr); ~MainWindow(); //(1)通过事件散发器,拦挡鼠标事件 bool event(QEvent *ev); //重写事件过滤器 bool eventFilter(QObject *,QEvent *);private: Ui::MainWindow *ui;};#endif // MAINWINDOW_H#include "mainwindow.h"#include "ui_mainwindow.h"#include <QDebug>#include <QEvent>#include <QMouseEvent>MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow){ ui->setupUi(this); //步骤o1:装置事件过滤器 this->installEventFilter(this); //步骤02:重写事件过滤器}MainWindow::~MainWindow(){ delete ui;}//(1)通过事件散发器,拦挡鼠标事件bool MainWindow::event(QEvent *e ){ //如果鼠标点击,在event事件散发器中,执行拦挡操作 if(e->type()==QEvent::MouseButtonPress) { //类型装换 QMouseEvent *ev=static_cast<QMouseEvent *>(e); QString str=QString("拦挡了鼠标点击了事件"); qDebug()<<str; return true;//true代表用户自主处理事件,不想下散发事件 } //其余事件,交给父类解决 return QMainWindow::event(e);}//事件过滤器实现bool MainWindow::eventFilter(QObject *obj,QEvent *ev){ if (obj==ui->lab_test) { if(ev->type()==QEvent::MouseButtonPress) { //类型装换 QMouseEvent *ev=static_cast<QMouseEvent *>(ev); QString str=QString("事件过滤器拦挡了鼠标点击"); qDebug()<<str; return true;//true代表用户自主处理事件,不想下散发事件 } } return QWidget::eventFilter(obj,ev);}

August 27, 2022 · 1 min · jiezi

关于qt:qt程序使用less编译less文件为qss文件

在qt应用程序里应用qrc里的style.qss文件,并且在程序编译的时候将style.less事后编译成style.qss,提供应用程序应用。 前提条件:装置node.js,而后全局装置less 办法1在projects里增加build steps,执行命令行即可,有多少个less文件就增加多少次 办法2在.pro文件里利用qmake进行预编译,编译机会为:build-link 假如你的我的项目里应用了qrc的style.qss文件,那么它会应用rcc.exe进行编译 1.应用QMAKE_PRE_LINK和QMAKE_POST_LINK无奈实时生成,因为这两者的生命周期是在link前后,而rcc.exe是在build期,不合乎预期 2.应用systemsystem生命周期优于build期,然而当.pro文件变动后,system执行lessc命令,然而如果只是批改了.less文件,它不会主动执行,不合乎预期 3.应用PRE_TARGETDEPS,QMAKE_EXTRA_TARGETS它两的生命周期优于build期,合乎预期,然而它是非阻塞式的,与build是并发执行的,rcc.exe拿到的还是旧的style.css,不合乎预期 4.应用QMAKE_EXTRA_COMPILERS根本用法 test.output = 文件1.qsstest.commands = lessc 文件1.less 文件1.qss & lessc 文件2.less 文件2.qss ...testInput = 文件1.lesstest.input = testInputtest.CONFIG = no_link留神:1.test.input必须应用变量,且不容许加$ $,写成test.input = 文件1.less或者test.input=$$testInput都是无奈解析的 2.test.config必须写成no_link,否则是会报错的 封装之后为: #扭转文件后缀名defineReplace(changeFileSubFix){ file = $$formatSlash($$1) subfix = $$2 dir = $$dirname(file) baseName = $$basename(file) baseNameList =$$split(baseName,.) fileName = $$first(baseNameList) targetFile = $$join(fileName,,$$dir\,$$subfix) return ($$targetFile)}#less命令,负责将配置的.less文件转换为.qss文件defineReplace(compileLessCommand){ files = $$formatSlash($$1) firstFile = $$first(files) input = $$firstFile output = $$changeFileSubFix($$firstFile,".qss") commands = for(file,files){ targetFile = $$changeFileSubFix($$file,".qss") commands += $$quote(lessc $$file $$targetFile &) } return ($$input $$commands $$output) #qmake不反对数据,数组嵌套语法}应用 ...

August 22, 2022 · 1 min · jiezi

关于qt:Qt60-qproperty不生效原因

qt的qss款式是能够应用根本属性和property属性的,比方咱们想扭转组件的minimumSize有两种办法 1.代码里写 qLabel->setMinimumSize (100,200);2.qss里写 QLabel{ qproperty-minimumSize:100px 200px;}然而咧,你会发现有些property属性写了不失效,比如说(它用了枚举值) QLabel{ qproperty-alignment:AlignCenter;}在有些论坛里有说是能够这么写的 什么起因呢?预计是在旧版本里Qt对AlignCenter字符串做了解析,新版本里不再辨认它了,那么怎么解决呢?应用Qt::AlignCenter或Qt.AlignCenter?都是不行的,咱们晓得枚举值默认状况下都是int型的,那么咱们间接设置int是不是就能够? ok,那么咱们打印下AlignCenter的值 qDebug() << Qt::AlignCenter << static_cast<int>(Qt::AlignCenter); QLabel{background-color:red;qproperty-alignment:132;} ok,它失效了~

August 21, 2022 · 1 min · jiezi

关于qt:QT-元对象系统

元对象零碎次要是为了实现信号和槽机制才被引入的,不过除了信号和槽机制以外,元对象零碎还提供了其余一些个性: QObject::metaObject()函数能够返回一个类的元对象,它是QMetaObject类的对象;QMetaObject::className()能够在运行时以字符串模式返回类名,而不须要C++编辑器原生的运行时类型信息(RTTI)的反对;QObject::inherits()函数返回一个对象是否是QObject继承树上一个类的实例的信息;QObject::tr()和QObject::trUtf8()进行字符串翻译来实现国际化;QObject::setProperty()和QObject::property()通过名字来动静设置或者获取对象属性;QMetaObject::newInstance()结构该类的一个新实例。

August 18, 2022 · 1 min · jiezi

关于qt:QT-对象树模型

对象树模型概念

August 18, 2022 · 1 min · jiezi

关于qt:QT-组件化开发-自动生成基础组件

在做QT自定义组件开发的时候,拷贝代码,再批改太繁琐了,所以想着能不能主动生成下根底组件,于是有了主动生成组件的想法。一个根本的组件是长这个样子: .pri QT子工程配置文件*.cpp,*.h, 组件内容*plugin.cpp,*plugin.h,组件插件化配置,次要用于qt designer里进行利落一开始的想法是应用bat脚本(因为外面应用了中文,所以此文件须要保留为ansi格局,保留成UTF-8的化执行会有问题)批处理,运行后先拷贝cpushbutton组件目录,而后遍历此目录,对文件进行重命名 @echo offset target=DialogButtonBoxset cTarget=C%target%set qTarget=Q%target%set dir="%cd%/cpushbutton - 正本"set lowerCTarget=%cTarget%for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do call set lowerCTarget=%%lowerCTarget:%%i=%%i%%set upperCTarget=%cTarget%for %%i in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do call set upperCTarget=%%upperCTarget:%%i=%%i%%ren %dir% %lowerCTarget%set newDir="%cd%/%lowerCTarget%"for /r %newDir% %%i in (*.*) do ( if "%%~xi"==".pri" ( ren %%i "%lowerCTarget%%%~xi" )else ( echo "%%~ni"| findstr "plugin" >nul &&( ren %%i "%lowerCTarget%plugin%%~xi" )||( ren %%i "%lowerCTarget%%%~xi" ) ))重命名后须要的是文件内容替换,整顿了一下后大略是这么些数据,为了不便,我在bat里主动生成了对应内容,在QT creator里间接拷贝过来,执行五次替换即可 ...

July 8, 2022 · 5 min · jiezi

关于qt:QT-自定义组件

1.应用QT project创立一个QT custom designer widget 2.创立后失去的文件目录如图所示 components.cpp 次要是进行组件合并,将cpushbutton和ctoolbutton合并,再减少组件也是相似写法 3.构建release版本,将生成的.dll文件拷贝到qt creator里的designer的plugin里 4.在qt designer的设计师里能够间接拖动生成的组件即可应用 问题:1.为啥qt creator的设计师里没有该组件?请确保你的组件构建版本与qt creator版本统一 2.为啥我的类继承了QPushButton(其余同理),在*.ui形容文件里是QWidget? emmm,QT会主动帮你生成这段形容,class依据你的domXML函数生成,extends默认都是QWidget,header是class名全小写,解决方案就是咱们本人生成这段形容 失去的*.ui形容文件就是这样

July 7, 2022 · 1 min · jiezi

关于qt:QT-Designer-plugins在qt-designer里使用

1.关上QT示例,Custom Widget Plugin Example 2.抉择编译环境,留神须要与QT creator保持一致,能够通过Help->About Qt Creator里查看qt creator的编译环境,我这里是Qt 6.2.3(MSVC 2019,64 bit) 3.抉择release构建 4.将生成的customwidgetplugin.dll放到qtcreator的plugins目录,我的是(D:\software\qt\Tools\QtCreator\bin\plugins\designer) 5.重新启动QT creator,新建一个widget程序,即可在.ui文件里看到这个控件 留神:编译环境须要严格统一!!!包含QT的版本,这里qt版本是6.2.3,不要应用其余版本,不然会呈现莫名其妙的问题,我之前用qt 6.3.1(MSVC 2019,64bit)来编译,将dll文件放到plugins后,提醒Failed to extract plugin meta data from 'D:/software/qt/Tools/QtCreator/bin/plugins/designer/customwidgetplugin.dll')

June 25, 2022 · 1 min · jiezi

关于qt:交叉编译-Qt5-armv8aarch64-with-WebEngine-NVIDIA-JETSON-TX2

本文写于 2020 年初,实现 armv8 下穿插编译 webengine,备份转载于此 原文链接 我的平台:On Windows10 WSL2 Debian(注:Ubuntu <= 16.04 会呈现 libclang < 3.8 的问题) 下载源码为防止网络问题,先装置一个下载工具,应用aria2能够断点持续下载 sudo apt install aria2而后 cd 到一个工作目录Qt 5.12.5 源码 aria2c https://mirrors.tuna.tsinghua.edu.cn/qt/official_releases/qt/5.12/5.12.5/single/qt-everywhere-src-5.12.5.tar.xztar xf qt-everywhere-src-5.12.5.tar.xz穿插编译工具 Linaro GCC aria2c https://releases.linaro.org/components/toolchain/binaries/latest-5/aarch64-linux-gnu/gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu.tar.xztar xf gcc-linaro-5.5.0-2017.10-x86_64_aarch64-linux-gnu.tar.xz在指标平台装置依赖库sudo apt-get install '.*libxcb.*' libxrender-dev libxi-dev \ libfontconfig1-dev libudev-dev libxkbcommon-dev \ libxkbcommon-x11-dev libc6-dev-arm64-cross libnss3-dev libicu-dev \ libdbus-1-devGLES 和 EGLmkdir /home/nvidia/GLEScd /home/nvidia/GLESapt-get download libgles2-mesa-devar x libgles2*.debtar -xvf data.tar.xzmkdir /home/nvidia/EGLcd /home/nvidia/EGLapt-get download libegl1-mesa-devar x libegl1*.debtar -xvf data.tar.xzcd /home/nvidia/GLES/usr/includesudo cp -r GLES2 GLES3 /usr/includecd /home/nvidia/EGL/usr/includesudo cp -r EGL KHR /usr/include在本机装置依赖sudo apt-get install -y 'libxcb.*' \ libx11-xcb-dev libglu1-mesa-dev \ libxrender-dev libxi-dev libinput* \ mtdev* mesa-utils \ mesa-utils-extra libgles2-mesa-dev ninja-build \ git rsync pkg-config gcc g++ ps: ...

May 16, 2022 · 3 min · jiezi

关于qt:视觉实战案例Qt实现8位灰度图叠加通道转换成24位三通道图像

前言在我的项目中,可能一些输出的图像要求是RGB的图像格式,然而手边只有单通道的黑白相机进行采图,这时就须要将8位的单通道图像转换成24位的三通道图像,个别都是应用3个8位图像叠加成三通道图像。 1、OpenCV实现单通道转三通道首先创立一个CV_8UC3的三通道图像,图像大小尺寸与单通道图像尺寸统一,而后将3份单通道图像叠加交融填入刚创立的三通道图像。 Mat Widget::convertTo3Channels(const cv::Mat& binImg){ cv::Mat three_channel = cv::Mat::zeros(binImg.rows,binImg.cols,CV_8UC3); std::vector<cv::Mat> channels; for (int i=0;i<3;i++) { channels.push_back(binImg); } cv::merge(channels,three_channel); return three_channel;}2、判断图像通道数进行转换这里先判断图像是否是单通道还是四通道,如果是四通道,将图像间接转换成三通道。如果是单通道应用下面程序转换成三通道 //判断输出图像的通道数 if(curMatImg.type() == CV_8UC4) { cvtColor(curMatImg,curMatImg,COLOR_RGBA2RGB); qDebug()<<"width"<<curMatImg.cols<<curMatImg.rows; } else if(curMatImg.type() == CV_8UC1) { curMatImg = convertTo3Channels(curMatImg); } else { qDebug()<<"Img is 3 Channels"; }3、程序实现代码transWidget.h#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include <QSettings>#include <QFileInfo>#include <QFileDialog>#include <QDebug>#include <QMessageBox>#include "opencv2/opencv.hpp"namespace Ui {class Widget;}class Widget : public QWidget{ Q_OBJECTpublic: explicit Widget(QWidget *parent = 0); ~Widget();private slots: void on_btn_trans_clicked(); void on_btn_close_clicked(); void on_btn_OpenFile_clicked(); void on_btn_NextPic_clicked(); void on_btn_LoadPic_clicked(); void on_btn_SaveImgPath_clicked();private: Ui::Widget *ui; QImage curImg; //文件夹中图像数量 int PicNum; //文件夹以后加载图像下标 int CurPicIndex=0; //批量加载图像文件夹的门路 QString file_path; //以后图像名称 QString CurfileName; //图像名称缓存 QMap<int,QString> PicNameInfo; //保留文件夹文件数量 int saveFile_Num; //Mat转换QImage QImage cvMat2QImage(const cv::Mat& mat); //QImage转换Mat cv::Mat QImage2Mat(QImage image); //图像转换到三通道 cv::Mat convertTo3Channels(const cv::Mat& binImg); void checkCurPicIndex();};#endif // WIDGET_HtransWidget.cpp#pragma execution_character_set("utf-8")#include "widget.h"#include "ui_widget.h"using namespace cv;Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this); ui->btn_NextPic->setEnabled(false);}Widget::~Widget(){ delete ui;}void Widget::on_btn_trans_clicked(){ //保留图像 if(ui->edt_ImgSavePath->text().isEmpty()) { QMessageBox::critical(NULL, "critical", "未指定保留文件夹,请设置!"); return; } else { Mat curMatImg = QImage2Mat(curImg); //判断输出图像是不是8位灰度图像 if(curMatImg.type() == CV_8UC4) { cvtColor(curMatImg,curMatImg,COLOR_RGBA2RGB); qDebug()<<"width"<<curMatImg.cols<<curMatImg.rows; } else if(curMatImg.type() == CV_8UC1) { curMatImg = convertTo3Channels(curMatImg); } else { qDebug()<<"Img is 3 Channels"; } QImage QimgTrans = cvMat2QImage(curMatImg); QImage ShowTranImg = QimgTrans.scaled(ui->lbl_RGBImg->size(),Qt::KeepAspectRatio); ui->lbl_RGBImg->setPixmap(QPixmap::fromImage(ShowTranImg)); QString SaveFilePath = ui->edt_ImgSavePath->text() + "/trans_" + QString::number(saveFile_Num) +".bmp"; QimgTrans.save(SaveFilePath); saveFile_Num++; }}Mat Widget::QImage2Mat(QImage image){ Mat cvMat; qDebug()<<image.format(); switch(image.format()) { case QImage::Format_ARGB32: case QImage::Format_RGB32: cvMat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); cv::cvtColor(cvMat, cvMat, COLOR_BGRA2BGR); break; case QImage::Format_ARGB32_Premultiplied: cvMat = cv::Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine()); break; case QImage::Format_RGB888: cvMat = cv::Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine()); cv::cvtColor(cvMat, cvMat, COLOR_BGR2RGB); break; case QImage::Format_Indexed8: cvMat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); break; case QImage::Format_Grayscale8: cvMat = cv::Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine()); break; } return cvMat;}QImage Widget::cvMat2QImage(const cv::Mat &mat){ switch ( mat.type() ) { // 8-bit 4 channel case CV_8UC4: { QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_RGB32 ); return image; } // 8-bit 3 channel case CV_8UC3: { QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_RGB888 ); return image.rgbSwapped(); } // 8-bit 1 channel case CV_8UC1: { static QVector<QRgb> sColorTable; // only create our color table once if ( sColorTable.isEmpty() ) { for ( int i = 0; i < 256; ++i ) sColorTable.push_back( qRgb( i, i, i ) ); } QImage image( mat.data, mat.cols, mat.rows, mat.step, QImage::Format_Indexed8 ); image.setColorTable( sColorTable ); return image; } default: qDebug("Image format is not supported: depth=%d and %d channels\n", mat.depth(), mat.channels()); qWarning() << "cvMatToQImage - cv::Mat image type not handled in switch:" << mat.type(); break; } return QImage();}Mat Widget::convertTo3Channels(const cv::Mat& binImg){ cv::Mat three_channel = cv::Mat::zeros(binImg.rows,binImg.cols,CV_8UC3); std::vector<cv::Mat> channels; for (int i=0;i<3;i++) { channels.push_back(binImg); } // cv::merge() cv::merge(channels,three_channel); return three_channel;}void Widget::on_btn_close_clicked(){ close();}void Widget::on_btn_OpenFile_clicked(){ QSettings setting("./Setting.ini", QSettings::IniFormat); //为了能记住上次关上的门路 QString lastPath = setting.value("LastFilePath").toString(); file_path = QFileDialog::getExistingDirectory(this, "请抉择文件夹门路...", lastPath); if(file_path.isEmpty()) { QMessageBox::warning(this,"Warning","未抉择文件夹,请从新抉择文件夹!"); return; } else { PicNameInfo.clear(); CurPicIndex = 0; QDir dir(file_path); //改文件夹曾经判断是否存在,保障以后必然存在 QStringList filter; filter<<"*.bmp"<<"*.jpg"<<"*.png"; QFileInfoList list = dir.entryInfoList(filter, QDir::Files); //获取文件信息列表 if(!list.isEmpty()) { // qDebug() << list.count();//输入图片名 for(int i=0;i<list.count();i++){ QFileInfo fileInfo = list.at(i); qDebug() << fileInfo.fileName();//输入图片名 PicNameInfo.insert(i,fileInfo.fileName()); } CurfileName = PicNameInfo.value(0); QString picPathShow = file_path + "/" + PicNameInfo.value(0); ui->edt_ImgFolderPath->setText(picPathShow); curImg.load(picPathShow); QImage ShowImg = curImg.scaled(ui->lbl_GrayImg->size(),Qt::KeepAspectRatio); ui->lbl_GrayImg->setPixmap(QPixmap::fromImage(ShowImg)); ui->lbl_RGBImg->clear(); checkCurPicIndex(); } else { QMessageBox::warning(this,"Warning","该文件夹为空,请从新抉择文件夹!"); return; } } }void Widget::on_btn_NextPic_clicked(){ CurPicIndex++; CurfileName = PicNameInfo.value(CurPicIndex); QString curPicPath = file_path + "/" + PicNameInfo.value(CurPicIndex); ui->edt_ImgFolderPath->setText(curPicPath); curImg.load(curPicPath); QImage ShowImg = curImg.scaled(ui->lbl_GrayImg->size(),Qt::KeepAspectRatio); ui->lbl_GrayImg->setPixmap(QPixmap::fromImage(ShowImg)); ui->lbl_RGBImg->clear(); checkCurPicIndex();}void Widget::on_btn_LoadPic_clicked(){ QSettings setting("./Setting.ini", QSettings::IniFormat); //为了能记住上次关上的门路 QString lastPath = setting.value("LastFilePath").toString(); QFileInfo file; QString PicPath =QFileDialog::getOpenFileName(this,QString::fromLocal8Bit("抉择图像文件"),lastPath,"图像文件 (*.bmp *.jpg *.png)"); if(PicPath.isEmpty()) { return; } else { file = QFileInfo(PicPath); // CurfileName = file.fileName(); //获取文件名 // qDebug() << CurfileName;//输入图片名 qDebug()<<"加载图像胜利"; // QImage img(PicPath); curImg.load(PicPath); QImage ShowImg = curImg.scaled(ui->lbl_GrayImg->size(),Qt::KeepAspectRatio); ui->lbl_GrayImg->setPixmap(QPixmap::fromImage(ShowImg)); ui->lbl_RGBImg->clear(); // ui->graphicsView->fitInView(ImageItem); }}void Widget::checkCurPicIndex(){ if(PicNameInfo.size()>1) { if(CurPicIndex == 0) { // ui->btnPreviousPic->setEnabled(false); ui->btn_NextPic->setEnabled(true); } else if(CurPicIndex == PicNameInfo.count()-1) { ui->btn_NextPic->setEnabled(false); // ui->btnPreviousPic->setEnabled(true); } else { // ui->btnPreviousPic->setEnabled(true); ui->btn_NextPic->setEnabled(true); } } }void Widget::on_btn_SaveImgPath_clicked(){ QSettings setting("./Setting.ini", QSettings::IniFormat); //为了能记住上次关上的门路 QString lastPath = setting.value("LastFilePath").toString(); QString save_path = QFileDialog::getExistingDirectory(this, "请抉择文件夹门路...", lastPath); ui->edt_ImgSavePath->setText(save_path); QDir *dir = new QDir(save_path); QStringList filter; QFileInfoList fileInfoList = dir->entryInfoList(filter); saveFile_Num = fileInfoList.count()-2;}4、实现成果 ...

May 15, 2022 · 3 min · jiezi

关于qt:视觉实战案例QtOpenCV实现USB摄像头监测移动物体并录制视频功能帧差法

1、背景介绍最近手边的零食总是莫名其妙的缩小,为了抓到一个首恶来帮我续零食,就想着应用手边的usb摄像头来实现一个动静物体监测和保留视频的性能,不过这里应用最简略的帧差法来实现物体的静止监测。 2、应用OpenCV的帧差法实现静止物体监测开发环境Qt5.9 + OpenCV硬件Logitech摄像头 2.1 帧差法介绍静止物体图像在相邻两帧间差异较大,两帧差值后进行简略的图像处理,较容易判断是否存在物体挪动,相似于剪纸动画,本例中应用帧差后判断阈值宰割后的面积来确定是否存在物体静止。帧差法用前一帧图像作为以后帧的背景模型具备较好的实时性,其背景不积攒,且更新速度快、算法简略、计算量小。算法的有余在于对环境噪声较为敏感,阈值的抉择相当要害,抉择过低不足以克制图像中的噪声,过高则疏忽了图像中有用的变动。对于比拟大的、色彩统一的静止指标,有可能在指标外部产生空洞,无奈残缺地提取静止指标。 2.2 帧差法局部实现代码将以后帧图像和上一帧图像进行灰度化,而后高斯滤波后做图像差值,选定适合的二值化阈值宰割,最初对宰割解决的区域面积进行断定。 Mat grayframePre,frameDet; Mat frameNow,grayframeNow; cvtColor(matFrame,grayframeNow,COLOR_RGB2GRAY); cvtColor(framePre,grayframePre,COLOR_RGB2GRAY); GaussianBlur(grayframeNow,grayframeNow,Size(21,21),0,0); GaussianBlur(grayframePre,grayframePre,Size(21,21),0,0); absdiff(grayframeNow,grayframePre,frameDet); framePre = matFrame; threshold(frameDet,frameDet,20,255,THRESH_BINARY); Mat element = getStructuringElement(0,Size(3,3)); vector<vector<Point>> contours; dilate(frameDet,frameDet,element); findContours(frameDet,contours,RETR_TREE,CHAIN_APPROX_SIMPLE,Point()); qDebug()<<"Num"<<contours.size(); QString SavePath = "D:/ImgPath/" + QString::number(VideoNum) + "_track.avi"; if(contours.size()==0) { if(writer.isOpened()) { writer.release(); } if(isSaveFrame) { isSaveFrame = false; VideoNum++; } } else { for(int i=0;i<contours.size();i++) { double area = contourArea(contours[i]); if(area < 100)continue; else { qDebug()<<"有物体静止!"; if(!isSaveFrame) { int fourcc = writer.fourcc('M', 'J', 'P', 'G'); writer.open(SavePath.toStdString(),fourcc,10,Size(frameWidth,frameHeight),true); isSaveFrame = true; } else { writer.write(matFrame); } break; } } } } else { framePre = matFrame; }3、在Qt平台下应用opencv对静止物体进行监测widget.h#ifndef WIDGET_H#define WIDGET_H#include <QWidget>#include "opencv2/opencv.hpp"#include <QTimer>using namespace cv;namespace Ui {class Widget;}class Widget : public QWidget{ Q_OBJECTpublic: explicit Widget(QWidget *parent = 0); ~Widget();private slots: void on_btnOpenVedio_clicked(); void on_btnQuit_clicked(); void readFrame(); void on_ckb_Track_clicked(bool checked);private: Ui::Widget *ui; bool openCam; bool isTrack=false; bool isSaveFrame = false; QTimer *timer; VideoCapture *cap; Mat framePre; int fps,frameWidth,frameHeight; VideoWriter writer; int VideoNum = 0; //Mat转换QImage QImage cvMat2QImage(const cv::Mat& mat);};#endif // WIDGET_Hwidget.cpp#pragma execution_character_set("utf-8")#include "widget.h"#include "ui_widget.h"#include <iostream>#include <QDebug>using namespace std;Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget){ ui->setupUi(this); timer = new QTimer(this); timer->stop(); connect(timer,SIGNAL(timeout()),this,SLOT(readFrame())); openCam = true; cap = new VideoCapture(0); frameWidth = cap->get(CAP_PROP_FRAME_WIDTH); frameHeight = cap->get(CAP_PROP_FRAME_HEIGHT); fps = cap->get(CAP_PROP_FPS); qDebug()<<"width"<<frameWidth<<frameHeight<<fps;}Widget::~Widget(){ delete ui;}void Widget::on_btnOpenVedio_clicked(){ if(openCam) { ui->btnOpenVedio->setText("敞开摄像头"); timer->start(30); } else { ui->btnOpenVedio->setText("关上摄像头"); timer->stop(); } openCam = !openCam;}QImage Widget::cvMat2QImage(const cv::Mat &mat){ switch ( mat.type() ) { // 8-bit 4 channel case CV_8UC4: { QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_RGB32 ); return image; } // 8-bit 3 channel case CV_8UC3: { QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_RGB888 ); return image.rgbSwapped(); } // 8-bit 1 channel case CV_8UC1: { static QVector<QRgb> sColorTable; // only create our color table once if ( sColorTable.isEmpty() ) { sColorTable.resize( 256 ); for ( int i = 0; i < 256; ++i ) { sColorTable[i] = qRgb( i, i, i ); } } QImage image( (const uchar*)mat.data, mat.cols, mat.rows, static_cast<int>(mat.step), QImage::Format_Indexed8 ); image.setColorTable( sColorTable ); return image; } default: qDebug("Image format is not supported: depth=%d and %d channels\n", mat.depth(), mat.channels()); qWarning() << "cvMatToQImage - cv::Mat image type not handled in switch:" << mat.type(); break; } return QImage();}void Widget::on_btnQuit_clicked(){ timer->stop(); cap->release(); close();}void Widget::readFrame(){ Mat matFrame; cap->read(matFrame); if(isTrack) { Mat grayframePre,frameDet; Mat frameNow,grayframeNow; cvtColor(matFrame,grayframeNow,COLOR_RGB2GRAY); cvtColor(framePre,grayframePre,COLOR_RGB2GRAY); GaussianBlur(grayframeNow,grayframeNow,Size(21,21),0,0); GaussianBlur(grayframePre,grayframePre,Size(21,21),0,0); absdiff(grayframeNow,grayframePre,frameDet); framePre = matFrame; threshold(frameDet,frameDet,20,255,THRESH_BINARY); Mat element = getStructuringElement(0,Size(3,3)); vector<vector<Point>> contours; dilate(frameDet,frameDet,element); findContours(frameDet,contours,RETR_TREE,CHAIN_APPROX_SIMPLE,Point()); qDebug()<<"Num"<<contours.size(); QString SavePath = "D:/ImgPath/" + QString::number(VideoNum) + "_track.avi"; if(contours.size()==0) { if(writer.isOpened()) { writer.release(); } if(isSaveFrame) { isSaveFrame = false; VideoNum++; } } else { for(int i=0;i<contours.size();i++) { double area = contourArea(contours[i]); if(area < 100)continue; else { qDebug()<<"有物体静止!"; if(!isSaveFrame) { int fourcc = writer.fourcc('M', 'J', 'P', 'G'); writer.open(SavePath.toStdString(),fourcc,10,Size(frameWidth,frameHeight),true); isSaveFrame = true; } else { writer.write(matFrame); } break; } } } } else { framePre = matFrame; } QImage Qimg = cvMat2QImage(matFrame); ui->picshow->setPixmap(QPixmap::fromImage(Qimg));}void Widget::on_ckb_Track_clicked(bool checked){ if(checked) { isTrack = true; } else { isTrack = false; }}4、界面成果展现关上摄像头后,能够进行采集视频操作,勾选“关上追踪”,程序会调用帧差算法断定是否有静止物体,如果有物体静止,就保留静止时的视频。 ...

May 8, 2022 · 3 min · jiezi

关于qt:QMessageBoxcritical-严重警告错误对话框

QMessageBox::critical 重大正告谬误对话框critical(QWidget parent,title text,buttons,defaultButton): QMessageBox::critical(this, "critical", "Content", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);//默认抉择YES弹出严重错误对话框parent:指定父窗口title:对话框题目text:对话框文本buttons:多个规范按钮,默认为OK按钮defaultButton:默认选中的规范按钮,默认为对话框中第一个按钮

May 4, 2022 · 1 min · jiezi

关于qt:SDDC的Windows初体验QT篇

前言如果相熟爱智和看过我之前文章的敌人见到这篇文章肯定会有很大疑难,SDDC 作为智能设施发现控制协议,怎么会用在 windows 上? 这所有还是源自于我微小的脑洞,因为这段在搞 Windows 开发,突发奇想能不能把电脑也接入到爱智上,于是就把嵌入式设施应用的 SDDC 协定移植到了 Windows 上,本文就介绍下基于 QT 移植的 libsddc 库,其实我还移植到了 VS2022 上了,这个之后再介绍吧。 软硬件抉择这里应用 windows 开发,除了电脑也不须要其余额定的硬件了。 软件的话,应用的是 QT 5.9.0 版本,官网下载太慢了,举荐大家下载这个清华大学开源镜像站的资源:https://mirrors.tuna.tsinghua.edu.cn/qt/archive/qt/5.9/5.9.0/qt-opensource-windows-x86-5.9.0.exe 代码获取与解析代码能够从我的 gitee 仓库间接获取: https://gitee.com/inspiration-desktop/windows-libsddc.git 关上 libsddc 我的项目如下: 其中 SDDC 相干代码都已基于 windows环境进行兼容批改,具体批改内容能够全局搜寻 __WINDOWS__ 宏来查看,其中次要的差别是 windows 和嵌入式零碎的 socket 相干实现上,还有就是多线程,QT自身就反对 pthread ,这个给移植带来了很大的便当,不像 VS 为了反对 pthread 还须要一顿折腾,对于VS的移植之后的文章再介绍吧。 main.cpp 代码解析,次要内容是获取uuid作为设施惟一标识(其实还是我没找到适合的获取 windows MAC 地址的接口...); #include "mainwindow.h"#include <QApplication>#include "sddc_message_example.h"#include "sddc.h"#include "test_thread.h"#include "cJSON.h"#include <QUuid>#include <QFile>#include <iostream>int main(int argc, char *argv[]){ QApplication a(argc, argv); // 启动可视化窗口,临时用不到 //MainWindow w; //w.show(); char * uuid_str; char buffer[128]; QString uuidstr; QUuid uuid; // 获取uuid作为设施惟一标识 QFile file("uuid.txt"); if(file.exists()){ std::cout << "file exist\n"; if(!file.open(QIODevice::ReadWrite)){ std::cout << "open file failed\n"; }else{ //读取文件 //判断文件是否曾经读到开端了 while(!file.atEnd()){ //读取数据 memset(buffer,0,sizeof(buffer)); qint64 length = file.readLine(buffer,128); if(length != -1){ uuid_str = (char*)&buffer; std::cout << "read success\n"; } } file.close(); } }else{ if(!file.open(QIODevice::ReadWrite)){ std::cout << "open file failed\n"; }else{ uuid = QUuid::createUuid(); uuidstr = uuid.toString(); uuid_str = (char *)uuidstr.remove("{").remove("}").remove("-").toStdString().data(); memset(buffer,0,sizeof(buffer)); memcpy(buffer,uuid_str,strlen(uuid_str)); uuid_str = buffer; std::cout << uuid_str << std::endl; qint64 length = -1; length = file.write(uuid_str); if(length == -1){ std::cout << "write file failed\n"; }else{ std::cout << "write file success\n"; } file.close(); } } std::cout << uuid_str << std::endl; // 启动一个新线程进行其余业务解决 //test_thread *thread1 = new test_thread(); //thread1->start(); // 启动 SDDC 协定 sddc_main(uuid_str); a.exec(); return 0;}成果点击左下角的绿色三角运行程序; ...

April 28, 2022 · 1 min · jiezi

关于qt:视觉实战案例Qt调用Basler网口工业相机SDK实现采图和相机参数设置

1、采图UI显示 2、硬件连贯和IP配置2.1 外触发硬件接线依据相机接线图,连贯相机的电源的触发信号输出; 2.2 IP配置Gige网口相机须要电脑网卡和相机在同一ip段内,反对动静、动态等形式配置IP,关上Pylon IP Configurator来匹配IP,如下 3、代码实现根本采图性能Balser都有对应的Demo进行参考,这里只截取相机采图和局部参数设置性能演示。 balser_gigeCamera.h#ifndef BALSER_GIGECAMERA_H#define BALSER_GIGECAMERA_H/**************************** @projectName camera_test* @brief Basler相机图像采集及参数设置性能;* @author Alaric* @date 2018-11-04**************************/#include <QImage>#include "balser_gigecamera_global.h"#include <QObject>#include <pylon/PylonIncludes.h>#include <pylon/BaslerUniversalInstantCamera.h>#include <pylon/_BaslerUniversalCameraParams.h>#include <QMutex>using namespace std;using namespace Pylon;using namespace GenApi;using namespace Basler_UniversalCameraParams;class BALSER_GIGECAMERASHARED_EXPORT Balser_GigeCamera : public QObject, public CImageEventHandler{ Q_OBJECTpublic: Balser_GigeCamera(QObject *parent = nullptr); ~Balser_GigeCamera(); enum BaslerCamera_Type{ Type_Basler_Freerun, //设置相机的内触发 Type_Basler_Line1, //设置相机的外触发 Type_Basler_ExposureTimeAbs, //设置相机的曝光工夫 Type_Basler_GainRaw, //设置相机的增益 Type_Basler_AcquisitionFrameRateAbs, //设置相机的频率 Type_Basler_Width, //图片的宽度 Type_Basler_Height, //图片的高度 Type_Basler_LineSource, //灯的触发信号 }; void initCamera(); //初始化相机 void OpenCamera(); //关上相机 void CloseCamera(); //敞开相机 void deleteAll(); //删除相机 int getExposureTime(); //取得曝光工夫 void setExposureTime(int time); //设置曝光工夫 int getGain(); //取得增益 void setGain(int value); //设置增益 void setFrameRate(int value); //设置帧率 int getFrameRate(); //取得帧率 void OneKeyAutoExTime(); //一键主动曝光 void SetCamera(Balser_GigeCamera::BaslerCamera_Type index, int tmpValue = 0); // 设置各种参数 int GetCamera(Balser_GigeCamera::BaslerCamera_Type index); // 获取各种参数 void AutoExposureOnce(CBaslerUniversalInstantCamera& camera); //主动曝光 void StartAcquire(); //开始采集 void StopAcquire(); //完结采集 void StartSnap(); //抓图 bool GrabOnLine_Signal; //实时采图信号 signals: void canShowImg(QImage img); //发送图像数据 public slots: void WorkTypeSignal(int work_type); //接管图像处理信号,0为Once,1为Online;private: CBaslerUniversalInstantCamera m_basler; CGrabResultPtr m_ptrGrabResult; CImageFormatConverter m_formatConverter;//Basler 图片格式转换类 CPylonImage pylonImage; //Basler 图像格式 QMutex m_mutexLock; int TestImg_WorkType = -1; //图像处理形式,默认-1为不解决,0为Once,1为Online; QImage CopyImgToQImage(CGrabResultPtr ptrGrabResult); protected: virtual void OnImageGrabbed(CInstantCamera &camera, const CGrabResultPtr &grabResult);};#endif // BALSER_GIGECAMERA_H这里balser采集到的BYTE格局的图像数据依照通道数转换成QImage格局,最初发送给UI线程进行显示。 ...

March 22, 2022 · 4 min · jiezi

关于qt:如何评价-Qt-的发展前景

以前:QT=乞讨 当初:QT=前途 QT作为跨平台的C++图形用户界面利用程序开发框架,最大的劣势就是——跨平台。如果利用须要反对多个平台,并且要求多个平台的性能同步,交互体验基本一致,然而开发成本不能成倍增加,只须要做极少量适配工作,抉择QT算是最佳计划了。 以往QT需要比拟强烈的畛域次要集中于军工、安防、车联网、工业管制、电力等绝对偏传统的行业畛域,整体需要比较稳定。然而近年来因为美国的技术限度造成了种种不确定性,采纳国产Linux零碎代替Windows,实现国产代替渐成共识。这也就意味着,像QT这种GUI框架必然会越受青眼。 以灵便用工平台飞援为例,平台上的客户对于QT开发的需要呈现显著增长,也从侧面印证了这种判断。

March 21, 2022 · 1 min · jiezi

关于qt:QProcess的正确用法

  在进行编程过程中,常常用到在程序当中调用其它的程序,这就须要用到过程调用,在QT中就用到了QProcess的进行过程调用,其有QT本身的特点,用起来十分不便,与C++自身的接口不一样,其流程特点如下: 特点1:须要waitForStarted,判断程序启动是胜利,还是失败 特点2:须要waitForFinished,判断程序是否完结 这也是比拟传统的用法,当然,你不违心判断完结,就能够不判断了。 个别应用时容易犯的谬误,就是间接省略了特点1的处理过程,进行了特点2,失常的话,是没问题,然则被调用的程序出问题的话,那就难查找起因了,如下: //QProcess的用法void MainWindow::on_pushButton_2_clicked(){ qDebug()<<"enter function MainWindow::on_pushButton_2_clicked"; QProcess myProcess; QStringList arguments; arguments += "1"; arguments += "2"; myProcess.start("./test", arguments); myProcess.closeReadChannel(QProcess::StandardOutput); myProcess.closeReadChannel(QProcess::StandardError); myProcess.closeWriteChannel(); while(!myProcess.waitForFinished(500)) { qDebug()<<"wait"; sleep(2); QCoreApplication::processEvents(QEventLoop::AllEvents, 2000); } qDebug()<<"exit function MainWindow::on_pushButton_2_clicked";}下面代码看着是没问题的,失常是能够执行的,我专门测试了一个异样的状况,就是下面的./test程序是不存在的,执行状况如下: enter function MainWindow::on_pushButton_2_clickedwaitwaitwaitwaitwaitwaitwaitwait发现了,程序进入了死循环,你也不晓得什么起因,是不是,有些蒙了 起因是,程序启动就失败了,这时waitForFinished()函数会始终返回false,官网也有相应的阐明: Returns true if the process finished; otherwise returns false (if the operation timed out, if an error occurred, or if this QProcess is already finished)说的很明确,如果过程曾经完结了,会始终返回false,所以下面就进入了死循环。那怎么解决呢?上面就说说QProcess的规范流程了,如下: //QProcess的用法void MainWindow::on_pushButton_2_clicked(){ qDebug()<<"enter function MainWindow::on_pushButton_2_clicked"; QProcess myProcess; QStringList arguments; arguments += "1"; arguments += "2"; myProcess.start("./test", arguments); myProcess.closeReadChannel(QProcess::StandardOutput); myProcess.closeReadChannel(QProcess::StandardError); myProcess.closeWriteChannel(); if(myProcess.waitForStarted()) { qDebug()<<"启动胜利"; } else { qDebug()<<"启动失败 error:"<<myProcess.errorString(); return; } while(!myProcess.waitForFinished(500)) { qDebug()<<"wait"; sleep(2); QCoreApplication::processEvents(QEventLoop::AllEvents, 2000); } qDebug()<<"exit function MainWindow::on_pushButton_2_clicked";}这样再执行,输入如下: ...

March 2, 2022 · 1 min · jiezi

关于qt:解决QT程序异常中止报错acrtfirstblock-header

在Windows下应用VS开发QT程序,如果应用了函数toStdString来将QString转换为std::string的时候,可能会产生解体,报错__acrt_first_block == header。这种解体会产生在vs我的项目的运行库设置为动态链接(/MT)时,如果运行库设置的是动静链接(/MD)则不会有问题。这个解体的根本原因是对象在析构时开释内存不正确。std::string是STL中定义的模板类,所以编译器在编译dll时会将std::string实例化,在编译exe时也会将其实例化。当设置运行库为动态链接(/MT)时,dll和exe都有本人独立的heap内存。函数toStdString会返回一个std::string,这个std::string是在dll的内存中调配的,当其在exe中被开释时就会抛出__acrt_first_block == header的异样。这个问题在QT的官网bugreports里也有人反馈——QString::toStdString() bug——依照官网的说法这不是QT的bug,是微软编译器的实现问题。所以,这个问题的解决办法就是: 设置dll和exe的运行库为动静链接(/MD)。让dll的接口不要返回std::string。应用toLocal8Bit替换toStdString。例如,将 std::string fs = qsFilter.toStdString();批改为 std::string fs = std::string(qsFilter.toLocal8Bit());

November 20, 2021 · 1 min · jiezi

关于qt:如何解决VS中QT的ui文件双击无法打开

最近在VS2017中开发QT的程序。在关上一个已存在的工程后,双击外面的ui文件没有反馈。而在新建的工程中,双击ui文件时却能关上Qt Designer。起初发现通过从新增加ui文件的默认打开方式能够解决。解决步骤如下: 在VS工程的[解决方案资源管理器]中,右键点击ui文件,在下拉菜单中抉择[打开方式],在弹出窗口中[移除]掉[Qt Designer(默认值)]。而后点击[增加]按钮,在弹出窗口的程序这一栏中增加你装置的designer.exe(例如:C:\Qt\Qt5.13.2\5.13.2\msvc2017_64\bin\designer.exe),也能够通过最左边的[...]按钮来增加。增加完后,点击[设为默认值],将增加的Qt Designer从新设置为默认值。最初,点击[确认],敞开弹出窗口,从新双击ui文件即可关上Qt Designer。

November 20, 2021 · 1 min · jiezi

关于qt:Qt学习实例Qt实现可自由展开和折叠控件布局功能

1、介绍和功能分析本次学习的内容次要是实现控件的折叠和开展,相似抽屉控件,目前Qt自带的控件QToolBox具备这个性能,然而一次只能开展一个,所以针对本人的需要能够本人写一个相似的性能,这里实现的办法比拟多,其实原理也比较简单,就是点一次暗藏,再点一次显示的成果。 2、实现办法目前实现的办法有两种,原理基本相同,办法一是应用QPushButton联合SetVisible()函数来实现点击后暗藏和显示的成果。其UI布局如下:办法一应用点击QPushButton按钮来实现暗藏和显示QWidget的成果,再在QPushButton前减少辅助图标就实现了开展和收起的实际效果,其成果如下图: 办法二中次要通过ToolBox进行调用,将传入的QWidget传入到ToolPage中,ToolPage主动填充到内容区,再将ToolPage增加到垂直布局中,ToolPage分为标题栏(QPushButton)和内容区(QWidget),点击QPushButton后,循环展开/折叠内容区。办法二与办法一实现原理雷同,只是办法二对ToolBox进行了再次封装,而后通过ToolBox间接调用。其UI布局如下: 3、代码实现首先从新写一个抽屉的类来创立控件相干性能: LockerButton.h#ifndef LOCKER_BUTTON_H#define LOCKER_BUTTON_H#include <QWidget>#include <QPushButton>class QLabel;class LockerButton : public QPushButton{ Q_OBJECTpublic: explicit LockerButton(QWidget* parent = nullptr); // 设置按钮图标 void SetImageLabel(const QPixmap &pixmap); // 设置按钮文字 void SetTextLabel(QString text); // 返回图像label句柄 QLabel* GetImageHandle(); // 返回文字label句柄 QLabel* GetTextHandle();private: // 按钮图标 QLabel* m_imageLabel; // 按钮文字 QLabel* m_textLabel;};#endif // LOCKER_BUTTON_HLockerButton类继承于PushButton类,次要进行控件的图标和文字设置。 LockerButton.cpp#include "LockerButton.h"#include <QLabel>#include <QVBoxLayout>#include <QLineEdit>#include <QDoubleValidator>LockerButton::LockerButton(QWidget* parent) : QPushButton(parent){ m_imageLabel = new QLabel; m_imageLabel->setFixedWidth(20); m_imageLabel->setScaledContents(true); m_imageLabel->setStyleSheet("QLabel{background-color:transparent;}"); m_textLabel = new QLabel; m_textLabel->setStyleSheet("QLabel{background-color:transparent;}"); QHBoxLayout* mainLayout = new QHBoxLayout; mainLayout->addWidget(m_imageLabel); mainLayout->addWidget(m_textLabel); mainLayout->setMargin(0); mainLayout->setSpacing(0); this->setLayout(mainLayout);}void LockerButton::SetImageLabel(const QPixmap &pixmap){ m_imageLabel->setPixmap(pixmap);}void LockerButton::SetTextLabel(QString text){ m_textLabel->setText(text);}QLabel* LockerButton::GetImageHandle(){ return m_imageLabel;}QLabel* LockerButton::GetTextHandle(){ return m_textLabel;}接下来是调用,参考网上大部分是通过代码去创立控件,这里我应用的是PushButton控件在ui上实现,在Form上拉一个PushButton控件,而后晋升为LockerButton,如下图:再接下来就是Widget的实现了 ...

October 27, 2021 · 2 min · jiezi

关于qt:QGraphicsView实现背景的绘制和前景图像的绘制

1、介绍Qt中应用QGraphicsScene重写drawBackGround绘制背景,就是应用自定义的Scene类来重写drawBackGround的函数来从新绘制背景,这里须要留神的是自定义的Scene类要继承QGraphicsScene类,因为drawBackGround是一个虚函数,相当于事件函数,所以在创立Scene的同时会主动去调取drawBackGround函数,这里在Scene自定义类中间接申明虚函数drawBackGround,如下所示: protected: virtual void drawBackground(QPainter* painter, const QRectF& rect);而后在Scene类中从新定义drawBackGround函数,这里间接应用重写的函数来实现本人革新背景的性能 Q_UNUSED(rect); QPen pen; pen.setColor(QColor(60,60,60)); pen.setWidth(1); painter->setPen(pen); qreal left=rect.left(); for(int i=left;i<2068;i+=10) { painter->drawLine(left,i,2068,i); } for(int i=left;i<2068;i+=10) { painter->drawLine(i,left,i,2068); }这里定义了一个间距为10像素的网格线路, 2、从新绘制前景图像这里理论实现成果如drawBackGround相似,然而我在实现的过程中发现,drawForeGround函数必须在QGraphicsView的类里能力触发,这里我查找了drawForeGround的介绍。发现在QGraphicsView和QGraphicsScene这两个类下都有drawForeGround函数,这里我在QGraphicsView类下实现的前景图的重绘操作 void InteractiveView::drawForeground(QPainter* painter, const QRectF& rect) { qDebug()<<"drawForeground"; QRectF SceneRect = this->sceneRect(); painter->setPen(QPen(Qt::red, 3)); painter->drawLine(0,0,0,300); painter->drawLine(0,0,300,0);}这里只是简略的在前景图上画了两条直线,如果想实现鼠标追随来实现相应的前景图创立,则须要引入鼠标追随的事件来实现。

September 4, 2021 · 1 min · jiezi

关于qt:zlib开发笔记三zlib库介绍在ubuntu上进行arm平台交叉编译

前言 不便做嵌入式arm的穿插移植zlib库。 Zlib库 zlib被设计为一个收费的,通用的,法律上不受限制的-即不受任何专利爱护的无损数据压缩库,简直能够在任何计算机硬件和操作系统上应用。 下载 官网:http://www.zlib.net QQ群:1047134658(点击“文件”搜寻“zlib”,群内与博文同步更新) 穿插编译环境筹备步骤一:穿插编译链工具制作 (略) 步骤二:引入穿插编译链工具到环境变量 创立环境文件 touch env.sh 编辑文件 gedit env.shenv.sh#/bin/bashexport PATH=/home/yang/work/tool/gcc-sigmastar-9.1.0-2019.11-x86_64_arm-linux-gnueabihf/bin:$PATH (留神:PATH中的门路批改为穿插编译器的理论门路) 步骤三:启动控制台,并引入该文件source ../tool/env.sh 步骤四:验证 输出头几个字母,应用tab: 并查看具体的版本: zlib穿插编译步骤一:解压tar xvf zlib-1.2.11.tar.gz 步骤二:引入穿插编译器(请先执行“穿插编译环境筹备”)export CC=arm-linux-gnueabihf-9.1.0-g++ 步骤三:配置configure(CC则是穿插编译) 步骤四:编译makemake 通过多方面的钻研排除,最初发现是CC连贯的库与理论连贯库应用的gcc不同,批改如下: gedit makefile 步骤五:makemake 步骤六:装置sudo make installsudo make install 步骤七:查看编译后果 模块化 Ubuntu上对于库的模块化不蕴含库,模块化可参考《zlib开发笔记(一):zlib库介绍、编译和工程模板》 工程模板v1.0.0. 对应工程模板:zipDemo_v1.0.0_根底模板_zip库的根底环境.rar (该工程模板,因为ubuntu零碎问题而加载库为.so,所以疏忽模块中自带的dll,所以模块无需批改引入参数)。 上一篇:《zlib开发笔记(二):zlib库介绍、ubuntu平台编译和工程模板》下一篇:敬请期待...

August 23, 2021 · 1 min · jiezi

关于qt:QtMPlayer音乐播放器开发笔记一ubuntu上编译MPlayer以及Demo演示

若该文为原创文章,转载请注明原文出处本文章博客地址:https://hpzwl.blog.csdn.net/article/details/118713520 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) Qt开发专栏:三方库开发技术 前言 在ubuntu上实现MPlayer播放器播放音乐。 Demo Mplayer MPlayer是一款开源多媒体播放器,以GNU通用公共许可证公布。此款软件可在各支流操作系统应用,例如Linux和其余类Unix零碎、Windows及Mac OS X零碎。 MPlayer基于命令行界面,在各操作系统也可抉择装置不同的图形界面。mplayer的另一个大的特色是宽泛的输出设备反对。它能够在X11、Xv、DGA、OpenGL、SVGAlib、fbdev、AAlib、DirectFB下工作,且能应用GGI和SDL和一些低级的硬件相干的驱动模式(比方Matrox、3Dfx和Radeon、Mach64、Permedia3)。MPlayer还反对通过硬件MPEG解码卡显示,如DVB 和DXR3与Hollywood+。 MPlayer的开发始于2000年。最后的作者是 Arpad Gereoffy。MPlayer最后的名字叫"MPlayer - The Movie Player for Linux",不过起初开发者们简称其为"MPlayer - The Movie Player",起因是MPlayer曾经不仅能够用于Linux而能够在所有平台上运行。 下载 最新源码下载地址: http://mplayerhq.hu/design7/news-archive.html QQ群:1047134658(点击“文件”搜寻“MPlayer”,群内与博文同步更新) Ubuntu编译步骤一:下载解压tar xvf MPlayer-1.4.tar.xz 步骤二:configurecd MPlayer-1.4/./configure ./configure --yasm=’’ 步骤三:make,须要zlib库撑持,编译zlib库make 须要编译zlib库,须要先编译,请参照博文《libzip开发笔记(二):libzip库介绍、ubuntu平台编译和工程模板》。 sudo ldconfig步骤四:持续编译makemake 步骤五:装置sudo make installsudo make install 步骤六:播放测试 (留神:若是虚拟机,虚拟机的音量和选用主机的声卡须要抉择下) DemoWidget.h #ifndef WIDGET_H#define WIDGET_H#include <QMainWindow>#include <QThread>#include "MplayerManager.h"#include <QFileDialog>namespace Ui {class Widget;}class Widget : public QWidget{ Q_OBJECTpublic: explicit Widget(QWidget *parent = 0); ~Widget();protected: void initControls();protected slots: void slot_durationChanged(int duration); void slot_positionChanged(int position); void slot_finished(); void slot_mediaInfo(MplayerManager::MediaInfo mediaInfo);private slots: void on_pushButton_startPlay_clicked(); void on_pushButton_stopPlay_clicked(); void on_pushButton_pausePlay_clicked(); void on_pushButton_resume_clicked(); void on_horizontalSlider_sliderReleased(); void on_horizontalSlider_valueChanged(int value); void on_pushButton_mute_clicked(bool checked); void on_horizontalSlider_position_sliderReleased(); void on_horizontalSlider_position_sliderPressed(); void on_pushButton_browserMplayer_clicked(); void on_pushButton_defaultMplayer_clicked(); void on_pushButton_browserMusic_clicked();private: Ui::Widget *ui; QThread *_pMplayerManagerThread; MplayerManager *_pMplayerManager; bool _sliderPositionPressed;};#endif // WIDGET_HWidget.cpp ...

July 26, 2021 · 3 min · jiezi

关于qt:案例分享QtArm基于RV1126平台的内窥镜软硬整套解决方案视频监控物联网产品等等

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/118887433长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) 单干案例专栏:案例分享(体验Demo可下载,只定制) 自研产品系列计划 1. 基于瑞芯微的 RV1126 芯片平台; 2. 外接 USB 摄像头(OV9734、 OV6946、OV2740 等 UVC 模块)作为图像输出源; 3. 可通过 LED 显示屏或 HDMI 外接显示器进行实时显示; 4. 白平衡、解冻、主动背光、主动光源等性能;’ 5. 拍照性能,可设置拍照门路(U盘,SD卡,内置存储); 6. 录像性能,可设置录像门路(U盘,SD卡,内置存储); 7. 亮度调整,摄像头光源亮度调整; 8. 物理按键,包含拍照、录像、上下左右、菜单、默认亮度、抉择等等; 9. 定制开机界面; 10. 照片浏览器; 11. 视频播放器; 12. 其余各种定制控件; 对于定制 反对相干的软硬shang业定制(非shang业勿扰,无ye务不探讨技术细节) Demo 相干博客 《案例分享:Qt+Arm+Fpga医疗肾镜(又名内窥镜)(实时影像、解冻、拍照、白平衡、九宫格、录像、背光调整、硬件光源调整、光源手动主动调整、物理按键)》 硬件计划参数PCB 尺寸: 9068mm(LW)。SOC: RV1126。DDR: 2G。Flash: Spi Flash。接口: USB、 HDMI、 TF 卡等。电源: DC5/12V。 若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/118887433

July 21, 2021 · 1 min · jiezi

关于qt:台达PLC开发笔记二台达PLC设置主机通讯参数为RTU并成功通讯

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/118480597 长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) 其余(编程相干)上一篇:《台达PLC开发笔记(一):台达PLC连贯介绍,别离应用485、网口与台达PLC建设连贯》下一篇:敬请期待... 前言 后面应用485和网口与台达胜利建设通信,然而485是应用用的ASICC模式,少数状况下是应用RTU模式晋升通信效率。 下载安装台达ISPSoft软件 官网下载地址:https://downloadcenter.delta-china.com.cn/DownloadCenter?v=1&q=ISP&sort_expr=cdate&sort_dir=DESC 配置须要通过网线,应用HWCONFIG软件进行配置: (先装置后面的commgr通信管理软件) 下载后,如下图: 装置后,如下图: 配置之前测试应用485测试ASCII通信形式 应用485测试RTU通信形式 (端口默认是ASCII形式,RTU形式会返回一个固定长度固定的数据,应该是谬误检测) 应用ISPSoft软件配置台达PLC的485由ASCII转为RTU步骤一:关上软件 步骤二:创立工程 步骤三:关上网络配置HWCONFIG 步骤四:配置COM1口等参数(ASCII改为RTU) (若没有之前应用网线连贯,会呈现提醒,之前是须要先网线连贯到PLC的) 正在下载,提醒解决中,如下图: 下载超时,是须要应用网口连贯的。 步骤五:应用网线形式连贯PLC 步骤六:再次下载新的配置(原先为485当初为网线IP) 步骤七:下载胜利,应用485RTU进行测试 (为hex了,不是acsii了,胜利) 入坑入坑一:应用Qt的modbus485读取失败问题 Qt的modbus全方面测试读取M、D、Y、X对应的寄存器左近几个值都为0。 解决 间接应用modbus rtu测试 是没有问题的,然而Qt返回值仍然是: 其余局部在此尝试过了,总共四种类型,相干的M、D、X、Y变量都设置过相似的,全副读取胜利,然而值都为0与理论不符,如同架空了一样。 论证(2021年04月25日补充) 测试单个线圈,应用libmodbus能够读出来 测试单个线圈,应用QModbus还是无奈读出 测试读取寄存器,应用libmodbus能够读出 测试读取寄存器,应用QModbus能够读出 ### 论断 Qt有些货色的确鸡肋,没必要死磕。 上一篇:《台达PLC开发笔记(一):台达PLC连贯介绍,别离应用485、网口与台达PLC建设连贯》下一篇:敬请期待...

July 12, 2021 · 1 min · jiezi

关于qt:QGraphicsItem-类型转换

在应用 Graphics View Framework 的时候,咱们少不了要对 QGraphicsItem 对象进行类型转换。我经验的尤为经典的场景就是在 QGraphicsView::mousePressEvent 中应用 QGraphicsView::itemAt 获取以后被选中的 item。而后对其进行类型转换之后再进行某些操作。 QGraphicsItem 只是一个基类,如果咱们想在 runtime 取得实在的子类类型,就必须对其进行类型转换。Type casting 相干的函数有泛滥抉择,有 C++ 的 static_cast 、dynamic_cast 和 Qt 的 qobject_cast 。但遗憾的是这三个函数对 QGraphicsItem 的类型转换并不非常敌对。 先说说 dynamic_cast ,这个函数看似完满,而且失败也会返回 nullptr 。但咱们应尽量避免应用 RTTI。 而后就是 static_cast ,这个函数其实就是通过笼罩固定长度的内存进行类型转换。因而咱们并不能通过这种强转判断类型的转换是否胜利。 咱们无妨对 dynamic_cast 和 static_cast 做一些小试验。从试验1的运行后果能够看出,如果把 if statement 正文掉的话,程序会解体。起因是 c 为 nullptr 。再来看看试验2的运行后果是输入 "b" ,调用的是类 B::hello,意料之外的后果。 class A{public: virtual void hello() { qDebug() << a; };private: const char* a {"a"};};class B : public A{public: void hello() override { qDebug() << b; }private: const char* b {"b"};};class C : public A{public: void hello() override { qDebug() << c; }private: const char* c {"c"};};// 试验1int main(){ A* b = new B; auto c = dynamic_cast<C*>(b); // if (c != nullptr) c->hello(); // crash!!!}// 试验2int main(){ A* b = new B; auto c = static_cast<C*>(b); c->hello(); // 输入 b}最初就是 qobject_cast ,它能够说是 Qt 的亲儿子。但它并不能用于 QGraphicsItem,归根到底 QGraphicsItem 没有继承 QOject 。如果想要用 qobject_cast 的话,能够抉择 QGraphicsObject 作为基类。 ...

June 30, 2021 · 2 min · jiezi

关于qt:Qt-绘制-PEFrameFocusRect

在应用 Qt 开发图形界面的时候,咱们不免要对各种控件进行从新绘制。记录一下我绘制 PE_FrameFocusRect 的通过。 PE_FrameFocusRect绘制 QListWidgetItem 的选中框须要用到 QStyle::drawPrimitive 。并且须要创立一个 QStyleOptionFocusRect 对象 ,它蕴含一个成员变量 QColor backgroundColor 。依据 Qt 文档我一开始认为批改这个背景色彩,就能够简略地批改 PE_FrameFocusRect 的背景色,但事实上并非如此。 QColor QStyleOptionFocusRect::backgroundColorThis variable holds the background color on which the focus rectangle is being drawnThe default value is an invalid color with the RGB value (0, 0, 0). An invalid color is a color that is not properly set up for the underlying window system.起初我去翻了一下源码才发现,QStyle::drawPrimitive 在描述 PE_FrameFocusRect 的时候基本没有用到这个成员。用到的却是 QPalette::Highlight 所保留的色彩,而后对其作一些批改。 ...

June 29, 2021 · 2 min · jiezi

关于qt:Qt-QGraphicsView应用定点缩放

性能:以鼠标地位为中心点定点缩放 原理阐明实现在光标地位缩放画布的成果能够了解为,光标所对应到画布上的坐标点在缩放之前和之后都持续对应在光标所在的地位。而个别缩放画布,画布会以画布的左上角为固定点缩放。 所以在每一次缩放实现后,咱们须要把画布上 光标对应的地位 挪动回去,就能够实现目标成果。 a.计算原理: 1.找到光标所对应到画布坐标零碎的地位点,这里记作target 2.缩放(参见如下代码块) 3.按缩放比例计算失去 经验缩放后 target的新地位_target 4.计算位移量 5.挪动画布 缩放局部#define ZOOM_IN_TIMES -5#define ZOOM_OUT_TIMES 5void scaledemo::wheelEvent(QWheelEvent *event){ qreal s=0; bool in = true; bool out = true; if(event->delta() >= 0) { scaleValue += 1; } if(event->delta() < 0) { scaleValue -= 1; } if( scaleValue < ZOOM_IN_TIMES ) { scaleValue = ZOOM_IN_TIMES; in = false; return; }else if( scaleValue > ZOOM_OUT_TIMES ) { scaleValue = ZOOM_OUT_TIMES; out = false; return; } if(in) { s = qPow(1.01,event->delta()/10); } if(out) { s = qPow(1/1.01,-event->delta()/10); } scale(s,s);}

June 8, 2021 · 1 min · jiezi

关于qt:Qt小知识-用一篇小短文带你进入-QML-的美妙世界

大家好,我是老吴。 明天用几个小例子带大家疾速入门 QML 编程。 0. 什么是 QML?QML 是一种用于形容应用程序用户界面的申明式编程语言,Qt Quick 则是 QML 利用的规范库。 我为什么抉择学习 QML?易上手; 可读性高; 学习材料多,有各种文档和示例; 跨平台; 性能不差,晦涩度还行。 1. 如何创立 QML 利用?举个栗子:在 Qt Creator 顺次点击: -> File -> New File or Project -> Applications -> Qt Quick Application 而后一路点击 next 直到 finish 。 批改 main.qml :`// 文件 main.qml``import QtQuick 2.12``import QtQuick.Window 2.12``Window {` `visible: true` `width: 320` `height: 240` `title: qsTr("Hello World")` `Rectangle {` `width: 320` `height: 240` `color: "green"` `Text {` `anchors.centerIn: parent` `text: "Hello, World!"` `}` `}``}`这样就实现了你的第一个 QML 程序,它的作用是在一个绿色的长方形块上显示 "Hello World!"。 运行成果: 这里的 Window、Rectangle、Text 都是 QML 里的类型,术语 为 QML Type。 ...

April 27, 2021 · 2 min · jiezi

关于qt:Qt-官方示例-网络入门-http-下载小工具

哈喽,我是老吴。 最近又玩了一下 Qt,给大家分享一点 Qt 相干的基础知识吧。 我集体十分喜爱 Qt,它几乎就是我这个 C++ 手残党的利器。 学习 Qt 的最佳路径应该是浏览官网的手册和示例,明天要分享的就是 Qt 官网提供的一个示例。 http 下载小工具: 点击查看大图 源码文件: `Makefile``httpwindow.cpp``main.cpp``httpwindow.h``http.pro`上面疾速地阐明一下如何实现这个小工具, let's go. 目录: `1. 实现主界面``2. 解析 URL 和创立空文件``3. 发送 http 申请和接管 http 数据``4. 增加进度条``5. 下载实现后主动关上文件`1. 实现主界面主界面基于 QDialog,包含: 3 个 LineEdit;1 个 CheckBox;1 个 Label;2 个 Button;代码如下: `httpwindow.h``class HttpWindow : public QDialog``{` `...``}````````httpwindow.cpp``HttpWindow::HttpWindow(QWidget *parent)` `: QDialog(parent)` `...``{` `QFormLayout *formLayout = new QFormLayout;` `formLayout->addRow(tr("&URL:"), urlLineEdit);` `formLayout->addRow(tr("&Download directory:"), downloadDirectoryLineEdit);` `formLayout->addRow(tr("Default &file:"), defaultFileLineEdit);` `formLayout->addRow(launchCheckBox);` `QVBoxLayout *mainLayout = new QVBoxLayout(this);` `mainLayout->addLayout(formLayout);` `mainLayout->addWidget(statusLabel);` `QPushButton *quitButton = new QPushButton(tr("Quit"));` `QWidget::close);` `QDialogButtonBox *buttonBox = new QDialogButtonBox;` `buttonBox->addButton(downloadButton, QDialogButtonBox::ActionRole);` `buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole);` `mainLayout->addWidget(buttonBox);``}`用 QFormLayout 对 3 个编辑框进行表单布局,而后再QVBoxLayout 来进行整体的垂直布局。 main.cpp: `int main(int argc, char *argv[])``{` `...` `HttpWindow httpWin;` `httpWin.show();` `...``}`运行成果: 此时只有界面, Download 按键并没有理论的性能。 2. 解析 URL 和创立空文件当用户点击 Downaload 按键时,须要解析用户输出的 URL 并关上一个新文件用于保留将要下载的文件。 ...

April 25, 2021 · 1 min · jiezi

关于qt:pyqt5-嵌于主界面状态栏的进度条

写在后面放在状态栏处的进度条。本想放在主界面,然而没找到相干代码。 代码# -*- coding: utf-8 -*-from PyQt5 import QtCore, QtWidgetsfrom PyQt5.QtWidgets import QProgressBar, QLabel, QApplication, QMainWindowfrom PyQt5.QtCore import QBasicTimerimport sysclass Ui_MainWindow(QMainWindow): def __init__(self,parent=None): super(Ui_MainWindow,self).__init__(parent) self.setupUi() #这里能够定义一些为以后类所用的全局变量 self.filepath = '' def setupUi(self): #设置窗口对象名称 self.setObjectName("MainWindow") #设置窗口大小 self.resize(800, 600) #定义按钮 self.startButton = QtWidgets.QPushButton(self) # 设置按钮对象名称(不是按钮显示内容) self.startButton.setObjectName("pred") #设置按钮地位 self.startButton.setGeometry(QtCore.QRect(10, 300, 93, 28)) #设置按钮显示内容 self.startButton.setText("开始") #为按钮绑定事件(点击按钮时就触发) self.startButton.clicked.connect(self.predict) #这里我绑定的是具体的业务处理函数,如果你想点击按钮就开始走进度条,则用上面这句 # 也能够间接为按钮绑定事件,点击按钮时,就开始走进度条 # self.startButton.clicked.connect(self.onStart) #定义状态栏 self.statusbar = QtWidgets.QStatusBar(self) # 将状态栏设置为以后窗口的状态栏 self.setStatusBar(self.statusbar) # 设置状态栏的对象名称 self.statusbar.setObjectName("statusbar") #设置状态栏款式 self.statusbar.setStyleSheet('QStatusBar::item {border: none;}') # 定义文本标签 self.statusLabel = QLabel() # 设置文本标签显示内容 self.statusLabel.setText(" 筹备 ") #定义程度进度条 self.progressBar = QProgressBar() # 设置进度条的范畴,参数1为最小值,参数2为最大值(能够调得更大,比方1000 self.progressBar.setRange(0, 100) # 设置进度条的初始值 self.progressBar.setValue(0) #设置定时器(走进度条的时候须要应用,否则进度条不会变动,而是固定不变 self.timer = QBasicTimer() self.step = 0 # 往状态栏中增加组件(stretch应该是拉伸组件宽度) self.statusbar.addPermanentWidget(self.startButton, stretch=0) self.statusbar.addPermanentWidget(self.statusLabel, stretch=2) self.statusbar.addPermanentWidget(self.progressBar, stretch=10) #其余界面设置 self.retranslateUi() QtCore.QMetaObject.connectSlotsByName(self) def retranslateUi(self): _translate = QtCore.QCoreApplication.translate #设置窗口题目 self.setWindowTitle(_translate("MainWindow", "testLoading")) # 每一个QObject对象或其子对象都有一个QObject.timerEvent办法。 # 为了响应定时器的超时事件,须要重写进度条的timerEvent办法。 def timerEvent(self, event): if self.step >= 100: self.timer.stop() # 批改文本标签显示内容 self.statusLabel.setText(" 预测实现 ") # 启用按钮 self.startButton.setEnabled(True) # 批改按钮显示内容 self.startButton.setText("开始") return #累计步数 self.step = self.step + 1 #批改进度条的值 self.progressBar.setValue(self.step) def onStart(self): # 批改文本标签显示内容 self.statusLabel.setText(" 请稍后 ") #禁用按钮 self.startButton.setEnabled(False) #批改按钮显示内容 self.startButton.setText("预测中...") #应用定时器的start()办法启动定时器,激活进度条。其中: # 参数1:超时工夫;参数2:到了超时工夫后,接管定时器触发超时事件的对象。 self.timer.start(100, self) #解决具体的业务逻辑,如调用深度学习模型进行预测。 def predict(self): self.onStart() ################用print模仿模型的调用#################### print('predict.......')if __name__ == '__main__': app = QApplication(sys.argv) ui = Ui_MainWindow() ui.show() sys.exit(app.exec_())成果动图如果看不到效果图,请返回此页面查看https://blog.csdn.net/qq_42772612/article/details/115557955 ...

April 9, 2021 · 1 min · jiezi

关于qt:pyqt5-设置按钮圆角

2种办法1.能够间接在Qt Designer中设置。详见此文:在Qt designer中实现按钮的圆角设置 2.pycharm中通过代码设置: 要害是这行代码(引号中设置款式)self.pushButton.setStyleSheet('') from PyQt5 import QtCore, QtWidgetsfrom PyQt5.QtWidgets import QApplication, QMainWindowimport sysclass Ui_MainWindow(QMainWindow): def __init__(self,parent=None): super(Ui_MainWindow,self).__init__(parent) self.setupUi() def setupUi(self): self.setObjectName("MainWindow") #窗口大小 self.resize(800, 600) #定义按钮 self.pushButton = QtWidgets.QPushButton(self) #设置按钮地位(x,y,width,height) self.pushButton.setGeometry(QtCore.QRect(10, 240, 93, 28)) #设置按钮内容 self.pushButton.setText("button") #设置按钮对象名(不是显示内容 self.pushButton.setObjectName("pushButton") #设置按钮圆角 self.pushButton.setStyleSheet('background-color: rgb(192, 192, 192);border-radius: 10px; border: 2px groove gray;border-style: outset;')if __name__ == '__main__': app = QApplication(sys.argv) ui = Ui_MainWindow() ui.show() sys.exit(app.exec_())运行后果下面那段代码放到一个py文件中,间接运行即可。 集体审美无限,按钮色彩较丑,轻喷。色彩能够参照此文进行调整:RGB色彩表 参考在Qt designer中实现按钮的圆角设置 RGB色彩表

April 9, 2021 · 1 min · jiezi

关于osg:项目实战QtOSG三维点云引擎支持原点缩放单独轴或者组合多轴拽拖旋转支持导入点云文件

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/115416147 长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) 开发专栏:商业我的项目实战OSG与OsgEarth三维开发专栏 需要 开发基于osg的三维点云引擎模块。 1.基于x,y,z坐标轴。 2.可设置原点,设置缩放比例。 3.可设置y轴和z轴单位。 4.三轴中,XY为2D图的程度、竖直方向;Z轴,对应高度图中的double型高度。 5.引擎核心可设置。 6.可设置引擎中心点,能够拽拖绕中心点旋转模型。 7.能够独自以引擎中心点绕X,Y,Z轴旋转,拽拖时旋转. 8.能够组合XY,XZ,YZ轴旋转,拽拖时旋转。 9.依据输出的bmp图片以及建模的txt高度文件,出现点云。 10.可复位坐标系,可分明导入的点云。 附赠性能: 11.反对导入图片,随机高度进行点云模仿。 12.反对导入cvs点云文件(以后仅解析点)。 体验下载地址 CSDN免积分下载地址:https://download.csdn.net/download/qq21497936/16388051 QQ群下载地址:1047134658(点击“文件”搜寻“osg3D”,群内与博文同步更新) Demo Demo局部源码#ifndef OSGWIDGET_H#define OSGWIDGET_H/************************************************************\ * 控件名称: osg3D点云定制 * 控件形容: * 1.根底三维框架 * 2.可设置中心点 * 3.鼠标中键按下后可挪动中心点 * 4.反对导入bmp,bmp+z文件,cvs点云文件 * 5.反对清空数据,复位视角等操作 * 作者:红模拟 联系方式:QQ21497936 * 博客地址:https://blog.csdn.net/qq21497936 * 著作权信息 * 作者:红瘦子(AAA红模拟) * 公司:长沙红瘦子网络科技有限公司 * 博客专家地址:blog.csdn.net/qq21497936/article/details/102478062 * 联系方式:QQ(21497936) 微信(yangsir198808) * 版本信息 * 日期 版本 形容 * ... ... ... * 2021年04月02日 v2.0.0 3D点云导入,XYZ周固定旋转,复位,清空 导入文件格式反对导入bmp,定制bmp+z,cvs文件\************************************************************/#include <QWidget>#include "OsgViewerWidget.h"#include "MyManipulator.h"class AnimationPathCameraMainpulator;namespace Ui {class OsgWidget;}class OsgWidget : public QWidget{ Q_OBJECTpublic: explicit OsgWidget(QWidget *parent = 0); ~OsgWidget();public: bool getFixXAxis() const; void setFixXAxis(bool fixXAxis); bool getFixYAxis() const; void setFixYAxis(bool fixYAxis); bool getFixZAxis() const; void setFixZAxis(bool fixZAxis);public: bool loadFile(QString imageFile, int minZ, int maxZ); bool loadFile(QString imageFile, float z); bool loadFile(QString imageFile, QString cloudZFile); bool loadFile(QString cvsFile, QColor color); void clear(); void resetCoordinate();protected: void initOsg(); // osg初始化 void loadNode(osg::ref_ptr<osg::Node> pNode); // 加载场景根节点protected: osg::ref_ptr<osg::Node> create3DPointCloud(); // 创立总场景 osg::ref_ptr<osg::Node> createAxisAndGrid(); // 创立坐标轴和线格 osg::ref_ptr<osg::Node> createTickLabel(); // 创立坐标轴的tickLabel和单位 osg::ref_ptr<osg::Node> createCloud(std::vector<osg::Vec3> &vectorVec3Vectex, std::vector<osg::Vec4> &vectorVec4VectexColor); // 创立点云protected: void resizeEvent(QResizeEvent *event); void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); void mouseDoubleClickEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); void wheelEvent(QWheelEvent* event);private: Ui::OsgWidget *ui;private: OsgViewerWidget *_pViewer; // osg场景嵌入Qt外围类 osg::ref_ptr<osg::MatrixTransform> _pRoot; // osg场景根节点private: float _xDistance; // x轴单个tick间距 int _xTickNumber; // x轴tick数(例如:5的时候,是6个,0~5) float _yDistance; // y轴单个tick间距 int _yTickNumber; // y轴tick数(例如:5的时候,是6个,0~5) float _zDistance; // z轴单个tick间距 int _zTickNumber; // z轴tick数(例如:5的时候,是6个,0~5) QString _zUnit; // z轴单位 float _zTickLabelOffset; // z轴坐标偏移 QString _yUnit; // y轴单位 float _zTickUnitLabelOffset; // z轴坐标偏移 QColor _gridColor; // 轴色彩 QColor _labelColor; // 轴tickLabel的色彩 osg::ref_ptr<osg::Node> _pNode; // 模型 osg::ref_ptr<MyManipulator> _pManipulator; // 自定义漫游器 osg::Vec3d _eyeVect3D; // 原始坐标,用于复位原始视角 osg::Vec3d _centerVect3D; // 原始坐标,用于复位原始视角 osg::Vec3d _upVect3D; // 原始坐标,用于复位原始视角};#endif // OSGWIDGET_H ...

April 6, 2021 · 2 min · jiezi

关于qt:Qt开发Activex笔记二Qt调用Qt开发的Activex控件

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113789693 长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) Qt开发专栏:开发技术上一篇:《Qt开发Activex笔记(一):环境搭建、根底开发流程和演示Demo》下一篇:敬请期待... 前言 开发Activex控件,以供其余应用程序调用,本篇章解说Qt调用Activex控件,不限于Qt开发的Activex控件。 Demo QAxWidget概述 QAxWidget类是包装ActiveX控件的QWidget。 QAxWidget能够实例化为空对象,带有它应该包装的ActiveX控件的名称,或者带有指向ActiveX控件的现有接口指针。ActiveX控件的属性、办法和事件仅应用QAxBase反对的数据类型,能够作为Qt属性、插槽和信号应用。基类QAxBase提供了一个API,能够通过IUnknown指针间接拜访ActiveX。 QAxWidget是一个QWidget,通常能够这样应用,例如,它能够组织在一个widget层次结构和布局中,或者充当一个事件过滤器。反对规范小部件属性,例如enabled,但它依赖于ActiveX控件来实现对环境属性(例如palete或font)的反对。QAxWidget试图提供必要的提醒。 然而,不能从新实现特定于Qt的事件处理程序,如mousePressEvent或keyPressEvent,并冀望牢靠地调用它们。嵌入式控件齐全笼罩QAxWidget,通常解决用户界面自身。应用特定于控件的API(即侦听控件的信号),或应用规范COM技术,如window过程子类化。 QAxWidget还从QAxBase继承了大部分与ActiveX相干的性能,特地是dynamicCall()和querySubObject()。 正告:能够将QAxWidget子类化,但不能在子类中应用Q_OBJECT宏(生成的moc文件将不会编译),因而无奈增加更多信号、插槽或属性。这种限度是因为运行时生成的元对象信息造成的。要解决此问题,请将QAxWidget聚合为QObject子类的成员。 Qt调用Activex办法步骤一:注册activex控件 运行之前先要注册,应用Qt下自带的idc注册一下。 idc -regserver activeHelloWorldDemo.dll 步骤二:确认activeQt控件的clsid 查看一下,关上注册表并搜寻一下,确认clsid,如下图: "2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"步骤三:应用QAxWidget调用QAxWidget *pAxWidget = new QAxWidget();pAxWidget->resize(400, 320);pAxWidget->setControl("2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC");pAxWidget->show(); 源码#include <QApplication>#include <QAxWidget>int main(int argc, char *argv[]){ QApplication a(argc, argv); QAxWidget *pAxWidget = new QAxWidget(); pAxWidget->resize(400, 320); pAxWidget->setControl("2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"); pAxWidget->show(); return a.exec();} 上一篇:《Qt开发Activex笔记(一):环境搭建、根底开发流程和演示Demo》下一篇:敬请期待...

February 14, 2021 · 1 min · jiezi

关于qt:Qt开发Activex笔记一环境搭建基础开发流程和演示Demo

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113773009 长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) Qt开发专栏:开发技术上一篇:无下一篇:敬请期待... 前言 应用C#开发动画,绘图性能跟不上,更换计划应用Qt开发Qt的控件制作成OCX以供C#调用,而activex则是ocx的更高级模式。 QtCreator是没有Active控件我的项目的,所有须要应用VS,笔者应用VS2019开发。 筹备工作 Qt5.15.2 + VS2019 + vs tools,搭建根底开发环境不再赘述。 开发第一个Qt Activex:Hello world步骤一:新建Qt ActiveQt Server我的项目 步骤二:拖一个QLabel,输出”Hello world” 步骤三:生成呈现谬误“MSB3073” 须要应用管理员权限关上VS2019软件。 步骤四:生成release和debug版本 步骤五:注册activex控件 运行之前先要注册,应用Qt下自带的idc注册一下。 idc -regserver activeHelloWorldDemo.dll 步骤六:调用activeQt控件 查看一下,关上注册表并搜寻一下,确认clsid,如下图: 创立一个html,而后输出如下内容: <html><head><title>activeQtDemo</title></head><body> <object id="object" classid="CLSID:2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"> <!-- 以下为入坑了 --> <!-- classid="2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"> --> [Object not available! Did you forget to build and register the server?] </object></body></html> 应用IE运行,active是微软特有的,其余浏览器不反对,如下图: 入坑入坑一:调用控件失败问题 起因 因为classid的格局谬误 解决<html><head><title>activeQtDemo</title></head><body> <object id="object" classid="CLSID:2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"> <!-- 以下为入坑了 --> <!-- classid="2F12BFB8-137D-4DC2-9A93-634EFE5A6DFC"> --> [Object not available! Did you forget to build and register the server?] </object></body></html> ...

February 11, 2021 · 1 min · jiezi

关于qt:地图开发笔记二Qt与百度地图js交互的基础Qt向Js发送指令定位各大省份与城市

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/112871383 长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) Qt开发专栏:三方库开发技术上一篇:《地图开发笔记(一):百度地图介绍、应用和Qt内嵌地图Demo》下一篇:继续更新... 前言 Qt要与百度地图交互,百度地图提供的JS,那么交互就是Qt与JS交互,本章Qt向JS交互发送指令。 Demo Qt管制JS Qt管制JS绝对界面,间接应用QWebEnginePage的runJavaScript接口即可,函数接口如下: void runJavaScript(const QString& scriptSource);void runJavaScript(const QString& scriptSource, quint32 worldId);void runJavaScript(const QString& scriptSource, const QWebEngineCallback<const QVariant &> &resultCallback);void runJavaScript(const QString& scriptSource, quint32 worldId, const QWebEngineCallback<const QVariant &> &resultCallback);参数一:执行的js脚本内容 其余参数请自行查看。 百度地图API设置中心点和缩放等级 示例var map = new BMap.Map("allmap");var point = new BMap.Point(116.331398,39.897445);map.centerAndZoom(point,12);定位以后所在的城市 LocalCity定位类 LocalCityOptions该类应用回调函数传回后果 LocalCityResult定位后果的后果类形容 示例function myFun(result){ var cityName = result.name; map.setCenter(cityName); alert("以后定位城市:"+cityName);}var myCity = new BMap.LocalCity();myCity.get(myFun); 设置地图缩放等级 外围类Map 示例map.setZoom(13)定位指定的城市 外围类Map ...

January 21, 2021 · 1 min · jiezi

关于qt:项目实战QtArmFpga医疗肾镜又名内窥镜实时影像冻结拍照白平衡九宫格

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/111241205长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) 开发专栏:我的项目实战 需要 1. 屏幕分辨率1920 x 1080; 2. 白平衡、解冻、主动背光、主动光源等性能;’ 2. 拍照性能,可设置拍照门路(U盘,SD卡,内置存储); 3. 录像性能,可设置录像门路(U盘,SD卡,内置存储); 4. 亮度调整,摄像头光源亮度调整; 5. 物理按键,包含拍照、录像、上下左右、菜单、默认亮度、抉择等等; 6. 定制开机界面; 7. 照片、视频九宫格浏览控件; 8. 照片浏览器; 9. 视频播放器; 10. 可查看照片、视频同时反对按键对照片和视频的操作; 11. 对存储控件的资源浏览器控件’,并可对其复制、粘贴、删除等操作; 12. 设置工夫日期,仿苹果滑动成果; 13. 其余各种定制控件; 留神 受限于老本(计划整体老本,较同行业最低),一直压缩的老本,导致该产品的呈现要害难点,其在于fpga上的仿arm跑linux的芯片性能等同于2011年的arm程度,通过fpga+arm+qt三方的代码优化和内存优化。’ Demo 软件界面 物理按键 须要模仿物理按键,在整个零碎运行时对所有按键进行对应的业务解决,按键如下图: 要害代码EndoscopeWidget.h #ifndef ENDOSCOPEWIDGET_H#define ENDOSCOPEWIDGET_H#include <QWidget>#include <QButtonGroup>#include <QThread>#include <QLabel>#ifdef LINUX#include "X264Manager.h"extern "C" { #include "fpga_comm_app.h" #include "common.h"}#endif#ifndef LINUX#define LOCAL_DIR ("local")#define USB1_DIR ("usb1") // usb#define USB2_DIR ("usb2") // usb默认门路#endif#define PICTURE_DIR ("Picture")#define VIDEO_DIR ("Video")#define DEBUG_X264_SRC (1) // 1 - 模仿数据源测试x264, 0 - 应用fpga数据源操作x264库#define DEBUG_SAVE_PATH (1) // 1 - 存储到利用目录下(arm、pc均可用), 0 - 存储到U盘(必须在arm上)#define MKDIR_USE_SHELL (1) // 1 - 应用mkdir创立目录, 0 - 应用qt自带的创立目录(倡议应用1)#define SKIP_FRAMES (0) // 1 - 是跳帧编码, 0 - 不跳帧#define SKIP_NUM (0) // 跳帧时有用,以后帧数 % SKIP_NUM== 0时跳帧#define X264_USE_THREAD (0) // 1 - x264编码应用另外的线程(须要拷贝缓存), 0 - 主线程间接调用#define CFG_FILE ("cfg") // 配置文件namespace Ui {class EndoscopeWidget;}class EndoscopeWidget : public QWidget{ Q_OBJECTpublic: enum LANGUAGE_TYPE { // 语言类型 LANGUAGE_TYPE_CHINESE_SIMPLE = 0x00, LANGUAGE_TYPE_ENGLISH, LANGUAGE_TYPE_CHINESE_TRADITION }; enum SAVE_LOCATION { // 存储地位 SAVE_LOCATION_LOCAL = 0x00, SAVE_LOCATION_USB1, SAVE_LOCATION_USB2 }; enum FUNCTION_TYPE { // 性能类型 FUNCTION_TYPE_NO_USE = 0x00, FUNCTION_TYPE_PHTOTO, FUNCTION_TYPE_RECORD, FUNCTION_TYPE_FREEZE, FUNCTION_TYPE_WHITE_BALANCE_CORRECT };public: explicit EndoscopeWidget(QWidget *parent = 0); ~EndoscopeWidget();signals: void signal_recvYuv(QByteArray byteArray);protected: void addFont(); // 增加字体 void loadCfg(); // 加载配置文件 void saveCfg(); // 存储配置文件 void updateDate(); // 更新日期 void updateLocateState(); // 更新本地local地位使能 void mkdir(QString currentDir); // 切换存储的时候须要创立文件夹protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event);protected slots: void slot_labelInfoTimeOut();protected slots: void slot_backgroundLightBrightnessValueChanged(int value); void slot_lightSourceBrightnessValueChanged(int value);protected slots: void slot_dateChanged(); // 日期扭转更新 void slot_languageButtonClicked(QAbstractButton *pBtn); // 语言按钮(中文简体、English、中文繁体) void slot_locateLocationClicked(QAbstractButton *pBtn); // 存储地位(本机、USB1,USB2) void slot_key1ButtonClicked(QAbstractButton *pBtn); // 按键一性能(不必、拍照、录像、解冻、白平衡校对) void slot_key2ButtonClicked(QAbstractButton *pBtn); // 按键二性能(不必、拍照、录像、解冻、白平衡校对) void slot_doubleClickedVideoFile(QString filePath); // 双击选中视频文件private slots: // 左侧菜单 void on_pushButton_photograph_clicked(); // 拍照 void on_pushButton_record_clicked(bool checked); // 录像 void on_pushButton_freezeScreen_clicked(bool checked); // 解冻 void on_pushButton_whiteBalanceCorrect_clicked(); // 白平衡校对 void on_pushButton_defaultLight_clicked(); // 默认亮度 void on_pushButton_photoSee_clicked(); // 图片查看private slots: // 右侧菜单 void on_pushButton_lightSourceSet_clicked(); // 光源亮度设置 void on_pushButton_dateSet_clicked(); // 工夫日期设置 void on_pushButton_languageSet_clicked(); // 语言设置 void on_pushButton_key1Set_clicked(); // 按键一设置 void on_pushButton_key2Set_clicked(); // 按键二设置 void on_pushButton_backgroundLightSet_clicked(); // 背光亮度设置 void on_pushButton_photoVideoSet_clicked(); // 照片/录像文件设置 void on_pushButton_set_clicked(bool checked); // 设置返回private slots: // 文件操作:左侧操作图片菜单 void on_pushButton_delete_clicked(); // 文件操作:删除 void on_pushButton_selectAll_clicked(); // 文件操作:抉择所有 void on_pushButton_copy_clicked(); // 文件操作:复制 void on_pushButton_paste_clicked(); // 文件操作:粘贴 void on_pushButton_back_clicked(); // 文件操作:返回private slots: void on_pushButton_startPlay_clicked(); // 播放器:播放 void on_pushButton_pause_clicked(); // 播放器:暂停 void on_pushButton_resume_clicked(); // 播放器:复原 void on_pushButton_stop_clicked(); // 播放器:进行 void on_pushButton_playerBack_clicked(); // 播放器:返回private: Ui::EndoscopeWidget *ui; QList<QString> _listCopyFile; // 复制的文件列表 QButtonGroup _buttonGroupLanguage; // 语言选择 QButtonGroup _buttonGroupKey1Function; // 按键1性能 QButtonGroup _buttonGroupKey2Function; // 按键2性能 QButtonGroup _buttonLocation; // 存储地位 QString _filePath; // 播放地址 bool _isLoopSaveImageIndex; int _imageIndex; // 当天拍照的序号(从0开始) bool _isLoopSaveVideoIndex; int _videoIndex; // 当天录像的序号(从0开始) QString _cfgFile; // 配置文件 LANGUAGE_TYPE _language; // 以后语言 SAVE_LOCATION _saveLocation; // 以后存储地位 FUNCTION_TYPE _key1Function; // 按键1性能 FUNCTION_TYPE _key2Function; // 按键2性能 int _backgroundLightBrightness; // 背光亮度 int _lightSourceBrightness; // 光源亮度 QString _storeDir; QString _photoDir; // 辅助变量:以后拍照文件夹 QString _videoDir; // 辅助变量:以后视频文件夹 QString _fileName; // 辅助变量:存储文件名称#ifdef LINUX static QThread *_pX264ManagerThread; // x264视频编码线程 static X264Manager *_pX264Manager; // x264治理类 static int _index;private: QTimer *_pTimer;protected slots: void slot_timeOut();public: static bool _recording; static int fpga_com_read_record_data_handler_t(char *buffer, int length);#endif QTimer *_pTimerInfo; // 计时器用于显示 QLabel *_pLabelRecIcon; // 图标 QLabel *_pLabelRecord; // 图标 QLabel *_pLabelInfo; // 提醒Label};#endif // ENDOSCOPEWIDGET_HEndoscopeWidget.cpp ...

December 18, 2020 · 7 min · jiezi

关于qt:项目实战Qt管道焊接参数条码打印系统条码打印机TSC-244-Pro打印条码打印中文打印字符多张连续打印

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110973861长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) 开发专栏:我的项目实战 需要 电脑端通过条码打印机TSC-TTP244 Pro: 1. 打印出尺寸为60*30cm 2. 条码打印机TSC-TTP244 Pro 不干胶纸 (不须要碳带,热敏纸) 3. windows零碎要求用QT编写程序,并加上必要的正文(所有源代码要给咱们,包含SDK) 4. 界面须要适应不同分辨率的电脑 5. 条码款式如下: Demo 硬件:条码打印机TSC 244 Pro v1.0.0 若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110973861

December 15, 2020 · 1 min · jiezi

关于qt:项目实战QtiMax6生命探测仪探测静止目标动态目标生命目标探测半径雷达显示目标轨迹显示热力图过程回放

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110994486长期继续带来更多我的项目与技术分享,征询请加QQ:21497936、微信:yangsir198808 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) 开发专栏:我的项目实战 需要 申明探测仪 1. 扫描雷达状态显示:正在扫描 or 扫描进行; 2. 显示扫描雷达的林敏度; 3. 探测过程中的数据文件保留(用于跟踪和前期回放) 4. 探测仪连贯app的终端的状态显示; 5. 电池电量显示; 6. 多语言切换,中文/英文; 7. 探测指标二维成图显示界面,包含生命体、静止指标、动静指标; 8. 显示or暗藏动静指标的挪动轨迹; 9. 雷达探测过程中实时事实探测的后方障碍物物体等,同时转换为一维火山图显示; 10. 后方探测间隔的、方位范畴‘、灵敏度设置; 11. 探测文件实时保留; 12. 探测文件的探测过程回放; Demo 硬件 若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110994486

December 12, 2020 · 1 min · jiezi

关于qt:项目实战Qt西门子PLC通讯调试和模拟工具包含PLC上位机通讯PLC服务器

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/110071837各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中...(点击传送门) Qt开发专栏:我的项目实战(点击传送门) 前言 西门西PLC、台达触摸屏、法兰克机床等等多年以前玩得比拟多,革新机床、培修机床、给机床编程等等,没事还能车个整机啥的,对于多年以前的研发革新,有工夫就重新整理下。 先上点有历史年代感的照片: 需要 基于Qt实现与PLC通信性能。 Demo 体验下载地址 CSDN:https://download.csdn.net/download/qq21497936/13239895 QQ群:1047134658(点击“文件”搜寻“plcCommunication”,群内与博文同步更新) v1.2.0 v1.1.0 要害源码 PlcWidget.h #ifndef PLCSERVERMANAGER_H#define PLCSERVERMANAGER_H/************************************************************\ * 控件名称:PlcServerManager * 性能形容:Plc通信服务器(用于模仿PLC,包含仿真DB数据空间) * 控件性能: * 1.惟一实例类 * 2.注册DB * 3.监听、进行监听 * 4.对所有事件进行反馈 * 作者:长沙红瘦子(AAA红模拟) * 博客专家地址:https://blog.csdn.net/qq21497936/article/details/102478062 * 联系方式:QQ(21497936) 微信(yangsir198808) * 版本信息 * 日期 版本号 形容 * 2020年11月23日 v1.0.0 根底性能 * 2020年12月01日 v1.1.0 减少客户端写入提醒信号\************************************************************/#include <QObject>#include <QMutex>#include <QHash>#include "snap7.h"class PlcServerManager : public QObject{ Q_OBJECTprivate: explicit PlcServerManager(QObject *parent = 0);public: static PlcServerManager * getInstance(); QHash<int, QByteArray> getHashDB2ByteArray() const;signals: void signal_listenStateChanged(bool listen); void signal_dataChanged();public slots: void slot_start(); void slot_stop(); void slot_listen(QString ip); void slot_stopListen(); void slot_regsiterDB(int dbNum, int size); void slot_setDB(int dbNum, QByteArray data);private: static PlcServerManager *_pInstance; static QMutex _mutex; static void callBack_event(void *usrPtr, PSrvEvent PEvent, int Size);private: bool _running; // 线程是否启用 bool _listen; // 是否连贯PLC QString _ip; // ip地址 QStringList _listIp; // 连贯上的客户端地址 TS7Server *_pTS7Server; QHash<int, QByteArray> _hashDB2ByteArray;};#endif // PLCMANAGER_HPlcWidget.cpp ...

December 3, 2020 · 2 min · jiezi

关于qt:Qt中的TCP服务端和客户端互发消息

Qt中的TCP服务端和客户端互发音讯 作者:hackett 微信公众号:加班猿 废话不多说,上演示成果 因为咱们用到socket跟Lamda表达式,所以工程.pro文件须要增加对应的库 为了不便,main.cpp中让程序显示两个Widget窗口,程序运行起来就能够测试  ServerWidget w; w.show(); ClientWidget w2; w2.show(); 一、服务端服务端的UI界面布局: 2个PushButton(send,close) 2个textEdit(发送内容,接管内容) 新建一个监听套接字,监听端口号为9999的IP,期待连贯,有连贯过去提醒胜利连贯同时服务端读就绪   //监听套接字,指定父对象,让其主动回收空间 tcpServer = new QTcpServer(this);  tcpServer->listen(QHostAddress::Any, 9999);  setWindowTitle("服务器: 9999");  //newConnection代表有新的连贯 connect(tcpServer, &QTcpServer::newConnection,  [=]()  {  //取出建设好连贯的套接字  tcpSocket = tcpServer->nextPendingConnection();   //获取对方的IP和端口  QString ip = tcpSocket->peerAddress().toString();  quint16 port = tcpSocket->peerPort();  QString temp = QString("[%1:%2]:胜利连贯").arg(ip).arg(port);  ui->textEditRead->setText(temp);   //readyRead代表读就绪  connect(tcpSocket, &QTcpSocket::readyRead,  [=]()  {  //从通信套接字中取出内容  QByteArray array = tcpSocket->readAll();  ui->textEditRead->append(array);  }  );  }  ); 二、客户端客户端的UI界面布局: 3个PushButton(connect,send,close) 2个lineEdit(端口号,IP) ...

November 11, 2020 · 2 min · jiezi

关于qt:Qt混合Python开发技术Python介绍混合过程和Demo

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109474663各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中...(点击传送门) Qt开发专栏:三方库开发技术 前言 Qt中混合Python开发,可调用Python命令与脚本。 Python Python是一种跨平台的计算机程序设计语言。 是一个高层次的联合了解释性、编译性、互动性和面向对象的脚本语言。最后被设计用于编写自动化脚本(shell),随着版本的不断更新和语言新性能的增加,越多被用于独立的、大型项目的开发。 Python是一种解释型脚本语言,能够利用于以下畛域: Web 和 Internet开发科学计算和统计人工智能桌面界面开发软件开发后端开发网络爬虫 下载Python 3.x版本的对一些函数做了限度,2.x反对,所以应用2.x,选了一个python自带pip的,版本为Python2.7.13。 官网下载地址:https://www.python.org/downlo... 下载后,装置即可。 笔者补充 Python学习笔记后续会陆续公布,只讲实用不废话,最快速度上手Python。 Qt引入Python库 依照模块化,将python的libs和include目录拷贝到模块的门路下(参照“模块化”),模块pri文件如下: INCLUDEPATH += $$PWDDEPENDPATH += $$PWDHEADERS += \ $$PWD/PythonManager.hSOURCES += \ $$PWD/PythonManager.cpp# python2.7.13INCLUDEPATH += \ $$PWD/python2.7.13/includeLIBS += -L$$PWD/python2.7.13/libsLIBS += -lpython27 模块化 测试运行 引入模块后的工程部署: 测试代码: 测试的python脚本和输入后果: 工程模版v1.0.0 若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109474663

November 7, 2020 · 1 min · jiezi

关于qt:Qt-使用-canon-edsdk-实现实时预览

概述想要应用 canon 的 sdk 进行实时的一个预览,即 LiveView 性能。 后期筹备后期的一些相机的连贯,能够参考我之前写的文章 QT 应用 canon sdk 拍照并保留到本机 实时预览步骤StartLiveView申明一个变量来标记 m_isLiveView 来标识 liveview 是否开启。 将实时预览输入到 PC 上 device |= kEdsEvfOutputDevice_PC;// -----------------------------void MainWindow::StartLiveView(){ // Change settings because live view cannot be started // when camera settings are set to "do not perform live view." // 开启 EdsError err = EDS_ERR_OK; uint evfMode = 1; //把 1 写入 enable err = EdsSetPropertyData(m_camera, kEdsPropID_Evf_Mode, 1, sizeof(uint), &evfMode); m_isLiveView = true; // Get the output device for the live view image EdsUInt32 device; err = EdsGetPropertyData(m_camera, kEdsPropID_Evf_OutputDevice, 0, sizeof(device), &device); if(err == EDS_ERR_OK) { device |= kEdsEvfOutputDevice_PC; err = EdsSetPropertyData(m_camera, kEdsPropID_Evf_OutputDevice, 0 , sizeof(device), &device); }}将预览的图像流转为 QImage 再转为 MatQImage img = QImage::fromData(data, length, "JPG");将图像流转为 QImage 格局,这个是最重要的,在网上搜寻了十分久,不晓得怎么利用 data 和 length,网上的很多都是用 vb 和 c# 解决的,没有 C++ 的。 ...

November 6, 2020 · 2 min · jiezi

关于qt:Qt实现自定义图标功能

Qt实现自定义图标性能 作者:hackett 微信公众号:加班猿 在上一节的根底上进行定义图标的性能 参考上一节的链接:Qt无边框窗口拖拽和暗影 成果:要做的是利用的放大放大、最小化性能,鼠标挪动和点击图标变色 筹备工作:控件:3个PushButton 1个Label 1个Frame 留神:须要进行布局,如果不布局可能会呈现不能放大放大的状况 筹备图标嵌入控件能够上阿里巴巴矢量图标库下载本人想要的图标,也能够去其余网站或者本人制作 我这里下载了三个图标 QSS样式表右键抉择扭转样式表,其余按键同理 增加色彩: QPushButton为扭转这个按钮的属性 QPushButton:hover为鼠标挪动到按键的成果 QPushButton:pressed为鼠标按下按键的成果 增加资源: 能够抉择咱们资源外面的图片为按键填充图片 接下来就能够链接到槽函数做相应的解决即可 放大放大按钮须要做下margin值的设置  void Widget::on_buttonMax_clicked() {  if(this->isMaximized())//是否曾经最大  {  ui->vLayout->setMargin(9);  //对应widget布局的Margin值  this->showNormal();  }else  {  ui->vLayout->setMargin(0); //全屏时widget布局的Margin值为0  this->showMaximized();  } } 源码:main.cpp  #include "widget.h" #include <QApplication>  int main(int argc, char *argv[]) {  QApplication a(argc, argv);  Widget w;  w.show();   return a.exec(); } widget.cpp  #include "widget.h" #include "ui_widget.h" #include <QMouseEvent> #include <QWidget> #include <QGraphicsDropShadowEffect>  Widget::Widget(QWidget *parent) :  QWidget(parent),  ui(new Ui::Widget) {  ui->setupUi(this);   this->setWindowFlags(Qt::FramelessWindowHint);   QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect();   shadow->setBlurRadius(5);   //边框圆角  shadow->setColor(Qt::black);//边框色彩  shadow->setOffset(0);       //不偏移   ui->shadowWidget->setGraphicsEffect(shadow);   this->setAttribute(Qt::WA_TranslucentBackground);   //父窗口设置通明,只留下子窗口 }  Widget::~Widget() {  delete ui; }  void Widget::mouseMoveEvent(QMouseEvent *event) {  if(this->z == QPoint())//判断鼠标挪动 如果为空的话不挪动  return;  QPoint y = event->globalPos();//鼠标相当于桌面左上角的地位,鼠标全局地位  QPoint x = y - this->z;  this->move(x); }  void Widget::mousePressEvent(QMouseEvent *event) {  QPoint y = event->globalPos();//鼠标相当于桌面左上角的地位,鼠标全局地位  QPoint x = this->geometry().topLeft();//窗口左上角位于桌面左上角的地位,窗口地位  this->z = y - x; //定值,不变 }  void Widget::mouseReleaseEvent(QMouseEvent *event) {  this->z = QPoint(); //鼠标松开获取以后的坐标 }  void Widget::on_buttonClose_clicked() {  this->close(); }  void Widget::on_buttonMax_clicked() {  if(this->isMaximized())//是否曾经最大  {  ui->vLayout->setMargin(9);  //对应widget布局的Margin值  this->showNormal();  }else  {  ui->vLayout->setMargin(0); //全屏时widget布局的Margin值为0  this->showMaximized();  } }  void Widget::on_buttonMin_clicked() {  this->showMinimized(); }widget.h ...

November 4, 2020 · 1 min · jiezi

关于qt:项目实战医疗流式细胞术数据文件fcs导出excel表工具

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109473140各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中...(点击传送门) Qt开发专栏:我的项目实战(点击传送门) 需要 解析医疗实验室数据文件*.fcs。 Demo导出数据 医疗流式细胞术数据文件规范(.fcs) 流式细胞术数据文件规范于1984年公布,以促成流式细胞术数据分析软件与在不同类型的流式细胞术仪器上获取的数据的互操作性。 该规范在1990年订正为FCS 2.0,在1997年订正为FCS 3.0,在2010年订正为FCS 3.1。2020年9月3日Spidlen J等人在Cytometry A杂志上提出了FCS 3.2,该修订版满足了一些新需要和倡议,并联合了十年来整个细胞仪畛域的提高。 FCS 3.2标准完整版能够下载(全英文):http://flowcyt.sf.net/fcs/fcs32.pdf 原始输出文件如下: 解析进去meta元数据如下: 解析进去data数据如下: 导出excel表如下: 若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109473140

November 4, 2020 · 1 min · jiezi

关于qt:Qt无边框窗口拖拽和阴影

Qt无边框窗口拖拽和暗影作者:hackett 微信公众号:加班猿 无边框窗口的实现只须要一行代码即可实现  this->setWindowFlags(Qt::FramelessWindowHint); 代码及运行成果: 无边框窗口能拖拽实现先要去QWidget外面找到鼠标事件函数 理一下坐标的地位状况: 左上角:屏幕的左上角 两头的窗口:程序的窗口 箭头:鼠标地位 坐标地位满足:x = y - z 在Designer外面拖一个Widget进去叫shadowWidget shadowWidget的色彩为灰色,咱们选个本人喜爱的背景色不便查看 接下来咱们要重写鼠标事件函数能力让拖拽性能失效  void Widget::mouseMoveEvent(QMouseEvent *event) {  QPoint y = event->globalPos();//鼠标相当于桌面左上角的地位,鼠标全局地位  QPoint x = y - this->z;  this->move(x); }  void Widget::mousePressEvent(QMouseEvent *event) {  QPoint y = event->globalPos();//鼠标相当于桌面左上角的地位,鼠标全局地位  QPoint x = this->geometry().topLeft();//窗口左上角位于桌面左上角的地位,窗口地位  this->z = y - x; //定值,不变 }  void Widget::mouseReleaseEvent(QMouseEvent *event) {  this->z = QPoint(); //鼠标松开获取以后的坐标 }最终成果变为鼠标可拖动的窗口: 源码: main.cpp  #include "widget.h" #include <QApplication>  int main(int argc, char *argv[]) {  QApplication a(argc, argv);  Widget w;  w.show();   return a.exec(); }widget.cpp ...

November 2, 2020 · 1 min · jiezi

关于qt:项目实战Qt编译Qt库以及使用C调用Qt库并实现C集成Qt的tcp客户端

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109338289各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中...(点击传送门) Qt开发专栏:我的项目实战(点击传送门) 需要 1.Qt曾经开发了利用,封装成Qt库,以供C#调用。 2.Qt的tcp客户端封装,以供C#调用,双向传递数据。 原理 1.应用QtCreator编译msvc版本的Qt库; 2.应用VS2017开发C#程序引入Qt库; 3.双向传递指针、传递数组; 相干博客 《我的项目实战:Qt编译Qt库以及应用C#调用Qt库,并实现C#集成Qt的tcp客户端》 《VS2017编写MFC库以及应用Qt调用MFC库办法》 《VS2017编写纯C库以及应用C#调用C库办法》 《Qt实用技巧:VS2017编写纯C库以及应用Qt调用C库办法》 《对于 C#调用C库Dll,有回调函数时,只执行一次回调函数就间接挂掉 的解决办法》 《对于 C#调用一个C/C++dll库运行时实现多个利用(动态变量辨别) 的解决办法》 《[对于 C#调用c库,将C#的byte\[\]传入C库的办法和将C库的char*向上传入C#的回调函数byte\[\] 的办法](https://blog.csdn.net/qq21497...》 Demo 以下是集成客户端的演示: 入坑入坑一:谬误“未加载ucrtbase.pdb"谬误 解决 须要对Qt的库进行初始化操作并且到用windeployqt导入库先关的依赖性项。

November 2, 2020 · 1 min · jiezi

关于qt:项目实战QtAndroid模拟操作器模拟操作app打开点击输入获取验证码等等

若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109313803各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中...(点击传送门) Qt开发专栏:我的项目实战(点击传送门) 需要 1.操作andorid模拟器,给输出的指定地位输出手机号码,并获取验证码 2.探测android设施(反对模拟器,android实体机) 3.兼容关上app的页面错误操作,即先齐全退出app,放弃启动画面连贯 4.兼容输出错误处理 5.获取验证码后无需期待60s 6.各步骤可调整地位,并反对保留、载入配置文件,复原默认 7.兼容卡顿景象,反对每步骤提早肯定工夫操作 体验下载地址 CSDN:https://download.csdn.net/download/qq21497936/13061326 QQ群:1047134658(点击“文件”搜寻“androidOptApp”,群内与博文同步更新) Demo v1.2.0 &esmp;1.优化管制速度 2.是否关上app可配置 Demo v1.1.1 若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109313803

October 30, 2020 · 1 min · jiezi

关于qt:Qt中一些乱七八糟的小知识点不断更新

//返回最靠近的整数 qRound(amount*100/total); QTableWidget: //设置交替行底色变动 ui->tableWidget->setAlternatingRowColors(true); //横向舒展单元格,铺满屏幕 ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); //只写模式如果无文件会主动创立 if(!dataFile.open(QIODevice::WriteOnly)){ qDebug()<<"文件关上失败"<<dataFile.errorString() <<QDir::currentPath()<<dataFile.fileName(); } dataFile.close();

October 24, 2020 · 1 min · jiezi

关于qt:QT-使用-canon-sdk-拍照并保存到本机

一、概述通过 usb 连贯 canon 单反,通过 QT 拍照,并将拍到的图像保留到本机。 二、操作步骤1. 初始化 SDK EdsInitializeSDK();2. 获取相机列表对象 EdsCameraListRef cameraList = NULL; error = EdsGetCameraList(&cameraList);3. 获取相机列表对象数量 // 遍历相机列表对象,获取相机列表对象数量 EdsUInt32 cameraCount = 0; error = EdsGetChildCount(cameraList, &cameraCount); if (error != EDS_ERR_OK) { qDebug() << "ERROR - failed to get camera count"; EdsRelease(cameraList); return; }4. 获取单个相机对象实例 for (uint32_t idx = 0; idx < cameraCount; idx++) { // 获取单个相机对象 EdsCameraRef cam = NULL; error = EdsGetChildAtIndex(cameraList, idx, &cam); m_camera = cam; }之后咱们对相机的操作次要就是通过这个。 ...

October 23, 2020 · 2 min · jiezi

关于qt:Qt三方库开发技术QXlsx介绍编译和使用

若该文为原创文章,未经容许不得转载原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108292147各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) Qt开发专栏:开发技术(点击传送门) 前话 应用Qt操作Xlsx表格,不依赖office以及wps组件。 本篇文章介绍的办法是应用编译成库的模式以模块退出到源代码中,不应用传统形式编译为模块须要手动增加到Qt安装文件当中去(无需作为Qt的module退出到安装文件中,笔者提倡模块化,超低耦合)。 QXlsx介绍 QXlsx是一个能够读写Excel文件的库。它不须要Microsoft Excel,能够在Qt5反对的任何平台上应用。 库反对的性能: 翻新新的xlsx文件;从.xlsx文件中提取数据编辑现有的.xlsx文件 QXlsx下载 github官网:https://github.com/QtExcel/QXlsx CSDN下载地址:https://download.csdn.net/download/qq21497936/12773165 QQ群:1047134658(点击“文件”搜寻“QXlsx”,群内与博文同步更新) QXlsx编译步骤一:下载解压 步骤二:应用QtCreator关上工程 应用QtCreator关上工程,抉择mingw32,如下图: ## 步骤三:切换release版本,编译本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108292147 模块化 xlsxManager.pri INCLUDEPATH += $$PWDDEPENDPATH += $$PWDHEADERS += \ $$PWD/XlsxManager.hSOURCES += \ $$PWD/XlsxManager.cpp#qXlsx mingw32INCLUDEPATH += $$PWD/qXlsx/includeLIBS += -L$$PWD/qXlsx/lib \ -lQXlsx 测试Demovoid XlsxManager::test(){ QXlsx::Document document("1.xlsx"); document.write(1, 1, QString("Hello world!!!")); document.saveAs("1.xlsx");} 工程模板v1.0.0 对应工程模板v1.0.0 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108292147

August 30, 2020 · 1 min · jiezi

关于qt:Qt开发技术QCharts四QChart面积图介绍Demo以及代码详解

若该文为原创文章,未经容许不得转载原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/108240696各位读者,常识无穷而人力有穷,要么改需要,要么找专业人士,要么本人钻研 红瘦子(红模拟)的博文大全:开发技术汇合(蕴含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬联合等等)继续更新中…(点击传送门) Qt开发专栏:开发技术(点击传送门)上一篇:《Qt开发技术:QCharts(三)QCharts样条曲线图介绍、Demo以及代码详解》下一篇: 敬请期待... 前言 红瘦子,来也! 依照程序,本章为面积图。 补充 QCharts所有的图表都依赖《Qt开发技术:QCharts(一)QCharts根本介绍以及图表框架详解》中的QChart、QChartView、QLegend、QValueAxis。 Demo Demo下载地址 以后为v1.1.0版本 CSDN:https://download.csdn.net/download/qq21497936/12753524 QQ群:1047134658(点击“文件”搜寻“qChartsTools”,群内与博文同步更新) 面积图概述 面积图是应用QAreaSeries类或AreaSeries QML类型实现的。默认状况下,X轴被用作一个边界和QLineSeries或线列作为另一个。然而,能够应用QLineSeries或LineSeries作为两个边界。 QAreaSeries(面积图类)概述 QAreaSeries类在面积图中显示数据。 面积序列用于显示定量数据。它是基于一系列线,用色彩强调边界线之间的区域。因为区域序列基于行序列,QAreaSeries构造函数须要一个QLineSeries实例,该实例定义区域的上边界。默认状况下,应用绘图区域底部作为下边界绘制面积图。下边界能够由另一条线指定,而不是绘图区域的底部。在这种状况下,QAReaSeries应该用两个QLineSeries实例初始化。 留神:当下边界值大于上边界值时,术语高低边界可能会产生误导。重点是这两条边界线之间的区域将被填充。 上面的代码片段阐明了如何创立根本面积图: _pLineSeries = new QLineSeries;_pLineSeries2 = new QLineSeries;_pLineSeries3 = new QLineSeries;_pLineSeries4 = new QLineSeries;// 形式一:逐个增加,大批量数据较慢_pLineSeries->append(0, qrand()%11);_pLineSeries->append(1, qrand()%11);_pLineSeries->append(2, qrand()%11);_pLineSeries->append(3, qrand()%11);_pLineSeries->append(4, qrand()%11);_pLineSeries->append(5, qrand()%11);_pLineSeries->append(6, qrand()%11);_pLineSeries->append(7, qrand()%11);_pLineSeries->append(8, qrand()%11);_pLineSeries->append(9, qrand()%11);_pLineSeries->append(10, qrand()%11);_pLineSeries->setName("通道1");_pLineSeries->setPen(QPen(QColor(qrand()%256, qrand()%256, qrand()%256), 2));// 通用:将数据插入到图表中_pAreaSeries = new QAreaSeries();_pAreaSeries->setName("面积1");_pLineSeries->setPointsVisible(true);_pLineSeries->setPointLabelsFormat("(@xPoint,@yPoint)");_pAreaSeries->setUpperSeries(_pLineSeries);_pChart->addSeries(_pAreaSeries); 效率更高的形式为: // 形式二:逐个增加,大批量数据插入QList<QLineSeries *> list;list.append(_pLineSeries);list.append(_pLineSeries2);list.append(_pLineSeries3);list.append(_pLineSeries4);for(int index = 0; index < 4; index++){ QList<QPointF> listPointF; for(int index = 0; index < 11; index++) { listPointF << QPointF(index, qrand()%11); } list.at(index)->append(listPointF); list.at(index)->setName(QString("通道%1").arg(index+1)); list.at(index)->setPen(QPen(QColor(qrand()%256, qrand()%256, qrand()%256), 2));}// 通用:将数据插入到图表中_pAreaSeries = new QAreaSeries();_pAreaSeries->setName("面积1");_pLineSeries->setPointsVisible(true);_pLineSeries->setPointLabelsFormat("(@xPoint,@yPoint)");_pAreaSeries->setUpperSeries(_pLineSeries);_pChart->addSeries(_pAreaSeries);_pAreaSeries2 = new QAreaSeries();_pAreaSeries2->setName("面积2");_pAreaSeries2->setUpperSeries(_pLineSeries2);_pChart->addSeries(_pAreaSeries2);_pAreaSeries3 = new QAreaSeries();_pAreaSeries3->setName("面积3");_pAreaSeries3->setUpperSeries(_pLineSeries3);_pAreaSeries3->setLowerSeries(_pLineSeries2);_pChart->addSeries(_pAreaSeries3);_pAreaSeries4 = new QAreaSeries();_pAreaSeries4->setName("面积4");_pAreaSeries4->setUpperSeries(_pLineSeries4);_pAreaSeries4->setLowerSeries(_pLineSeries3);_pChart->addSeries(_pAreaSeries4); ...

August 26, 2020 · 3 min · jiezi

关于qt:Qt中QDatefromString的一个小坑

Qt中2位数年份的字符串变日期格局的一个坑在Qt文档中yy示意2位数的年份,str = date->toString("yy.MM.dd")无问题。然而该str变回日期的时候date = QDate::fromString(str, "yy.MM.dd")有个年份谬误的问题 比方2020.08.21变str时为20.08.21,正确,再变date时为1920.08.21 这是因为变str时年份指定为2位数信息曾经不全,前面变date时,尽管参数是yy.MM.dd然而依然会转变为4位数的年份(这点Qt文档并未明确),主动补全,就成这样了。 附:Qt日期默认值为1900.1.1

August 22, 2020 · 1 min · jiezi

关于qt:QT-信号与槽机制

信号与槽机制原理 长处 毛病

August 14, 2020 · 1 min · jiezi

关于qt:Qt-QTableWidget及基本操作

QTableWidget 是 Qt 中的表格组件类。在窗体上搁置一个 QTableWidget 组件后,能够在 Property Editor 里对其进行属性设置,双击这个组件,能够关上一个编辑器,对其 Colum、Row 和 Item 进行编辑。 一个 QTableWidget 组件的界面根本构造如图 1 所示,这个表格设置为 6 行 5 列。 图 1 一个 QTableWidget 表格的根本构造和工作区的行、列索引号 表格的第 1 行称为行表头,用于设置每一列的题目,第 1 列称为列表头,能够设置其题目,但个别应用缺省的题目,即为行号。行表头和列表头个别是不可编辑的。 除了行表头和列表头之外的表格区域是内容区,内容区是规定的网格状,如同一个二维数组,每个网格单元称为一个单元格。每个单元格有一个行号、列号,图 1 示意了行号、列号的变化规律。 在 QTableWidget 表格中,每一个单元格是一个 QTable Widgetltem 对象,能够设置文字内容、字体、前景色、背景色、图标,也能够设置编辑和显示标记。每个单元格还能够存储一个 QVariant 数据,用于设置用户自定义数据。 图 2 实例 Samp4_9 的运行时界面 实例 samp4_9 以 QTableWidget 为次要组件,演示 QTableWidget 一些次要操作的实现。实例运行时的界面如图 2 所示,该实例将演示以下性能的实现办法: 设置表格的列数和行数,设置表头的文字、格局等。初始化表格数据,设置一批实例数据填充到表格里。插入行、增加行、删除以后行的操作。遍历表格所有单元格,读取表格内容到一个 QPlainTextEdit 里,表格的一行数据作为一行文本。表格上抉择的以后单元格变动时,在状态栏显示单元格存储的信息。界面设计与初始化Samp4_9 的主窗体从 QMainWindow 继承而来。在图 2 所示的窗口上,一个 QTableWidget 组件和一个 QPlainTextEdit 组件组成高低宰割布局 splitter。左侧的按钮都放在一个 QGroupBox 组件里,釆用 Grid 布局,而后将 groupBox 与 splitter 采纳左右宰割布局。这是一个典型的三区宰割的布局。 ...

August 1, 2020 · 3 min · jiezi

关于qt:Qt入门教程编写你的第一个qt程序

Qt是目前最先进、最残缺的跨平台C++开发工具。它不仅齐全实现了一次编写,所有平台无差别运行,更提供了简直所有开发过程中须要用到的工具。现在,Qt已被使用于超过70个行业、数千家企业,反对数百万设施及利用。 点击下载Qt最新试用版 组件和属性 咱们将开始一个QML程序,该程序绘制了一个300x300像素的蓝色矩形。 // File: BasicSteps\_1.qmlimport QtQuick 1.0Rectangle { width: 300 height: 300 color: "blue"}咱们运行QML查看器以查看工作后果: qmlviewer BasicSteps\_1.qml &上述QML代码的确会产生一个蓝色矩形。如上的一个残缺的QML代码被称为QML文档。QML文件是一段至多蕴含一个QML代码 import语句和一个顶层组件。在咱们的例子中 Rectangle是单个顶级组件。通常,QML文档与文件绝对应,然而它也能够是存储在字符串中的文本或指向存储在近程服务器上的QML文档的URL。该申明 import Qt 4.7使Qt 4.7的所有QML组件均可用于咱们的QML文档。Qt 4.7带有诸如Rectangle,Text,ListView,WebView,Flipable,Animation等内置组件(更多信息请参见QML Elements)。 组件是C ++类的QML等效项。它们具备属性,办法(成员函数),信号和插槽。产生 Rectangle在Qt文档中,element通常被用作component的同义词。具备可视示意模式(例如矩形或文本)的组件称为项。组件名称始终以大写字母结尾,后跟零个或多个字母,数字和下划线。组件实例的特色是其属性,即名称/值对。 下面的实例具备三个属性 width;heigth;color对应的值别离是:300;300;blue 别离。属性名称始终以小写字母结尾,后跟零个或多个字母,数字和下划线。属性是类型平安的,然而该行 将是非法的,因为width属性须要一些实数类型。QML反对以下根本类型:布尔型,色彩,日期,字体,整数,列表,点,实型,矩形,大小,字符串,工夫,URL。 width: 300; height: 300color: "blue"能够在用分号分隔的一行中写入多个属性;属性的程序无关紧要。咱们能够重写 Rectangle写作 Rectangle { color: "blue" height: 300 width: 300}后果将是雷同的。 在QML中,正文的标记形式与在C ++中雷同。行末正文以 //咱们示例的第1行蕴含这样的正文。多行正文以 /\* \*/

July 30, 2020 · 1 min · jiezi

QCustomPlot之数据选择十八

数据选择粒度可以通过函数QCPAbstractPlottable::setSelectable(所有的图表类都继承自QCPAbstractPlottable)设置数据选择的粒度,如下图所示: 数据选择方式及数据读取一般来说,数据选择是通过鼠标来进行的,即鼠标点击或者鼠标框选,鼠标点击选择通过函数 QCustomPlot::setInteractions 设置相应的枚举量即可,如果需要多选,则需要 QCustomPlot::setMultiSelectModifier 设置多选时使用的按键以及 setInteractions 设置枚举量包含 QCP::iMultiSelect ;而鼠标框选则通过 QCustomPlot::setSelectionRectMode 设置框选时的枚举类型为 srmSelect ,QCustomPlot还给了一个 srmCustom 类型让我们自定义框选时的行为,只需要连接 QCPSelectionRect::accepted 信号即可 已被选择的数据可以通过QCPAbstractPlottable::selection函数读取,其返回QCPDataSelection类,QCPDataSelection表现为多个选择范围的集合QList< QCPDataRange >,而QCPDataRange是单个数据选择的范围,包含被选择数据的开始位置以及结束位置(通俗的说就是下标index),注意这里遵循左闭右开原则 多个选择部分的对象在QCustomPlot中轴QCPAxis和图例QCPLegend等可以有多个部分可以被选择,由枚举SelectablePart决定可以被选择的部分,如图所示: 数据选择的风格QCustomPlot引入了QCPSelectionDecorator来决定数据被选择时的风格,主要有画笔、画刷和散点图三种风格 全部源码void MainWindow::setupLineStyleDemo(QCustomPlot *customPlot){ customPlot->legend->setVisible(true); customPlot->legend->setFont(QFont("Helvetica", 9)); QPen pen; QStringList lineNames; lineNames << "lsNone" << "lsLine" << "lsStepLeft" << "lsStepRight" << "lsStepCenter" << "lsImpulse"; for (int i = QCPGraph::lsNone; i <= QCPGraph::lsImpulse; ++i) { customPlot->addGraph(); pen.setColor(QColor(qSin(i*1+1.2)*80+80, qSin(i*0.3+0)*80+80, qSin(i*0.3+1.5)*80+80)); customPlot->graph()->setPen(pen); // 设置图表的画笔 customPlot->graph()->setName(lineNames.at(i-QCPGraph::lsNone)); customPlot->graph()->setLineStyle((QCPGraph::LineStyle)i); // 设置图表线段的风格 customPlot->graph()->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 5)); // 设置图表散点图的样式 QVector<double> x(15), y(15); for (int j=0; j<15; ++j) { x[j] = j/15.0 * 5*3.14 + 0.01; y[j] = 7*qSin(x[j])/x[j] - (i-QCPGraph::lsNone)*5 + (QCPGraph::lsImpulse)*5 + 2; } customPlot->graph()->setData(x, y); customPlot->graph()->rescaleAxes(true); } // 放大一点 customPlot->yAxis->scaleRange(1.1, customPlot->yAxis->range().center()); customPlot->xAxis->scaleRange(1.1, customPlot->xAxis->range().center()); customPlot->xAxis->setTicks(true); customPlot->yAxis->setTicks(true); customPlot->xAxis->setTickLabels(true); customPlot->yAxis->setTickLabels(true); customPlot->axisRect()->setupFullAxesBox();}void MainWindow::setupSelectionDemo(QCustomPlot *customPlot){ setupLineStyleDemo(customPlot); customPlot->setInteractions(QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables | QCP::iMultiSelect); // 轴、图例、图表可以被选择,并且是多选的方式 customPlot->setSelectionRectMode(QCP::srmSelect); // 鼠标框选 customPlot->setMultiSelectModifier(Qt::ControlModifier); // 使用ctrl键来多选 customPlot->xAxis->setSelectableParts(QCPAxis::spAxis | QCPAxis::spAxisLabel | QCPAxis::spTickLabels); // 轴的三个部分都可以被选择 customPlot->yAxis->setSelectableParts(QCPAxis::spAxis | QCPAxis::spAxisLabel | QCPAxis::spTickLabels); customPlot->xAxis->setLabel("xAxis"); customPlot->yAxis->setLabel("yAxis"); customPlot->legend->setSelectableParts(QCPLegend::spItems); // 图例本身不能被选择,只有里面的项可以被选择 customPlot->legend->setSelectedIconBorderPen(Qt::NoPen); // 设置图例里的项被选择时不显示Icon的边框 for (int i=0; i < customPlot->graphCount(); ++i) { QCPGraph *graph = customPlot->graph(i); graph->setSelectable(QCP::stDataRange); } // 连接QCustomPlot的信号,selectionChangedByUser表明是由鼠标点击进行的选择 // 这里主要就是同步图表和图例的显示 connect(customPlot, &QCustomPlot::selectionChangedByUser, [customPlot](){ for (int i=0; i < customPlot->graphCount(); ++i) { QCPGraph *graph = customPlot->graph(i); QCPPlottableLegendItem *item = customPlot->legend->itemWithPlottable(graph); if (item->selected() && !graph->selected()) graph->setSelection(QCPDataSelection(graph->data()->dataRange())); // 当图例项被选择时,选择图表全部的数据 else if (graph->selected()) item->setSelected(true); } });}

July 1, 2020 · 1 min · jiezi

qt的编译错误

修改了系统时间后,当前为2020.06.28 改为2020.06.08 make时出现一直make的情况,因为make是根据文件的修改时间来进行编译的,如果一个文件的修改时间比之前的早,那么会一直编译文件,导致了死循环。 所以系统时间不要改变!!

June 29, 2020 · 1 min · jiezi

项目实战Qt手机模拟器拉伸旋转框架

若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062本文章博客地址:https://blog.csdn.net/qq21497936/article/details/106817346红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门) Qt开发专栏:项目实战(点击传送门)Qt开发专栏:开发技术(点击传送门) 需求 手机模拟器伸缩旋转框架,中间为容器区域预留,给手机模拟器; 目标效果 功能 1.四个角鼠标图标切换,并且点击可拉伸; 2.手机框区域,鼠标点击可以拽托; 3.透明窗口的使用; 4.横竖屏的切换,,使用F1功能键; 原理 使用QRegion和QRect对鼠标区域进行判断; 使用QPainter进行绘制; 使用qss定制按钮样式; 对QWidget的paintEvent和resizeEvent使用; 涉及技术博文 《Qt实用技巧:在Qt中获取屏幕的绝对坐标》 《Qt开发技术:Qt绘图系统(一)绘图系统介绍》 《Qt开发技术:Qt绘图系统(二)QPainter详解》 《qss样式表笔记大全(一):qss名词解析(包含相关示例)》 《Qt实用技巧:实现窗口透明的五种方法》 《Qt实用技巧:组合图形的比例变换》 《Qt实用技巧:实现不规则窗口的鼠标消息穿透,包括穿透到桌面和穿透到父窗口》 Demo:手机模拟器拉伸旋转框架 v1.0.0 体验下载地址 CSDN:https://download.csdn.net/download/qq21497936/12530739 QQ群:1047134658(点击“文件”搜索“MobileFrame”,群内与博文同步更新) 核心代码MobileWidget.h #ifndef MOBILEWIDGET_H#define MOBILEWIDGET_H#include <QWidget>#include <QPainter>#include <QMouseEvent>namespace Ui {class MobileWidget;}class MobileWidget : public QWidget{ Q_OBJECTpublic: enum DIRECT { DIRECT_VERTICAL = 0x00, DIRECT_HORIZONTAL = 0x01, };public: explicit MobileWidget(QWidget *parent = 0); ~MobileWidget();protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); void keyPressEvent(QKeyEvent *event);protected: void drawBackground(QPainter *painter);private: Ui::MobileWidget *ui; int _minWidth; // 最小宽度 int _minHeight; // 最小高度 int _radius; // 圆角角度 int _spaceWidth; // 圆角到中间的边框高度 int _borderWidth; // 两边窄边的宽度 int _earY; // 耳机框的y坐标 int _earWidth; // 耳机框的宽度 int _earHeight; // 耳机框的高度 bool _vertical; QColor _transparentColor; // 四个直角透明区域颜色 QRect _cornerRect1; // 四个圆角区域矩形 1->2->3->4 = 左上->右上->左下->右下 QRect _cornerRect2; // 四个圆角区域矩形 QRect _cornerRect3; // 四个圆角区域矩形 QRect _cornerRect4; // 四个圆角区域矩形 QRect _borderRect1; // 左边界 QRect _borderRect2; // 右边界 QRect _topBorderRect1; // 顶部边框圆角部分 QRect _topBorderRect2; // 顶部边框圆角下部 QRect _bottomBorderRect1; // 底部边框圆角部分 QRect _bottomBorderRect2; // 底部边框圆角上部 QRect _centerRect; // 中心容器区域 QRect _earRect; // 耳机框区域 QRegion _moveRegion; // 鼠标点击可移动的区域 QRegion _stretchRegion1; // 鼠标点击可拉伸的区域 QRegion _stretchRegion2; // 鼠标点击可拉伸的区域 QRegion _stretchRegion3; // 鼠标点击可拉伸的区域 QRegion _stretchRegion4; // 鼠标点击可拉伸的区域 bool _leftButtonPressed; // 鼠标左键按钮 QPoint _beginPoint; // 鼠标左键按钮按下时的坐标 QPoint _leftTopPoint; // 窗口左上角的坐标 bool _stretchRegion1Pressed;// 拉伸按钮区域 bool _stretchRegion2Pressed;// 拉伸按钮区域 bool _stretchRegion3Pressed;// 拉伸按钮区域 bool _stretchRegion4Pressed;// 拉伸按钮区域 QRect _beginRect; // 拉伸开始时的原始窗口 DIRECT _direct; // 方向是水平还是垂直 QRect _buttonRectIcon; QRect _buttonRectService; QRect _buttonRectMax; QRect _buttonRectMin; QRect _buttonRectExit; QRect _buttonRectLeft; QRect _buttonRectMiddle; QRect _buttonRectRight;};#endif // MOBILEWIDGET_HMobileWidget.cpp ...

June 18, 2020 · 2 min · jiezi

思否写文章代码块粘贴时总是有出现

解决方法是:点击插入代码块,CB右键,粘贴为纯文本

June 7, 2020 · 1 min · jiezi

QCustomPlot之K线图十七

K线图需要引入的类:QCPFinancial,首先来看下K线图的示意图: 其中阳线在中国一般使用红色表示,阴线使用绿色表示 K线图的数据结构QCPFinancialData是QCPFinancial所使用的数据结构,包含五个数据类型,如下所示: 数据含义keykey轴坐标open开盘close关盘low最低high最高K线图的风格函数含义setChartStylecsOhlc(美国线) csCandlestick(蜡烛图)setWidthwtAbsolute(像素) wtAxisRectRatio(轴矩形比例) wtPlotCoords(坐标轴,默认)setTwoColored是否显示两种颜色,即阳线和阴线可以有各自的颜色setBrushPositive阳线画刷setBrushNegative阴线画刷setPenPositive阳线画笔setPenNegative阴线画笔timeSeriesToOhlc函数如果数据仅有一系列值(例如价格与时间)可用,则可以使用静态函数timeSeriesToOhlc生成合并的OHLC数据,然后将其传递给setData函数 参数含义time时间value值timeBinSize时间间隔大小,一般是一天(3600*24)timeBinOffset时间起始,一般传入time[0]完整示例来源:echarts class MyAxisTickerText : public QCPAxisTickerText{protected: virtual QVector<double> createTickVector(double tickStep, const QCPRange &range) Q_DECL_OVERRIDE { Q_UNUSED(tickStep) QVector<double> result; if (mTicks.isEmpty()) return result; auto start = mTicks.lowerBound(range.lower); auto end = mTicks.upperBound(range.upper); if (start != mTicks.constBegin()) --start; if (end != mTicks.constEnd()) ++end; int count = cleanMantissa(std::distance(start, end) / double(mTickCount + 1e-10)); auto it = start; while (it != end) { result.append(it.key()); int step = count; if (step == 0) ++it; while (--step >= 0 && it != end) ++it; } return result; }};void MainWindow::setupShangHaiIndexDemo(QCustomPlot *customPlot){ const QColor BrushPositive("#ec0000"); const QColor PenPositive("#8a0000"); const QColor BrushNegative("#00da3c"); const QColor PenNegative("#008f28"); const QVector<QString> rawTimes = { "2013/1/24", "2013/1/25", "2013/1/28", "2013/1/29", "2013/1/30", "2013/1/31", "2013/2/1", "2013/2/4", "2013/2/5", "2013/2/6", "2013/2/7", "2013/2/8", "2013/2/18", "2013/2/19", "2013/2/20", "2013/2/21", "2013/2/22", "2013/2/25", "2013/2/26", "2013/2/27", "2013/2/28", "2013/3/1", "2013/3/4", "2013/3/5", "2013/3/6", "2013/3/7", "2013/3/8", "2013/3/11", "2013/3/12", "2013/3/13", "2013/3/14", "2013/3/15", "2013/3/18", "2013/3/19", "2013/3/20", "2013/3/21", "2013/3/22", "2013/3/25", "2013/3/26", "2013/3/27", "2013/3/28", "2013/3/29", "2013/4/1", "2013/4/2", "2013/4/3", "2013/4/8", "2013/4/9", "2013/4/10", "2013/4/11", "2013/4/12", "2013/4/15", "2013/4/16", "2013/4/17", "2013/4/18", "2013/4/19", "2013/4/22", "2013/4/23", "2013/4/24", "2013/4/25", "2013/4/26", "2013/5/2", "2013/5/3", "2013/5/6", "2013/5/7", "2013/5/8", "2013/5/9", "2013/5/10", "2013/5/13", "2013/5/14", "2013/5/15", "2013/5/16", "2013/5/17", "2013/5/20", "2013/5/21", "2013/5/22", "2013/5/23", "2013/5/24", "2013/5/27", "2013/5/28", "2013/5/29", "2013/5/30", "2013/5/31", "2013/6/3", "2013/6/4", "2013/6/5", "2013/6/6", "2013/6/7", "2013/6/13", }; // 数据意义:开盘(open),收盘(close),最低(lowest),最高(highest) const QVector<QVector<double>> rawDatas = { { 2320.26,2320.26,2287.3,2362.94}, { 2300,2291.3,2288.26,2308.38}, { 2295.35,2346.5,2295.35,2346.92}, { 2347.22,2358.98,2337.35,2363.8}, { 2360.75,2382.48,2347.89,2383.76}, { 2383.43,2385.42,2371.23,2391.82}, {2377.41,2419.02,2369.57,2421.15}, {2425.92,2428.15,2417.58,2440.38}, {2411,2433.13,2403.3,2437.42}, {2432.68,2434.48,2427.7,2441.73}, {2430.69,2418.53,2394.22,2433.89}, {2416.62,2432.4,2414.4,2443.03}, { 2441.91,2421.56,2415.43,2444.8}, { 2420.26,2382.91,2373.53,2427.07}, { 2383.49,2397.18,2370.61,2397.94}, { 2378.82,2325.95,2309.17,2378.82}, { 2322.94,2314.16,2308.76,2330.88}, { 2320.62,2325.82,2315.01,2338.78}, { 2313.74,2293.34,2289.89,2340.71}, { 2297.77,2313.22,2292.03,2324.63}, { 2322.32,2365.59,2308.92,2366.16}, {2364.54,2359.51,2330.86,2369.65}, {2332.08,2273.4,2259.25,2333.54}, {2274.81,2326.31,2270.1,2328.14}, {2333.61,2347.18,2321.6,2351.44}, {2340.44,2324.29,2304.27,2352.02}, {2326.42,2318.61,2314.59,2333.67}, { 2314.68,2310.59,2296.58,2320.96}, { 2309.16,2286.6,2264.83,2333.29}, { 2282.17,2263.97,2253.25,2286.33}, { 2255.77,2270.28,2253.31,2276.22}, { 2269.31,2278.4,2250,2312.08}, { 2267.29,2240.02,2239.21,2276.05}, { 2244.26,2257.43,2232.02,2261.31}, { 2257.74,2317.37,2257.42,2317.86}, { 2318.21,2324.24,2311.6,2330.81}, { 2321.4,2328.28,2314.97,2332}, { 2334.74,2326.72,2319.91,2344.89}, { 2318.58,2297.67,2281.12,2319.99}, { 2299.38,2301.26,2289,2323.48}, { 2273.55,2236.3,2232.91,2273.55}, { 2238.49,2236.62,2228.81,2246.87}, {2229.46,2234.4,2227.31,2243.95}, {2234.9,2227.74,2220.44,2253.42}, {2232.69,2225.29,2217.25,2241.34}, {2196.24,2211.59,2180.67,2212.59}, {2215.47,2225.77,2215.47,2234.73}, { 2224.93,2226.13,2212.56,2233.04}, { 2236.98,2219.55,2217.26,2242.48}, { 2218.09,2206.78,2204.44,2226.26}, { 2199.91,2181.94,2177.39,2204.99}, { 2169.63,2194.85,2165.78,2196.43}, { 2195.03,2193.8,2178.47,2197.51}, { 2181.82,2197.6,2175.44,2206.03}, { 2201.12,2244.64,2200.58,2250.11}, { 2236.4,2242.17,2232.26,2245.12}, { 2242.62,2184.54,2182.81,2242.62}, { 2187.35,2218.32,2184.11,2226.12}, { 2213.19,2199.31,2191.85,2224.63}, { 2203.89,2177.91,2173.86,2210.58}, {2170.78,2174.12,2161.14,2179.65}, {2179.05,2205.5,2179.05,2222.81}, {2212.5,2231.17,2212.5,2236.07}, {2227.86,2235.57,2219.44,2240.26}, {2242.39,2246.3,2235.42,2255.21}, {2246.96,2232.97,2221.38,2247.86}, { 2228.82,2246.83,2225.81,2247.67}, { 2247.68,2241.92,2231.36,2250.85}, { 2238.9,2217.01,2205.87,2239.93}, { 2217.09,2224.8,2213.58,2225.19}, { 2221.34,2251.81,2210.77,2252.87}, { 2249.81,2282.87,2248.41,2288.09}, { 2286.33,2299.99,2281.9,2309.39}, { 2297.11,2305.11,2290.12,2305.3}, { 2303.75,2302.4,2292.43,2314.18}, { 2293.81,2275.67,2274.1,2304.95}, { 2281.45,2288.53,2270.25,2292.59}, { 2286.66,2293.08,2283.94,2301.7}, { 2293.4,2321.32,2281.47,2322.1}, { 2323.54,2324.02,2321.17,2334.33}, { 2316.25,2317.75,2310.49,2325.72}, { 2320.74,2300.59,2299.37,2325.53}, {2300.21,2299.25,2294.11,2313.43}, {2297.1,2272.42,2264.76,2297.1}, {2270.71,2270.93,2260.87,2276.86}, {2264.43,2242.11,2240.07,2266.69}, {2242.26,2210.9,2205.07,2250.63}, { 2190.1,2148.35,2126.22,2190.1} }; QSharedPointer<QCPAxisTickerText> textTicker(new MyAxisTickerText); // 文字轴 textTicker->setTickCount(10); QCPDataContainer<QCPFinancialData> datas; QVector<double> timeDatas, MA5Datas, MA10Datas, MA20Datas, MA30Datas; MA5Datas = calculateMA(rawDatas, 5); MA10Datas = calculateMA(rawDatas, 10); MA20Datas = calculateMA(rawDatas, 20); MA30Datas = calculateMA(rawDatas, 30); for (int i = 0; i < rawTimes.size(); ++i) { timeDatas.append(i); QCPFinancialData data; data.key = i; data.open = rawDatas.at(i).at(0); data.close = rawDatas.at(i).at(1); data.low = rawDatas.at(i).at(2); data.high = rawDatas.at(i).at(3); datas.add(data); textTicker->addTick(i, rawTimes.at(i)); } QCPFinancial *financial = new QCPFinancial(customPlot->xAxis, customPlot->yAxis); financial->setName("日K"); financial->setBrushPositive(BrushPositive); financial->setPenPositive(PenPositive); financial->setBrushNegative(BrushNegative); financial->setPenNegative(PenNegative); financial->data()->set(datas); const QVector<QColor> ColorOptions = { "#c23531", "#2f4554", "#61a0a8", "#d48265" }; QCPGraph *graph = customPlot->addGraph(); graph->setName("MA5"); graph->setData(timeDatas, MA5Datas); graph->setPen(ColorOptions.at(0)); graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(ColorOptions.at(0), 2), QBrush(Qt::white), 8)); graph->setSmooth(true); graph = customPlot->addGraph(); graph->setName("MA10"); graph->setData(timeDatas, MA10Datas); graph->setPen(ColorOptions.at(1)); graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(ColorOptions.at(1), 2), QBrush(Qt::white), 8)); graph->setSmooth(true); graph = customPlot->addGraph(); graph->setName("MA20"); graph->setData(timeDatas, MA20Datas); graph->setPen(ColorOptions.at(2)); graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(ColorOptions.at(2), 2), QBrush(Qt::white), 8)); graph->setSmooth(true); graph = customPlot->addGraph(); graph->setName("MA30"); graph->setData(timeDatas, MA30Datas); graph->setPen(ColorOptions.at(3)); graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(ColorOptions.at(3), 2), QBrush(Qt::white), 8)); graph->setSmooth(true); customPlot->xAxis->setTicker(textTicker); customPlot->rescaleAxes(); customPlot->xAxis->scaleRange(1.05, customPlot->xAxis->range().center()); customPlot->yAxis->scaleRange(1.05, customPlot->yAxis->range().center()); customPlot->legend->setVisible(true);}QVector<double> MainWindow::calculateMA(const QVector<QVector<double> > &v, int dayCount){ auto func = [](double result, const QVector<double> &v2){ return result + v2[1]; }; QVector<double> result; for (int i = 0; i < v.size(); ++i) { if (i < dayCount) { result.append(qQNaN()); } else { double sum = std::accumulate(v.begin() + i - dayCount + 1, v.begin() + i + 1, 0.0, func); result.append(sum / dayCount); } } return result;}最后不使用 QCPAxisTickerDateTime 作为轴标签,是因为数据的日期不是连续的,使用QCPAxisTickerDateTime会导致不连续的部分有间隔,如果需要使用QCPAxisTickerDateTime的话需要设置setTickOrigin为时间的第一个数据,不然的话会发生K线图与坐标轴对应不上的情况,同时还要设置K线图的宽度setWidth,例如一天的宽度financial->setWidth(3600 * 24 * 0.8),乘以0.8是为了稍微缩小一点继承QCPAxisTickerText的原因是因为QCPAxisTickerText在数据比较多的时候轴标签会挤在一起,密密麻麻的不好看

June 6, 2020 · 3 min · jiezi

前端面试每日-31-第406天

今天的知识点 (2020.05.26) —— 第406天 (我也要出题)[html] 如何在网页中打开腾讯QQ?[css] 给一个图片设置透明有哪些方式呢?[js] 你是如何比较js函数的执行速度的?[软技能] 工作中如何高效沟通?《论语》,曾子曰:“吾日三省吾身”(我每天多次反省自己)。前端面试每日3+1题,以面试题来驱动学习,每天进步一点!让努力成为一种习惯,让奋斗成为一种享受!相信 坚持 的力量!!!欢迎在 Issues 和朋友们一同讨论学习! 项目地址:前端面试每日3+1【推荐】欢迎跟 jsliang 一起折腾前端,系统整理前端知识,目前正在折腾 LeetCode,打算打通算法与数据结构的任督二脉。GitHub 地址 学习不打烊,充电加油只为遇到更好的自己,365天无节假日,每天早上5点纯手工发布面试题(死磕自己,愉悦大家)。希望大家在这浮夸的前端圈里,保持冷静,坚持每天花20分钟来学习与思考。在这千变万化,类库层出不穷的前端,建议大家不要等到找工作时,才狂刷题,提倡每日学习!(不忘初心,html、css、javascript才是基石!)欢迎大家到Issues交流,鼓励PR,感谢Star,大家有啥好的建议可以加我微信一起交流讨论!希望大家每日去学习与思考,这才达到来这里的目的!!!(不要为了谁而来,要为自己而来!)交流讨论欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个[Star]

May 26, 2020 · 1 min · jiezi

Qt上FFTW組件的編譯安裝

FFTW是一個做頻譜非常實用的組件,本文講述在Windows和Linux兩個平臺使用FFTW組件。Windows下的的FFTW組件已經編譯好成爲dll文件,按照開發應用的位數下載好組件包後直接按照dll規則使用組件;Linux下則需要自己進行編譯。 FFTW源碼包的下載:http://www.fftw.org/download.... Linux編譯FFTW組件1) 下載fftw-3.3.8.tar.gz文件,並解壓。2) 配置fftw編譯選項在終端輸入: ./configure --enable-type-prefix --prefix=/usr/local/fftw --with-gcc --disable-fortran --enable-i386-hacks --enable-shared=yes常見錯誤: 提示--enable-type-prefix沒有找到文件,此時請檢查上面命令每個選項之間的空格和縮進是否混淆,全部更改爲空格。 3) 編譯fftwmake -j8 4) 編譯安裝make install 5) 編譯浮點fftw支持make clean ./configure --enable-float --enable-type-prefix --prefix=/usr/local/fftw --with-gcc --disable-fortran --enable-i386-hacks --enable-shared=yes6) 編譯fftwmake -j8 7) 編譯安裝make install 最後在/usr/local/fftw路徑中又so、a文件。 Windows編譯FFTW組件 下载32位和64位版本后将该文件解压到自己想要设定的路径,我这里设定的c:/fftw。 然后,将文件中给所有的扩展名为.def 和 .dll文件拷贝到 qt安装路径5.10.0mingw53_32bin中,(版本号可能有区别,但是大同小异) 如果不进行上述步骤,使用的fftw组件的应用程序编译是没有问题的,但是无法启动。当在调试模式下会提示,During startup program exited with code 0x00000135的错误(Qt的bug由第三方dll文件引起)。 在Qt安装路径5.10.0mingw53_32include 路径中创建文件夹fftw,再将c:/fftw文件中的所有h文件,拷贝到该目录。 參考文獻:[1] Installation and Customization,http://www.fftw.org/fftw2_doc...

November 5, 2019 · 1 min · jiezi

QWT编译与配置WindowsLinux环境

QWT和FFTW两种开源组件是常用的工程软件支持组件,QWT可以提供丰富的绘图组件功能,FFTW是优秀数字波形分析软件。本文使用基于LGPL版权协议的开源项目QWT的源代码和FFTW在Window 64bit/Linux环境下的Qt上进行编译,编译器使用MinGW-64bit版本。最终配置生成QWT的静态库文件和将qwt ui组件集成到QtCreator的Designer中。 QWT的源代码下载地址目录:https://sourceforge.net/proje... 请下载zip版本的源代码(我这里下载的是qwt-6.1.4.zip文件) 1 Windows环境本文使用Window环境为: 系统: Windows 10 64bits QtCreator版本: Qt5.12.1 / MinGW 64版本 a)解压qwt-6.1.4.zip文件到本地路径解压qwt-6.1.4文件会发现该文件是一个基于Qt的工程文件,使用本地的QtCreator自帶的qt 命令行工具,分别编译release版本。 b) 切换到解压路径 C) 进行编译c.1 更改配置文件 win32 { QWT_INSTALL_PREFIX = C:/Qwt-$$QWT_VERSION # QWT_INSTALL_PREFIX = C:/Qwt-$$QWT_VERSION-qt-$$QT_VERSION}qmake qwt.pro mingw32-make -j8 mingw32-make install d) 配置QWT工作(关闭QtCreator)拷贝工作: d.1) 从 C:Qwt-6.1.4lib下拷贝libqwt.a和libqwtd.a 到 【qt安装路径Qt5.12.15.12.1mingw73_64lib】文件夹下 。d.2) 从 C:Qwt-6.1.4lib下拷贝qwt.dll和qwtd.dll 到 【qt安装路径Qt5.12.15.12.1mingw73_64bin】文件夹下 d.3) 从 C:Qwt-6.1.4pluginsdesigner下拷贝qwt_designer_plugin.dll 到 【qt安装路径Qt5.12.15.12.1mingw73_64pluginsdesigner】文件夹下 。 d.4) 在 【qt安装路径Qt5.12.15.12.1mingw73_64include】文件夹下新建Qwt文件夹,并将C:Qwt-6.1.4include此文件夹下所有内容拷贝到刚才新建的Qwt文件夹内。 over# 2 Linux環境本文使用的Linux環境爲: 系統: Manjaro KDE 64 bit版本gcc version 8.2.1 20181127 (GCC) ...

November 5, 2019 · 1 min · jiezi

QString较少用到的接口

介绍QString较少使用却很有用的接口。0x00 移除行首行尾的空白字符 空白字符包含:'t', 'n', 'v', 'f', 'r'和' '。 接口: QString QString::trimmed() const 示例: QString str = " lots\t of\nwhitespace\r\n ";str = str.trimmed();// str == "lots\t of\nwhitespace"0x01 移除行首行尾空白字符并将每个内部空白序列替换为一个空格。QString str = " lots\t of\nwhitespace\r\n ";str = str.simplified();// str == "lots of whitespace";0x02 QString转QStringListQStringList QString::split(const QString &sep, QString::SplitBehavior behavior = KeepEmptyParts, Qt::CaseSensitivity cs = Qt::CaseSensitive) constQString str = "a,,b,c";QStringList list1 = str.split(',');// list1: [ "a", "", "b", "c" ]QStringList list2 = str.split(',', QString::SkipEmptyParts);// list2: [ "a", "b", "c" ] 另外QStringList转QString可以使用以下接口: ...

November 3, 2019 · 1 min · jiezi

qmake实用函数

介绍些qmake使用频率较高的函数。0x00 判断某个类型是否存在:原型:defined(name[, type])type含义test检查测试函数replace检查代替函数var检查变量示例(判断变量是否存在):defined(COPY_TARGET, var) { ...}0x01 变量列表是否包含某个变量原型:contains(variablename, value)示例:contains(QT, core) { ...}0x02 判断变量值是否相等原型:equals(variablename, value)示例:TARGET = Testequals(TARGET, "Test") { ...}0x03 打印输出原型:message(string)log(string)warning(string)error(string)0x04 测试变量是否大于某个值原型:greaterThan(variablename, value)示例(判断Qt版本):greaterThan(QT_MAJOR_VERSION, 4): QT += widgets0x05 系统调用原型:system(command)

November 2, 2019 · 1 min · jiezi

qDebug-stdcout-printf性能表现

Qt君最近感觉qDebug相对于printf打印感觉有些慢,但又没有证据,于是闲着就写下qDebug,std::cout,printf的性能表现咯。注:测试数据仅供参考。0x00 测试环境环境参数CPUi5-8250U内存8G操作系统Windows@64位Qt版本Qt 5.12.1编译器MSVC2017@64位0x01 数据呈现 通过使用qDebug,std::cout,printf在1秒内打印的字符串数据。 分别各测试10次后取平均值,详细数据在文末。 debug版本(次/秒)release版本(次/秒)qDebug3831760923std::cout382890372696printf432606386663图表化显示 0x02 数据分析性能表现:printf > std::cout > qDebug;qDebug()相对于std::cout和printf差距过大(6~10倍);std::cout与printf数据基本一致;std::cout与printf的debug与release差距不大,甚至有debug比release快的现象(可能受实验环境影响)。0x03 结论qDebug比std::cout和printf慢,高频调用有可能影响系统时延;性能均衡推荐选用std::count;追求性能选用printf。0x04 测试程序#include <QDebug>#include <QElapsedTimer>#include <iostream>/* 注:单独打开某个宏测试 *///#define TEST1//#define TEST2//#define TEST3int main(int argc, char *argv[]){#ifdef TEST1 { QElapsedTimer t; qint64 it = 0; t.start(); while (t.elapsed() < 1000) { qDebug() << "Test1"; it++; } qDebug() << "Test1: " << it; }#endif#ifdef TEST2 { QElapsedTimer t; qint64 it = 0; t.start(); while (t.elapsed() < 1000) { std::cout << "Test2" << std::endl; it++; } std::cout << "Test2: " << it; }#endif#ifdef TEST3 { QElapsedTimer t; qint64 it = 0; t.start(); while (t.elapsed() < 1000) { printf("Test3\n"); it++; } printf("Test3: %lld\n", it); }#endif return 0}0x05 测试数据(各10次)debug版本qDebug: 38310 38452 39416 38420 38962 38385 39293 38814 34178 38946std::cout: 389512 397234 378168 367970 366371 364401 405547 405992 365863 387846printf: 468310 423937 480598 385025 490155 489473 373419 397995 445099 372054release版本qDebug: 60779 60710 59450 59685 63298 61044 59788 61167 61822 61495std::cout: 352541 358754 377001 380487 397576 362145 333757 413027 416352 335320printf: 468310 329729 333142 320171 333825 330411 471041 473771 468310 337921

October 17, 2019 · 1 min · jiezi

翻译-您没有做错线程

本文翻译自: https://woboq.com/blog/qthrea...原作者: Olivier Goffart发布时间:2013年1月22日 这篇文章是关于QThread的使用的。这是对我当时的同事Brad三年前的博客帖子的回答:"您做错了"。 Brad在他的博客文章中解释说,他看到许多用户通过对QThread进行子类化,在该子类中添加一些槽并在构造函数中执行以下操作来滥用QThread: moveToThread(this); 他们把线程移动到自己类内。正如Brad所提到的,这是错误的:QThread应该是管理线程的接口。因此,应该在创建线程中使用它。 这样,就无法在该线程中运行QThread对象中的槽,并且在QThread的子类中具有槽是一种不好的做法。 但是,Brad继续并完全不鼓励使用QThread的任何子类。他声称这违反了正确的面向对象设计。这是我不同意的地方。放入代码run()是扩展QThread的一种有效的面向对象方法:QThread表示一个仅启动事件循环的线程,子类表示一个被扩展以执行其工作的线程run()。 Brad上任后,该社区的一些成员就反对对QThread进行子类化进行了讨伐。问题在于,有很多完全合法的原因可以继承QThread。 在Qt 5.0和Qt 4.8.4中,更改了QThread的文档,因此示例代码不涉及子类。查看Qt 4.8 QThread文档的第一个代码示例(更新的文档已经修复)。它具有许多样板行,仅用于在线程中运行一些代码。而且甚至存在泄漏:QThread永远不会退出并被销毁。 我在IRC上被问到一个用户的问题,该用户遵循该示例,以便在线程中运行一些简单的代码。他很难弄清楚如何正确销毁线程。这就是促使我撰写此博客条目的原因。 如果允许子类化QThread,那么您将获得: class WorkerThread : public QThread { void run() { // ... }};void MyObject::startWorkInAThread(){ WorkerThread *workerThread = new WorkerThread; connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); workerThread->start();} 此代码不再泄漏,并且更加简单,并且不会创建无用的对象,因此开销较小。 Qt线程示例threadedfortuneserver是使用此模式运行阻塞操作的示例,并且比使用worker对象的等效示例要简单得多。 我已经向文档提交了补丁, 以免再次阻止对QThread的子类化。 经验法则什么时候子类化,什么时候不子类化?如果您确实不需要线程中的事件循环,则应该子类化。如果需要事件循环并处理线程中的信号和槽,则可能不需要子类化。改用QtConcurrent呢? QThread的级别很低,您最好使用更高级别的API,例如QtConcurrent。 现在,QtConcurrent有其自身的一系列问题:它与单个线程池绑定,因此如果要运行阻塞操作,它不是一个好的解决方案。在其实现中还存在一些问题,这些问题会带来一些性能开销。所有这些都是可以修复的。也许甚至Qt 5.1也会有所改进。 一个很好的选择也是C ++ 11与标准库 std::thread 和std::async它们现在在一个线程中运行的代码的标准方式。好消息是它仍然可以在Qt上正常工作:所有其他Qt线程原语都可以与本机线程一起使用。(如果需要,Qt将自动创建一个QThread来创建) ...

October 17, 2019 · 1 min · jiezi

使用QString生成重复字符

使用QString生成重复字符,避免使用复杂繁琐的循环语句生成。通过构造函数生成 构造一个给定大小的字符串,且每个字符为ch。 QString::QString(int size, QChar ch)QString str = QString(5, '+')// str == "+++++"使用fill接口实现 将字符串中的每个字符设置为ch。如果大小不同于-1(默认值),则预先将字符串调整为指定size大小。 QString &QString::fill(QChar ch, int size = -1)QString str = "Hello";str.fill('+');// str == "+++++"str.fill('---', 3);// str == "---"

October 16, 2019 · 1 min · jiezi

为QtCreator添加一键打包工具

用图文的方式教大家如何添加。0x00 设置入口 0x01 添加工具 0x02 配置打包工具环境 填入下列参数到对应栏目下。由于打包工具会在执行文件目录下生成打包依赖文件,建议在项目文件(.pro)中使用DESTDIR指定执行文件的生成路径。 执行档:%{CurrentProject:QT_HOST_BINS}\windeployqt.exe参数:%{CurrentRun:Executable:FilePath}工作目录:%{CurrentRun:Executable:NativePath} 0x03 效果

October 15, 2019 · 1 min · jiezi

利用qmake分类编译输出的中间文件

通过配置项目文件控制编译器分类生成中间文件,中间文件较多时作用较大。DESTDIR设置执行文件的输出目录,如(.exe文件)。OBJECTS_DIR设置编译时生成的中间代码文件的路径。MOC_DIR设置编译时生成moc文件的路径。注:所有QObject派生的类都会生成moc。RCC_DIR设置编译时资源文件的路径。注:把图片放到qrc里面,使用编译器生成qrc_xxx.cpp文件。UI_DIR设置编译时ui界面文件的路径。注:如存在xxx.ui文件则编译器生成名为ui_xxx.h文件qmake分类语句build_type =CONFIG(debug, debug|release) { build_type = debug} else { build_type = release}DESTDIR = $$build_type/outOBJECTS_DIR = $$build_type/objMOC_DIR = $$build_type/mocRCC_DIR = $$build_type/rccUI_DIR = $$build_type/ui设置分类语句前 设置分类语句后齐齐整整的目录分类 目录树├─moc│ moc_mainwindow.cpp│ moc_predefs.h│├─obj│ main.obj│ mainwindow.obj│ moc_mainwindow.obj│ qrc_rcc.obj│ TextEdit_resource.res│├─out│ TextEdit.exe│├─rcc│ qrc_rcc.cpp│└─ui ui_mainwindow.h

October 14, 2019 · 1 min · jiezi

QProcess使用waitForFinished的小坑

我们使用以下接口都会有超时机制,主要是避免长时间的阻塞。但有些类似有超时机制的接口在使用上就需要注意了。 bool QAbstractSocket::waitForBytesWritten(int msecs = 30000)bool QAbstractSocket::waitForConnected(int msecs = 30000)bool QAbstractSocket::waitForDisconnected(int msecs = 30000)bool QAbstractSocket::waitForReadyRead(int msecs = 30000) 一般我们使用QProcess执行命令时都会执行waitForFinished等待程序执行完成。细看接口可以看到它有默认的超时时间(30s),如果超过30s就会中断执行。如果我们执行某些耗时操作又没有设置超时时间则会导致一直中断执行从而得不到想要的结果。 bool QProcess::waitForFinished(int msecs = 30000) 下列例子由于没有设置waitForFinished超时时间,如果gzip解压时间超过30s就得不到想要的结果。 QProcess gzip;gzip.start("gzip –d /opt/etc.zip.gz");if (!gzip.waitForStarted()) return false; if (!gzip.waitForFinished()) return false;QByteArray result = gzip.readAll(); 应该设置可预计的超时时间或不可预计的执行时间就应该设置waitForFinished(-1)参数(直到执行完成)。

October 9, 2019 · 1 min · jiezi

『前瞻』Qt514支持markdown语法

在2019/09/25的Qt5.14评估版本中看到QTextEdit和QTextBrowser支持markdown格式。编写文本(笔记,文章等)上markdown相对于html语法,其简洁,方便,高效。支持markdown的类QTextDocumentQTextEdit和QTextBrowserQml的Text和TextEdit QTextDocument支持标准markdown语法和CommonMark,GitHub规范允许的范围内保留格式(包括标题,表格,列表,引用块和代码块)。默认情况下它们还支持markdown与html混合语法编写。QTextBrowse::setSource()基于文件扩展名识别Markdown语法。效果 附录markdown文本# 1.标题# 标题1## 标题2### 标题3#### 标题4##### 标题5###### 标题6---# 2. 列表* list1* list2* list3---# 3. 嵌套列表1. 第一项: - 第一项嵌套的第一个元素 - 第一项嵌套的第二个元素2. 第二项: - 第二项嵌套的第一个元素 - 第二项嵌套的第二个元素---# 4. 任务列表- [ ] task1- [x] task2- [x] task3---# 5. 文字格式**粗体文本**_斜体文本__**粗斜体文本**_~~删除线文本~~<u>带下划线文本</u><font face="微软雅黑" >微软雅黑字体</font><font size=1 >1号字</font><font size=2 >2号字</font><font color=#FF0000 >红色</font><font color=#008000 >绿色</font><font color=#0000FF >蓝色</font>---# 6. 分隔线---# 7. 表格| 表头1 | 表头2 || ---- | ---- || 单元格1 | 单元格2 || 单元格3 | 单元格4 |ref:https://wiki.qt.io/New_Featur... ...

October 8, 2019 · 1 min · jiezi

Qt-6咨讯

Qt 6发布前的Qt 5.14和Qt 5.15为承接Qt 5版本与Qt 6的重要桥梁。就像Qt 4.8与Qt 5一样。Qt 6目标计划于2020年年底前发布版本。新一代的QML引入强类型,简化维护成本,让编译器生成性能更好的代码。引入更多类似javascript解释器引擎,主要用于适配单片机等低端硬件。去掉了QML的版本控制,简化QML代码。优化QObject与QML的数据交互,删除QObject和QML之间重复的数据结构,避免运行时生成数据结构。支持把QML编译成高效原生的C++代码。为QML支持私有方法和属性,用于隐藏实现。更好的工具集成,加入更多和更完善的编译检错工具。下一代图形优化2D与3D图形。它能在编译时根据目标硬件预处理这些素材并在需要时使用。计划引入统一的主题样式引擎,这将允许我们在桌面和移动平台上获得Qt Widgets和Qt Quick的原生外观。统一并且一致的工具库Qt 3D Studio和Qt Design Studio合并。设计工具将集成Photoshop、Sketch、Illustrator、Maya、3D Max等工具。CMake替换QMake成为官方编译工具(QMake依然支持)。增强已有的C++ API支持C++17。QML一些功能将会引入到C++中。语言支持继续支持Python语言。新增WebAssembly支持(浏览器运行Qt程序技术)。兼容Qt 5和增量改进将删除Qt 5中已经废弃的大部分功能(函数、类或模块)。让Qt 6与Qt 5.15 LTS足够兼容。ref:https://www.qt.io/blog/2019/0...

October 8, 2019 · 1 min · jiezi

圆形按钮样式

大家中秋好。月饼圆,月亮圆,中秋团团圆圆。今天就分享些关于圆的东西(圆形按钮样式)。 主题效果默认颜色悬停颜色按下颜色红色#f44336#d5d5d5#f2f2f2蓝色#008cba#d5d5d5#f2f2f2绿色#4caf50#d5d5d5#f2f2f2灰色#e7e7e7#d5d5d5#f2f2f2黑色#555555#d5d5d5#f2f2f2红色圆形按钮样式示例QPushButton { min-width: 100px; max-width: 100px; max-height: 100px; min-height: 100px; border-radius: 50px; font-size: 15px; color: white; background: #f44336 ; /* 默认颜色 */}QPushButton:hover { font-size: 18px; color: white; background: #d5d5d5; /* 悬停颜色 */}QPushButton:pressed { background: #f2f2f2 /* 按下颜色 */}关于更多源码示例https://github.com/aeagean/QS... Qt君公众号后台回复"QSS"获取更多相关信息。

October 8, 2019 · 1 min · jiezi

QImage实用接口

介绍QImage的图像缩放,转换,镜像等接口功能。图像缩放QImage scaled(const QSize &size, Qt::AspectRatioMode aspectRatioMode, Qt::TransformationMode transformMode) const图像转换QImage convertToFormat(QImage::Format format, Qt::ImageConversionFlags flags) const &图像镜像 在水平/垂直方向镜像,具体取决于水平和垂直设置为true还是false。 QImage mirrored(bool horizontal, bool vertical) const &图像保存bool save(const QString &fileName, const char *format, int quality) constBGR转RGBQImage rgbSwapped() const &

October 6, 2019 · 1 min · jiezi

Qt官方示例可拖拽本文

可对文本进行拖动到指定位置。 部分主要代码当被鼠标拖动的对象进入其容器范围内时触发此事件void DragWidget::dragEnterEvent(QDragEnterEvent *event){ if (event->mimeData()->hasText()) { if (event->source() == this) { event->setDropAction(Qt::MoveAction); event->accept(); /* 接受拖拽事件 */ } else { event->acceptProposedAction(); } } else { event->ignore(); }}在一个拖动过程中,释放鼠标键时触发此事件 void DragWidget::dropEvent(QDropEvent *event){ if (event->mimeData()->hasText()) { const QMimeData *mime = event->mimeData(); QStringList pieces = mime->text().split(QRegularExpression(QStringLiteral("\\s+")), QString::SkipEmptyParts); QPoint position = event->pos(); QPoint hotSpot; QByteArrayList hotSpotPos = mime->data(hotSpotMimeDataKey()).split(' '); if (hotSpotPos.size() == 2) { /* 松开拖拽设置为当前位置 */ hotSpot.setX(hotSpotPos.first().toInt()); hotSpot.setY(hotSpotPos.last().toInt()); } for (const QString &piece : pieces) { QLabel *newLabel = createDragLabel(piece, this); newLabel->move(position - hotSpot); newLabel->show(); newLabel->setAttribute(Qt::WA_DeleteOnClose); position += QPoint(newLabel->width(), 0); } if (event->source() == this) { event->setDropAction(Qt::MoveAction); event->accept(); /* 接受拖拽事件 */ } else { event->acceptProposedAction(); } } else { event->ignore(); } for (QWidget *widget : findChildren<QWidget *>()) { if (!widget->isVisible()) widget->deleteLater(); }}捕获鼠标按下事件void DragWidget::mousePressEvent(QMouseEvent *event){ QLabel *child = qobject_cast<QLabel*>(childAt(event->pos())); if (!child) return; QPoint hotSpot = event->pos() - child->pos(); QMimeData *mimeData = new QMimeData; mimeData->setText(child->text()); mimeData->setData(hotSpotMimeDataKey(), QByteArray::number(hotSpot.x()) + ' ' + QByteArray::number(hotSpot.y())); qreal dpr = window()->windowHandle()->devicePixelRatio(); QPixmap pixmap(child->size() * dpr); pixmap.setDevicePixelRatio(dpr); child->render(&pixmap); QDrag *drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(hotSpot); Qt::DropAction dropAction = drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction); if (dropAction == Qt::MoveAction) child->close();}关于更多在QtCreator软件可以找到: ...

October 4, 2019 · 1 min · jiezi

使用QRegExp正则的一个小技巧

使用字符字面量'R'来避免繁琐的转义字符。 使用Qt的正则表达式中需要转义的字符本身也可能需要转义。例如: \d需要写成\\d.需要写成\\.需要写转义字符\ QRegExp rx("^\\d\\d?$"); /* 匹配整数0到99 */可以使用字符字面量R来避免这种情况。 QRegExp rx(R"(^\d\d?$)");

September 20, 2019 · 1 min · jiezi

使用Qt获取系统版本

获取Windows,Mac,IOS,Android,Linux等系统版本信息。Qt 4版本 可以获取到系统版本的变量或函数 头文件#include <QSysInfo>使用公有静态变量和静态方法获取Windows系统版本const WinVersion WindowsVersionWinVersion windowsVersion ()使用公有静态变量获取Mac系统版本const MacVersion MacintoshVersion使用静态方法获取塞班系统版本和塞班S60系统版本S60Version s60Version ()SymbianVersion symbianVersion ()系统版本枚举部分预览enum MacVersion { MV_9, MV_10_0, MV_10_1, MV_10_2, ..., MV_YOSEMITE }enum S60Version { SV_S60_3_1, SV_S60_3_2, SV_S60_5_0, SV_S60_5_1, ..., SV_S60_Unknown }enum SymbianVersion { SV_9_2, SV_9_3, SV_9_4, SV_SF_1, ..., SV_Unknown }enum WinVersion { WV_32s, WV_95, WV_98, WV_Me, ..., WV_CE_based }Qt 5.0 - Qt 5.9版本 以下方法在Qt 5.9版本以上被官方标记为不推荐使用 头文件#include <QSysInfo>使用公有静态变量和静态方法获取Windows系统版本const WinVersion WindowsVersionQSysInfo::WinVersion windowsVersion()使用公有静态变量和静态方法获取Mac系统版本const MacVersion MacintoshVersionQSysInfo::MacVersion macVersion()系统版本枚举部分预览enum MacVersion { MV_9, MV_10_0, MV_10_1, MV_10_2, ..., MV_None }enum WinVersion { WV_32s, WV_95, WV_98, WV_Me, ..., WV_None }Qt 5.4 版本以上(推荐使用)头文件#include <QSysInfo> 获取系统类型QString productType()// windows, macos, osx, android, ios, // tvos, debian, winrt, watchos, unknown获取版本信息QString productVersion()部分版本信息列表: ...

September 10, 2019 · 1 min · jiezi

Qt中实现文本省略…

QFontMetrics类的elidedText()函数可以实现文本省略功能,假设有标签需要省略,如下所示: QString str = ui->label->fontMetrics().elidedText(string, Qt::ElideRight, 180);ui->label->setText(str);参数1,待省略文本参数2,省略模式,即…出现的位置 Qt::ElideLeft左边, Qt::ElideMiddle中间, Qt::ElideRight右边参数3, 可显示的字符串长度

September 8, 2019 · 1 min · jiezi

Qt中几个常用的标准对话框

/* * 这是几个标准对话框的使用方法 * 可以通过按钮触发槽,进而创建标准对话框对象 * 创建对象后所需操作仅仅是设置几个参数 */#include <QDebug>#include <QColorDialog> //颜色对话框#include <QFileDialog> //文件对话框#include <QFontDialog> //字体对话框#include <QInputDialog> //输入对话框#include <QProgressDialog> //进度对话框选取颜色的对话框 void MyWidget::on_pushButton_clicked(){ QColor color = QColorDialog::getColor(Qt::red, this, "颜色框"/*, QColorDialog::ShowAlphaChannel*/); //调用颜色对话框的静态函数,优点是不用创建对象 //前3参数为初始颜色,父窗口,对话框标题, //注释掉的可选参数功能是在对话框中显示透明度选项, qDebug()<< "color: " << color;//调试用 // qDebug的输出比如:color: QColor(ARGB 1, 0, 0, 0),分别是透明度alpha,红绿蓝 //alpha默认值1表示完全不透明,0是完全透明,三基色0~1对应0~255 /* //也可以创建对象,设置方面更灵活 QColorDialog dialog(Qt::red, this); //创建对象 dialog.setOption(QColorDialog::ShowAlphaChannel); dialog.exec(); //模态方式运行 QColor color = dialog.currentColor(); //获取当前颜色 qDebug() << "color: " <<color; //输出颜色信息 */}文件对话框,打开保存文件等,但以下函数均只是获取文件/文件夹路径和名称,并不执行打开、保存等实际操作 void MyWidget::on_pushButton_2_clicked(){ //该类有许多其他函数,可自行查阅 QString fileName = QFileDialog::getOpenFileName(this, "单文件选择框", "d:", "图片文件(*png *jpg);;文本文件(*txt)"); //以模态方式运行一个文件对话框,选择单个文件,不能是文件夹 //单击打开,返回所选文件名称格为如:fileName: "E:/爱佳利/Pictures/she/she.png" //多个文件是getOpenFileNames,需要使用QStringList fileNames = //4参数为父窗口,对话框标题,默认路径,文件类型过滤器,不指定则默认可选择所有类型的文件 //同类别两文件类型之间需要一个空格*png *jpg,不同类别之间两分号;; //另有getSaveFileName()保存文件和getExistingDirectory()获取文件夹路径,不能是文件 qDebug() << "fileName: " << fileName;/* QString fileName1 = QFileDialog::getSaveFileName(this, "保存文件对话框", "d:","图片类型(*png)"); qDebug() << "fileName1: " << fileName1 ; QString fileName2 = QFileDialog::getExistingDirectory(this, "文件路径对话框", "d:"); qDebug() << "fileName2: " << fileName2; QStringList fileNames = QFileDialog::getOpenFileNames(this, "多文件选择框", "d:", "图片文件(*png *jpg)"); qDebug() << "fileNames: "; for(auto x: fileNames){ qDebug() << x; }*/}选取字体的对话框 ...

September 8, 2019 · 2 min · jiezi

Qt在不同平台上的安装

Qt在不同平台上的安装来源 | 愿码(ChainDesk.CN)内容编辑愿码Slogan | 连接每个程序员的故事网站 | http://chaindesk.cn愿码愿景 | 打造全学科IT系统免费课程,助力小白用户、初级工程师0成本免费系统学习、低成本进阶,帮助BAT一线资深工程师成长并利用自身优势创造睡后收入。官方公众号 | 愿码 | 愿码服务号 | 区块链部落免费加入愿码全思维工程师社群 | 任一公众号回复“愿码”两个字获取入群二维码本文阅读时长:9minQt为移动和嵌入式设备提供了不同的外观,用户期望不同的演示风格。这是在框架内控制的,因此开发人员可以专注于开发单个应用程序。Qt框架在两个独立的发行版中发布,一个是商业版,一个是开源版(称为双重许可版)。通过这种方式,他们可以免费支持开源兼容的应用程序,同时为封闭源商业项目提供不受限制的使用。在2000年之前(2.2版本发布),免费分发的源代码已经获得了各种许可证,一些团体认为这些许可证与常见的开源计划不兼容。对于2.2版本,它被改为GPL许可,这解决了对该集团对真正的开源自由的承诺的任何担忧。2007年,Qt 4.5发布,他们将LGPL作为选择,为喜欢更宽松许可的开发人员提供选择。开始使用therecipe / qt为了开始我们对Qt的探索和对Go的绑定,我们将构建一个简单的hello world 应用程序。为了能够这样做,我们首先需要安装therecipe / qt,这取决于我们必须首先设置的各种先决条件。与Go-GTK一样,我们将依赖本机库,这需要我们设置CGo功能并安装适合当前平台的Qt库。准备CGoQt Go绑定需要CGo的存在才能使用本机库。在完整的开发系统上,可能已经建立了这个系统。安装QtQt网站提供各种安装方法,包括任何拥有Qt帐户(可以免费注册)的人都可以使用的定制在线安装程序。通常,Qt安装附带Qt Creator(项目IDE),GUI设计器,其他工具和示例。访问上一个站点将自动检测您的系统并建议最合适的下载(这通常是最佳选择)。请注意,Qt安装可能非常大。如果硬盘驱动器上没有至少40 GB的空间,则需要在安装前留出一点空间。一些操作系统提供Qt库和工具作为其包管理器的一部分,它通常提供更轻量级的安装,它将自动保持最新。在多个平台上安装Qt苹果系统在Apple macOS上,安装的最佳方法是使用Qt下载站点上提供的安装程序。下载macOS安装程序。下载后,打开包并在里面运行程序; 这将安装选定的编译器,工具和支持应用程序。如果在安装过程中遇到任何错误,第一步是检查Xcode安装是否完整且是最新的。视窗在Windows上安装比我们看到的其他一些工具包更简单,因为Qt安装程序有一个mingw捆绑包来设置大多数编译要求(尽管仍然建议为绑定阶段设置自己的编译器)下一个。要安装它,请转到前面列出的下载页面并访问Windows安装程序。运行下载的可执行文件,然后按照屏幕上的说明进 建议安装到默认位置。完成后,您就可以设置绑定了。Linux使用Qt网站上的在线安装程序是最简单的方法,虽然可以通过系统的包管理器进行安装(如果你想尝试包管理器方法,那么首先阅读Qt文档)。在大多数平台上,Qt下载网站将正确检测平台并提供简单的运行安装程序。下载文件后,您应该使其可执行,然后运行它:这将像在macOS上一样启动安装程序,从这里,按照屏幕上的说明操作并完成安装。许可证/ Qt帐户当涉及到登录屏幕时,如果您有,请输入您的Qt帐户详细信息。如果您有资格获得他们的开源许可证(GPL或LGPL),您可以跳过此步骤,确保电子邮件和密码字段为空。安装qt(绑定)要使用qt(Go Qt绑定),我们需要下载项目及其依赖项,然后运行安装脚本来配置和编译库。如果使用Windows,建议使用MSYS2终端。如果您将Qt下载安装到默认位置以外的任何位置,请确保将QT_DIR环境变量设置为您选择的位置。首先,应该使用go工具,运行go get和安装库及其依赖项go get。下载完成后,我们需要运行qtsetupqt项目中包含的工具; 所以,在cmd/qtsetup文件夹中,执行go run main.go。使用Linux终端:此过程完成后,绑定应该可以使用了。如果您遇到错误,那可能是因为Qt工具未正确安装或位置已自定义且您忘记设置QT_DIR环境变量。建立要使用Go构建我们的第一个qt应用程序,让我们创建另一个Hello World 应用程序。与前面的示例一样,我们将在单个应用程序窗口中使用简单的垂直框布局。以下代码应足以加载您的第一个应用程序:package mainimport (“os"“github.com/therecipe/qt/widgets”)func main() {app := widgets.NewQApplication(len(os.Args), os.Args)window := widgets.NewQMainWindow(nil, 0)window.SetWindowTitle(“Hello World”)widget := widgets.NewQWidget(window, 0)widget.SetLayout(widgets.NewQVBoxLayout())window.SetCentralWidget(widget)label := widgets.NewQLabel2(“Hello World!”, window, 0)widget.Layout().AddWidget(label)button := widgets.NewQPushButton2(“Quit”, window)button.ConnectClicked(func(bool) {app.QuitDefault()})widget.Layout().AddWidget(button)window.Show()widgets.QApplication_Exec()}让我们从这段代码片段中注意一些细节。每个窗口小部件构造函数都采用(通常)两个参数,每个参数都是父窗口小部件和flags参数。传入的其他类型通常会在这些值之前添加,并在函数名称中包含附加参数的注释。例如, widgets.NewQLabel2(title, parent, flags)相当于widgets.NewQLabel(parent, flags).SetTitle(title)。此外,您将看到布局应用于新的widgets.QWidget直通SetLayout(layout),并通过设置为窗口内容window.SetCentralWidget(widget)。要加载显示并运行应用程序,我们调用window.Show()然后widgets.QApplication_Exec()。此文件以通常的方式构建 go build hello.go:由于Qt框架的大小,构建的文件非常大。在针对特定分发进行包装时,这将显着降低。运行构建阶段的输出是一个二进制文件,可以在命令行上或通过双击文件管理器在当前计算机上执行。另外,您可以直接执行它 - 无论go run hello.go哪种方式,您应该看到一个简单的窗口,如下所示:在此阶段,二进制文件可以在具有安装Qt的相同体系结构的计算机上执行。对象模型和事件处理Qt框架是使用C++语言编写的 ,并且以前用C++编码的人很熟悉它的大部分架构。值得注意的是,Go不是一种完整的面向对象语言,因此不能直接匹配这些功能。特别是,我们应该看一下继承,因为它对Qt对象模型很重要。继承Qt API是一个完全面向对象的模型,它大量使用了继承模型。虽然Go并不真正支持传统方式的面向对象继承,但它的组合方法非常强大,并且在其位置上运行良好。结果意味着您可能不会注意到差异!内存管理正如您在前面的示例中已经注意到的,每个窗口小部件都希望将父窗口传递给构造函数。这使得Qt框架能够在移除窗口小部件树时处理整理和释放内存。QObject(这是所有Qt API的基础对象)跟踪其子对象,因此,在删除时,也可以删除其子对象。这使得复杂窗口小部件层次结构的创建和删除更容易正确处理。要使用此功能,您应该始终记住将父对象传递给窗口小部件的构造函数(以函数开头的Go函数New…),尽管传递nil可能看起来像是在工作。信号和插槽Qt类似于GTK +,这是一个事件驱动的框架,广泛使用信号来处理事件管理和数据通信。在Qt中,这个概念分为信号和插槽; 信号是事件发生时产生的信号,信号是接收信号的信号。设置插槽以接收信号的动作称为连接,这导致在调用其连接信号时调用插槽功能。在Qt中,这些是类型化事件,意味着每个信号都有一个与之关联的类型参数列表。定义信号时,此类型已设置,并且任何希望连接到信号的插槽都需要具有相同的类型。s.ConnectMySignal( func(msg string) { log.Println(“Signalled message”, msg) })信号和插槽是Qt Designer生成的高级用户界面,是处理多线程应用程序的推荐方法。信号可以从后台线程触发,并且用户接口代码可以将该信号连接到其自己的插槽,实质上是监听信号。当信号触发时,任何相关数据(信号参数)将从一个线程传递到另一个线程,因此可以在GUI更新中安全使用。由于Qt是对Qt API的轻量级绑定,因此特定于Go的文档很少,但您可以在Qt的博客文章中找到有关Qt设计和官方文档中提供的所有类的更多信息。 ...

April 8, 2019 · 1 min · jiezi

QtCharts之QValueAxis类

文章首发自公众号:: nullobject 。个人站点:https://www.nullobject.cn 这篇文章主要讲解QValueAxis类的API及其使用。0x00 关于QValueAxisQValueAxis,即数值轴,适用于具有连续数据坐标的图表。QValueAxis作为QAbstractAxis的实现类之一,在继承了QAbstractAxis特性的同时,根据数值轴的特点封装实现了许多方便实用的功能。QValueAxis使用起来也非常简单,在上一篇文章QAbstractAxis中的示例代码均是使用QValueAxis实例来说明的。本文主要介绍QValueAxis实现的功能。QValueAxis使用示例:#include <QApplication>#include <QChartView>#include <QLineSeries>#include <QValueAxis>#include <QDebug>QT_CHARTS_USE_NAMESPACEint main(int argc, char *argv[]){ QApplication a(argc, argv); // 创建QChartView对象 QChartView *chartView = new QChartView; chartView->setRenderHint(QPainter::Antialiasing); // 创建序列 QLineSeries *series = new QLineSeries(); // 隐藏图例 chartView->chart()->legend()->hide(); // 添加数据 series->append(0,2); series->append(QPointF(2,6)); series->append(3,8); series->append(7,9); series->append(11,3); *series << QPointF(11,2) << QPointF(15,5) << QPointF(18,4) << QPointF(19,2); // 添加序列到图表 chartView->chart()->addSeries(series); // 创建X轴 QValueAxis *axisX = new QValueAxis; // 设置QValueAxis属性 axisX->setRange(10, 20.5); axisX->setTickCount(5); axisX->setLabelFormat("%.2f"); chartView->chart()->setAxisX(axisX, series); // 创建Y轴 QValueAxis *axisY = new QValueAxis; axisY->setRange(0, 10); axisY->setTickCount(5); axisY->setLabelFormat("%.2f"); chartView->chart()->setAxisY(axisY, series); chartView->resize(400,300); chartView->show(); return a.exec();}效果:0x01 设置刻度线在Qt 5.12版本之前,QValueAxis只支持固定的刻度线设置,只能通过setTickCount设置刻度线的数量,刻度线会平均分布在坐标轴。而在Qt最新版本5.12版中,QValueAxis支持通过tickType属性来设置刻度线为固定分布(TicksFixed)或者是动态分布(TicksDynamic)。QValueAxis::TickType tickType:设置刻度类型QValueAxis::TickType tickType() const;void setTickType(QValueAxis::TickType type);其中TickType为QValueAxis中声明的用于描述刻度类型(刻度线和刻度标签在轴上的位置)的枚举类:enum TickType { TicksDynamic = 0, TicksFixed};tickType属性改变时触发tickTypeChanged(QValueAxis::TickType)信号TicksFixed 设置刻度位置为均匀分布QValueAxis默认的刻度类型为TicksFixed。将刻度类型设置为TicksFixed,可以通过设置tickCount属性值来指定刻度线的数量,此时刻度线会被均匀地地分布在坐标轴上。默认的刻度线数量是5条,最低数量不能低于2。:axisY->setRange(0, 10);axisY->setTickType(QValueAxis::TickType::TicksFixed);axisY->setTickCount(6);效果:其中tickCount的操作函数声明如下:int tickCount() const;void setTickCount(int count);tickCount属性修改只在tickType值为TicksFixed时有效。tickCount属性改变时触发tickCountChanged(int)信号。TicksDynamic 设置刻度位置为动态分布动态设置刻度的位置,需要通过设置锚点tickAnchor和刻度间距tickInterval属性值来实现,必须要设置指定tickInterval才有效果:axisY->setRange(0, 10);axisY->setTickType(QValueAxis::TickType::TicksDynamic);// 设置刻度间距为3axisY->setTickInterval(3);// 设置锚点坐标为5axisY->setTickAnchor(5);效果:其中锚点tickAnchor属性用于指定刻度线和标签开始绘制的位置,刻度间距tickInterval属性用于指定刻度与刻度之间的距离。上示例子中将tickAnchor和tickInterval分别设置为5和3,表示刻度将从坐标为5的位置开始,向轴两端分布,如果不显示设置tickAnchor,则默认从坐标轴的起始位置开始分布;tickInterval的类型为qreal类型,支持设置刻度间隔为小数。修改tickAnchor和tickInterval对应会触发的信号分别为:tickAnchorChanged(int)和tickIntervalChanged(qreal)。0x02 设置坐标轴显示范围QValueAxis通过max和min两个属性来表示坐标轴的最大和最小值,可以通过调用对应的方法来设置坐标轴的显示范围。qreal max:设置坐标轴最大值qreal max() const;void setMax(qreal max);max属性修改会触发maxChanged(qreal)信号。qreal min:设置坐标轴最小值qreal min() const;void setMin(qreal min);min属性修改会触发minChanged(qreal)信号。setRange:设置坐标轴显示范围void setRange(qreal min, qreal max);除了可以调用setMax或setMin单独设置坐标轴的极值外,也可以直接调用setRange同时设置坐标轴的最大、最小值:// axisY->setMin(0);// axisY->setMax(10);// 等价于setRange(0,10);axisY->setRange(0, 10);当坐标轴的最大值max或者最小值min发生改变时,都会触发rangeChanged(qreal min,qreal max)信号。0x03 设置刻度标签显示格式QValueAxis坐标轴支持通过labelFormat属性设置标签的显示格式,例如指定显示小数位数等。QString labelFormat:设置标签格式QString labelFormat() const;void setLabelFormat(const QString &format);其中传参format为需要指定的字符串格式,例如设置为显示小数点后两位数:axisX->setLabelFormat("%.2f");目前labelFormat支持设置以下转换说明符、长度修饰符以及标准C++库中printf()函数提供的格式标志:d, i, o, x, X, f, F, e, E, g, G, c。具体使用可以百度搜索了解:printf() 输出格式。修改该属性会触发labelFormatChanged(const QString&)信号。0x04 The End :) ...

April 3, 2019 · 1 min · jiezi

QtCharts之QAbstractAxis类

文章首发自公众号:: nullobject 。个人站点:https://www.nullobject.cn这篇文章主要讲解QAbstractAxis类的API及其使用0x00 QtCharts中坐标轴结构在学习QAbstractAxis类之前,需要先熟悉QtCharts中轴的组成元素都有哪些:QtCharts中,一个坐标轴的内容大致包含以下几种:轴标题(title)、轴刻度标签(labels)、轴线(lines)、网格线(grid lines)、和轴阴影(shades)。通过QAbstractAxis可以分别对以上几种元素进行单独控制。0x01 设置标题QAbstractAxis可以设置坐标轴标题的显示/隐藏、颜色、内容和字体等几个属性。示例例如,设置坐标轴标题内容为axisTitle,颜色为蓝色,字体15号加粗,并显示出来:// 显示标题 axisXLeft->setTitleVisible(true); // 设置标题内容 axisXLeft->setTitleText(QStringLiteral(“I am axis’s title”));// 设置颜色 axisXLeft->setTitleBrush(QBrush(Qt::blue)); // 设置字体12号加粗 QFont font = axisXLeft->titleFont(); font.setPointSize(15); font.setBold(true); axisXLeft->setTitleFont(font); 结果:titleVisible:设置标题显示bool isTitleVisible() const;void setTitleVisible(bool visible = true);坐标轴标题默认情况下是显示的。修改该属性时会触发titleVisibleChanged(bool visible)信号。titleText:设置标题内容QString titleText() const;void setTitleText(const QString &title);默认情况下,QAbstractAxis不会设置任何标题内容。用户可以根据需要修改坐标轴标题。标题发生改变时会触发titleTextChanged(const QString &text)信号。titleFont:设置标题字体QFont titleFont() const;void setTitleFont(const QFont &font);该属性通过QFont来设置标题的字体风格。该属性发生改变时,会触发titleFontChanged(const QFont &font)信号。titleBrush:设置标题颜色画刷QBrush titleBrush() const;void setTitleBrush(const QBrush &brush);注意目前只支持通过画刷来设置颜色,不支持设置画刷得其他效果(如画刷风格BrushStyle等)。该属性发生改变会触发titleBrushChanged(const QBrush &brush)信号。0x02 设置刻度标签QAbstractAxis除了可以设置坐标轴刻度标签的显示/隐藏、颜色、和字体几个属性外,还可设置刻度标签的倾斜角度。示例例如,设置轴刻度标签显示,倾斜-45度,红色,加粗9号字体:// 显示刻度标签 axisXLeft->setLabelsVisible(true); // 倾斜45度 axisXLeft->setLabelsAngle(-45); // 颜色 axisXLeft->setLabelsColor(Qt::red); // 加粗9号 font = axisXLeft->labelsFont(); font.setBold(true); font.setPointSize(9); axisXLeft->setLabelsFont(font); 效果:labelsAngle:设置倾斜角度int labelsAngle() const;void setLabelsAngle(int angle);设置刻度标签的倾斜角度,默认为水平显示。该属性发生改变时,触发labelsAngleChanged(int angle)信号。labelsColor、labelsBrush:设置颜色QColor labelsColor() const;void setLabelsColor(QColor color);QBrush labelsBrush() const;void setLabelsBrush(const QBrush &brush);轴刻度标签的颜色可以通过labelsColor者labelsBrush任一属性设置来实现。两者的区别在于被修改时触发的信号不一样、修改labelsColor属性稍微便利些而已,且通过修改labelsBrush实现时也只支持修改QBrush颜色,而不支持QBrush的其它属性设置。实际上修改轴刻度标签颜色,内部都是通过设置QBrush来实现。修改labelsColor属性会触发labelsColorChanged(QColor color)信号;修改labelsBrush属性会触发labelBrushChanged(const QBrush &brush)信号。labelsFont:设置字体风格QFont labelsFont() const;void setLabelsFont(const QFont &font);使用方式与修改轴标题字体相同。该属性发生改变会触发labelsFontChanged(const QFont &font)信号。labelsVisible:设置显示/隐藏刻度标签bool labelsVisible() const;void setLabelsVisible(bool visible = true);默认为显示刻度标签。该属性修改时触发labelsVisibleChanged(bool visible)信号:0x03 设置轴线可以设置轴线显示/隐藏、轴线画笔、方向倒置。示例例如显示轴线,并为其设置颜色为红色、宽度为2的画笔:// 显示轴线axisXLeft->setLineVisible(true); // 设置轴线画笔QPen pen = axisXLeft->linePen(); pen.setColor(Qt::red); pen.setWidth(2); axisXLeft->setLinePen(pen);效果:lineVisible:设置显示轴线bool isLineVisible() const;void setLineVisible(bool visible = true);默认会显示轴线。该属性发生改变时会触发lineVisibleChanged(bool visible)信号。linePen:设置轴线画笔QPen linePen() const;void setLinePen(const QPen &pen);通过设置轴线画笔,可以自定义轴线宽度、绘制颜色等。如果只需要修改轴线颜色,可以直接调用setLinePenClolor(QColor color)方法。改属性发生改变时会触发linePenChanged(const QPen &pen)信号。通过setLinePenColor修改轴线颜色时会触发gridLineColorChanged(const QColor &color)信号。reverse:翻转坐标轴bool isReverse() const;void setReverse(bool reverse = true);将坐标轴的极值方向翻转,左侧为默认reverse=false,右侧为翻转之后的效果:注意:该属性仅在使用笛卡尔坐标系的图表上有效,比如折线、曲线、散点图和使用笛卡尔坐标系的面积图。reverse值改变时会触发reverseChanged(bool)信号。0x04 设置网格线QtCharts的坐标轴网格线分为主网格线gridLine和次网格线minorGridLine,主网格线相当于刻度线的延申(例如在QValueAxis),次网格线分布在相邻的两条主网格线之间,且次网格线需要由QAbstractAxis的子类,即具体类型的坐标轴实现才能支持。示例:以QValueAxis为例,显示主次网格线并设置颜色:// 设置网格线/刻度数量axisXLeft->setTickCount(5);axisXLeft->setMinorTickCount(5);// 主网格线axisXLeft->setGridLineVisible(true);axisXLeft->setGridLineColor(Qt::darkGray);// 次网格线axisXLeft->setMinorGridLineVisible(true);axisXLeft->setMinorGridLineColor(Qt::gray);效果:gridVisible、minorGridVisible设置显示网格线// 获取/设置显示主网格线,默认显示bool isGridLineVisible() const;void setGridLineVisible(bool visible = true);// 获取/设置显示次网格线,默认不显示bool isMinorGridLineVisible() const;void setMinorGridLineVisible(bool visible = true);gridVisible改变时触发gridVisibleChanged(bool visible)信号。minorGridVisible改变时触发minorGridVisibleChanged(bool visible)信号。gridLinePen、minorGridLinePen设置网格线画笔// 设置主网格线画笔QPen gridLinePen() const;void setGridLinePen(const QPen &pen);// 设置次网格线画笔QPen minorGridLinePen() const;void setMinorGridLinePen(const QPen &pen);与轴线颜色的设置类似,如果只需要修改网格线的颜色,可以直接调用对应的setGridLineColor(const QColor &color)或者setMinorGridLineColor(const QColor &color)方法快速设置。gridLinePen改变时触发gridLinePenChanged(const QPen &pen)信号。minorGridLinePen改变时触发minorGridLinePenChanged(const QPen &pen)信号。gridLineColor改变时触发gridLineColorChanged(const QPen &pen)信号。minorGridLineColor改变时触发minorGridLineColorChanged(const QPen &pen)信号。0x05 设置阴影QtCharts坐标轴阴影指的是相邻主网格线之间的区域。QAbstractAxis中提供了对阴影边框(shadesBorder)、阴影区域(shadesArea)的设置:示例以QValueAxis为例,设置坐标轴的阴影边框和填充:// 显示阴影区域,包括阴影边框axisXLeft->setShadesVisible(true);// 设置阴影边框QPen sPen = axisXLeft->shadesPen();sPen.setWidth(5);sPen.setColor(Qt::yellow);axisXLeft->setShadesPen(sPen);//axisXLeft->setShadesBorderColor(Qt::darkYellow);// 设置阴影区域颜色填充axisXLeft->setShadesBrush(QBrush(QColor(48,157,255,125)));//axisXLeft->setShadesColor(Qt::blue);效果:shadesBorderColor、shadesPen设置阴影边框QColor shadesBorderColor() const;void setShadesBorderColor(QColor color);QPen shadesPen() const;void setShadesPen(const QPen &pen);设置阴影边框,如果只需要改变颜色可以直接调用setShadesBorderColor(QColor),需要设置更多属性可以调用setShadesPen(const QPen&)为阴影边框设置一个画笔对象。shadesBorderColor属性改变会触发shadesBorderColorChanged(QColor color)信号。shadesPen属性改变会触发shadesPenChanged(const QPen &pen)信号。shadesBrush、shadesColor设置阴影区域填充QBrush shadesBrush() const;void setShadesBrush(const QBrush &brush);QColor shadesColor() const;void setShadesColor(QColor color);设置阴影区域填充,如果只需要修改颜色可以直接使用setShadesColor(QColor),需要设置更多效果可以调用setShadesBrush(const QBrush&)为阴影区域设置一个画刷,例如,设置画刷的填充风格为DiagCrossPattern:QBrush sBrush = axisXLeft->shadesBrush();sBrush.setColor(QColor(48,157,255,125));// 设置画刷风格sBrush.setStyle(Qt::BrushStyle::DiagCrossPattern);axisXLeft->setShadesBrush(sBrush);效果:shadesBrush值修改会触发shadesBrushChanged(const QBrush &brush)信号。shadesColor值修改会触发shadesColorChanged(QColor color)信号。0x06 The End :) ...

April 2, 2019 · 2 min · jiezi

QtCharts之QXYSeries

文章首发自公众号:: nullobject 。个人站点:https://www.nullobject.cn这篇文章主要介绍QXYSeries类的API及其使用0x00 前言QXYSeries作为QAbstractSeries的派生类之一,主要负责实现以二维点集为数据源,坐标类型为二维坐标系的图表类型,包括折线图、曲线图和散点图等。QXYSeries封装了大量对数据源进行增删改操作的函数和信号,同时内部实现了控制数据点在坐标系上的显示形态(点标签的格式、颜色、是否显示等)的功能。0x01 显示和控制点标签Qt图表中的点标签指的是数据点在图表上对应位置的附加信息显示(比如点的坐标或者其他信息):QXYSeries类中提供了pointLabels*开头的五个属性及对应的方法和信号来操作点标签的显示风格。pointLabelsClipping : 获取和设置是否对点标签超出绘图区域边缘的部分进行裁剪:bool pointLabelsClipping() const;void setPointLabelsClipping(bool enabled = true);效果:可以看到,当设置pointLabelsClipping属性为true(默认值)时,点标签超出绘图区域的部分会被裁剪掉。pointLabelsClipping属性发生改变时,会触发pointLabelsClippingChanged(bool clipping)信号。pointLabelsColor : 获取和设置点标签的显示颜色:QColor pointLabelsColor() const;void setPointLabelsColor(const QColor &color);效果:上图分别为将pointLabelsColor属性设置为黑色和绿色的效果。看到这您有可能会有疑问:咦怎么只改变了坐标的颜色,而折线上点的颜色没有变?注意了,这里的点标签是指图表上对数据点加以说明的信息部分,不包括点本身的显示。pointLabelsColor属性发生改变时,会触发pointLabelsColorChanged(const QColor &color)信号。pointLabelsFont : 获取和设置点标签的显示字体:QFont pointLabelsFont() const;void setPointLabelsFont(const QFont &font);该属性通过一个QFont设置来实现:// 获取pointLabels默认字体QFont font = series->pointLabelsFont();// 加粗font.setBold(true);// 斜体font.setItalic(true);// 设置字体大小font.setPointSize(12);// 设置字体为Arial类型font.setFamily(QStringLiteral(“Arial”));// 更新pointLabels字体series->setPointLabelsFont(font);效果:pointLabelsFont属性发生改变时,会触发pointLabelsFontChanged(const QFont &font)信号。pointLabelsFormat : 获取和设置点标签的显示格式:QString pointLabelsFormat() const;void setPointLabelsFormat(const QString &format);QXYSeries类提供了两个占位符来设置点标签显示真实坐标数据:@xPointX轴坐标@yPointY轴坐标例如,我们需要以:(15,23)这样的格式来显示点标签,可以这样设置,即可实现上文中点标签的显示格式效果:// 设置点标签格式series->setPointLabelsFormat(QStringLiteral("(@xPoint,@yPoint)"));pointLabelFormat属性默认被设置为没有括号的坐标格式:@xPoint, @yPoint。pointLabelsFormat属性发生改变时,会触发pointLabelsFormatChanged(const QString &format)信号。pointLabelsVisible : 获取和设置显示/隐藏点标签:bool pointLabelsVisible() const;void setPointLabelsVisible(bool visible=true);该属性默认被设置为false。// 隐藏点标签series->setPointLabelsVisible(false);效果:pointLabelsVisible属性发生改变时,会触发pointLabelsVisibilityChanged(bool visible)信号。pointsVisible : 获取和设置显示/隐藏点在图表上的标注:bool pointsVisible() const;void setPointsVisible(bool visible=true);与pointsLabelVisible不同,pointsLabelVisible设置的是点标签的显示,而pointsVisible设置的是点本身在图表上的位置标注。该属性默认被设置为false。对比显示和隐藏点标注效果:0x02 对数据源进行增删改QXYSeries类中封装了一系列的重载方法用于操作图表的数据源进行增删改。QXYSeries内部用一个模板类型为QPointF的QVector来持有数据源,其声明在qxyseries_p.h头文件内:增加数据可以调用append的对应重载方法,或者是重载操作符<<添加单个点或者整个点集到数据源的尾部:void append(qreal x, qreal y);void append(const QPointF &point);void append(const QList<QPointF> &points);QXYSeries& operator<<(const QPointF &point);QXYSeries& operator<<(const QList<QPointF> &points);也可以调用insert方法将数据点插入到数据源的指定位置:void insert(int index, const QPointF &point);对应地,不管以何种方式,成功添加数据后都会触发pointAdded(int index)信号,index为被添加的数据的下标。需要注意:每添加一个点就会触发一次pointAdded信号,即批量添加数据时会触发对应次数的pointAdded。删除数据QXYSeries提供了remove重载方法和removePoints方法来移除目标数据:// 删除指定坐标的点void remove(qreal x, qreal y);void remove(const QPointF &point);// 删除指定索引下标的点void remove(int index);// 从下标index位置开始,删除count数量的点void removePoints(int index, int count);与增加数据类似,成功删除数据后会触发对应次数的pointRemoved(int index)信号,index为被删除的数据的下标。修改数据源修改数据源通过replace系列的重载方法实现:// 替换具体坐标的点void replace(qreal oldX, qreal oldY, qreal newX, qreal newY);void replace(const QPointF &oldPoint, const QPointF &newPoint);// 替换指定索引下标的点void replace(int index, qreal newX, qreal newY);void replace(int index, const QPointF &newPoint);// 替换整个数据源void replace(QList<QPointF> points);void replace(QVector<QPointF> points);当只替换数据源的局部数据点(调用前四种重载方法)时,会触发pointReplaced(int index)信号,index为被替换的点的下标;而当替换了整个数据源数据(调用后两种方法)时,则会触发pointsReplaced()信号。需要注意:调用replace后两种重载替换整个数据源时,传QList还是传QVector在性能上是有所区别的:直接传入QList结构的数据集远远比逐个点替换或者先清除所有点再添加这两种方式的效率要高。而直接传入QVector结构的数据集又比前者效率要高。因此:需要批量更新数据点时,应当优先选择void replace(QVector<QPointF> points);这个重载方法。究其原因:本小节一开始就介绍了,QXYSeries内部持有数据源的数据结构为QVector<QPointF>,而参数为QList<QPointF>的重载方法的内部实现也是将QList转换为QVector,再调用参数为QVector<QPointF> 的重载方法实现对数据的更新,无形中多了一个数据转换的步骤,拉低性能:Tips:QList和QVector两个容器本身的效率上也是有区别的,Qt官方推荐优先使用QVector。详细可以参考QVector的官方文档介绍。获取数据源QXYseries提供了返回类型分别为QList<QPointF>和QVector<QPointF>的方法获取数据源:QList<QPointF> points() const;QVector<QPointF> pointsVector() const;与更新replace方法批量更新数据源的重载类似,points()方法获取数据源的方法,内部实现也是获取原始数据源再将其转为QList类型返回;pointsVector()方法则直接返回原始的QVector数据源。0x03 QXYSeries中的鼠标操作QXYSeries共提供了五个鼠标事件响应信号,分别是:单击clicked、双击doubleClicked、鼠标键按下pressed,鼠标键松开released、光标移到图表线上或从图表移开hovered:series->connect(series,&QLineSeries::clicked,[](const QPointF& point){ qDebug() << “point clicked:” << point;});series->connect(series,&QLineSeries::doubleClicked,[](const QPointF& point){ qDebug() << “point double clicked:” << point;});series->connect(series,&QLineSeries::hovered,[](const QPointF& point,bool state){ qDebug() << “point hovered:” << point << " state:" << (state?“光标移动到图表上”:“光标从图表上移开”);});series->connect(series,&QLineSeries::pressed,[](const QPointF& point){ qDebug() << “point pressed:” << point;});series->connect(series,&QLineSeries::released,[](const QPointF& point){ qDebug() << “point released:” << point;});运行程序,执行光标移动到图表序列上->左键双击->光标从图表序列上方移开,结果如下:point hovered: QPointF(4.58291,8.71473) state: moved to seriespoint pressed: QPointF(4.58291,8.71473)point released: QPointF(4.58291,8.71473)point clicked: QPointF(4.58291,8.71473)point double clicked: QPointF(4.58291,8.71473)point pressed: QPointF(4.58291,8.71473)point released: QPointF(4.58291,8.71473)point clicked: QPointF(4.58291,8.71473)point hovered: QPointF(4.71022,8.18182) state: moved from series0x04 The End. ...

March 30, 2019 · 2 min · jiezi

基于ffmpeg+nginx+UscreenCapture的局域网直播系统搭建

本文的创作灵感是由Windows screen recording with FFmpeg UScreenCapture and NGINX RTMP module而来,笔者建议大家可以先去原文看一下大致的内容,但需要一定的英文阅读能力,本文并不是照搬翻译,而是根据原文成功搭建直播系统的基础上增加了服务器录制和本地录制的内容:系统环境:Windows 7 Service Pack 1 64bit软件准备:ffmpeg:这里笔者使用原文的地址下载了官方打包好的可执行文件nginx:这里笔者使用原文的地址下载了编译好nginx rtmp module的打包文件UScreenCapture(x64):请参看原文下载地址QtAv:笔者在二次开发时选择的库 (可选)vlc-qt:基于vlc的库(可选),笔者一开始做本地录制功能的时候选择了这个库,但是在尝试本地播放视频同时录制的时候,发现开始录制后没有停止录制的接口,于是就放弃了libvlc:vlc官方的开源组件,可供其他开发平台调用(可选),上面的vlc-qt是基于Qt开发环境的,如果不依赖Qt可以尝试用这个库,不过需要看一下官方的开发文档,笔者并没有相关开发经验,就不做过多介绍了产品需求:将某台PC的桌面作为视频直播源,推送至直播服务器,可供局域网内的其他PC通过视频播放器观看,观看直播的同时可以随时开始/停止录制当前的播放内容开发步骤:安装UScreenCapture(x64),后续作为可用视频输入源供ffmpeg使用点击下载好的nginx目录中的nginx.exe,启动nginx服务器,根据conf文件夹中的nginx.conf配置,此时服务器会监听81-web端口和1935-rtmp端口打开命令提示符(cmd),输入以下命令,此命令用于确认是否正确安装并ffmpeg可以识别UscreenCapture作为视频流输入源:[这里是ffmpeg文件夹的绝对路径]/ffmpeg.exe -list_devices true -f dshow -i dummy[这里是ffmpeg文件夹的绝对路径]/ffmpeg -f dshow -i video=“UScreenCapture” -preset ultrafast -f flv rtmp://127.0.0.1/view/test上述代码的作用就是,以UScreenCapture作为输入源,编码速率设定为ultrafast,编码格式为flv,将视频媒体流推送到rtmp://127.0.0.1/view/test这个地址上当然,其中输入源可以选择摄像头,本地视频文件等;编码速率,格式以及推送地址都可以根据需要进行配置,最终的目的都是为了把本地源推送至服务器以供远程播放器使用测试直播是否正常可以使用ffmpeg文件夹中的ffplay rtmp://127.0.0.1/view/test, 也可以使用其他播放器,如vlc player如果需要录制视频功能,可以选择以下两种方案,录制后的文件各自保存的位置不同播放端录制使用QtAv的VideoDecoder+VideoEncoder+AVMuxer+AVDemuxer,将播放源进行编解码后保存到本地,因为官方没有正式的例子,下文的代码仅供演示使用(代码整理中,后续尽快添加)To Be Continued。。。服务器端录制 利用nginx rtmp module的rtmp_control功能,通过HTTP协议在服务器端进行开始录制及停止录制操作,nginx端的配置见下文server { …… location /control { rtmp_control all; }}rtmp { server { listen 1935; application view {下面的录制命令app参数会用到这个配置名 live on; recorder NAME_THIS_WHAT_YOU_WANT { # 下面的录制命令rec参数会用到这个配置名 record all manual; record_suffix -%Y-%m-%d-%H%M.mp4; record_path C:\nginx\recordings; record_unique on; } } }}rtmp://127.0.0.1/view/test,其中view是服务器配置的rtmp服务名,test是自定义的视频流名称启动录制:http://localhost:81/control/record/start?app=view&name=自定义的视频流名称&rec=NAME_THIS_WHAT_YOU_WANT停止录制:http://localhost:81/control/record/stop?app=view&name=自定义的视频流名称&rec=NAME_THIS_WHAT_YOU_WANT ...

February 13, 2019 · 1 min · jiezi

干货 - 如何逆向解决QT程序汉化中的乱码问题

作者:逆向驿站原文链接https://mp.weixin.qq.com/s/aG…一款QT开发的国外软件,大概率是没有做中文支持的,所以你汉化中,不论怎么设置编码都一定是乱码。面对这个问题,你去互联网上找答案,答案却大多是复制粘贴的开发中解决乱码的文章,可是我们是要逆向中解决,于是吾爱破解、汉化新世纪等找过来,盘搜搜个遍,发现基本不是资源过期就是驴唇不对马嘴的抄袭贴,所以我来发一篇干货准备【环境和工具】win7/xp虚拟机环境pdf2any原版安装程序(qt开发的国外程序,不支持中文,无源码)ollydbgRadialix 3010editorqt-win-opensource-4.8.2-mingw.exe(相当于QT库支持,核心部件)qt-creator-opensource-windows-x86-3.3.0.exe(相当于编辑器而已)MinGW.rar(编译调试环境)最后三个是QT开发环境,搭建起来有利于学习,当然如果你不想玩QT开发那其实只用装第一个就行了,里面有QT各种库函数的源码,遇到相应程序浏览源码即可【学习层次】生搬硬套,能解决大部分QT汉化中乱码问题搞懂搞透,举一反三详解视频干货视频,放出来尽可以去传播,但是不要干那种修改我版权说是自己视频的事,那就low了!https://v.qq.com/x/page/o0825…实战图文一.某QT程序汉化中遇乱码QT开发的国外软件,若是没有特意做中文支持,不论怎么搞,都是乱码例如汉化下图中的标题registration乱码二.逆向分析寻找原因1.OD中定位标题字符串程序载入OD,定位"registration",并查看,程序中都有那些位置会调用这个字符串,如图发现有三个地方调用了这个字符串地址,全部下断点2.运行观察断点下好后,运行程序,观察调用字符串的逻辑流程,发现下的三个断点中有两个在程序启动会被调用,调用的目的分别是作为两个QT库函数的参数,如下图3.正向查阅相关函数源码这里多说一句,玩逆向不只光玩逆向,一直强调逆向是一种思维,逆向破解的逆向就是开发,活用开发资料,逆向破解中往往事半功倍。安装QT后就可以看QT各种库函数的源码和资料,如果你想更深入的了解,给吃透的话,最好的方式莫过于自己开发,自己逆向分析。开始寻找目标函数源码,everything搜两个函数类命,QCoreApplication和QMetaObject,如下图打开源码,阅读相关函数,源码如下QCoreApplication::translate函数定义,发现核心参数就是这个枚举类型,当枚举类型为0的时候中文是乱码,当是1的时候中文没问题QMetaObjcet::tr函数实现,发现这个函数的实质其实是以枚举类型参数为0去调用QCoreApplication::translate4.逆向中验证上面的正向源码从新载入OD,重新运行,根据上面正向查阅的源码资料观察相应的两个库函数在逆向中的体现,如下图可见,两个函数其实最终调用的都是第一个函数,而核心关键点就是枚举类型参数的值,那么我们在第一个库函数入口【6A2B5818】下断点动态运行一下,堆栈中观察参数的变化,如下动图5.总结所有线索标题字符串Registration被函数QCoreApplication::translate作为参数标题字符串Registration被函数QMetaObeject::tr作为参数两个函数核心都是QCoreApplication函数QCoreApplication控制中文乱码核心参数是枚举类型,值0乱码,1是utf-8支持中文QMetaObeject::tr调用的QCoreApplication::translate关键枚举类型是0,所以标题最后是不支持中文的,导致一汉化产生乱码三、修改QT库QTCore4.dll解决问题其实上面的分析如果已经完全搞懂了,其实就已经知道怎么解决了,而且解决方法有很多,但是都并不能保证所有程序的通用性,毕竟一个开发一个样,这次他用这个库函数,没准下次他用另外一个,所以吃透后,具体问题具体分析才是任何武功中的“无招胜有招”!针对于这个案例,解决的思路就至少有以下三种程序领空修改,让其调用的QMetaObeject::tr更换为QMetaObeject::trUtf8(阅读源码就会发现有这个函数,为什么此案例他没调用这个,因为是国外软件,他压根没想支持中文,所以他用的是tr而不是trutf8),这样修改的好处,可以相对保证汉化者的劳动成果,毕竟修改的地方可能会多,而且只在程序领空修改,但通用性差,换个程序百分百没用修改库函数QMetaObeject::tr,让他调用QCoreApplication::translate时,枚举参数设置成1,也就是压根用逆向的方式把QMetaObeject::tr函数改成了QMetaObeject::trUtf8,好处通用性较强。修改QCoreApplication::translate内部逻辑,让枚举类型为0时,也按为1的流程逻辑走(最常见的爆破套路),有点通用性很强,极大程度适用很多QT程序汉化乱码问题后两种方法都是修改QT库函数,所以最终体现是修改了QTcore4.dll这个文件,方法分别如下方法1方法2修改后,生成新的qtcore4.dll文件,替换原版qtcore4.dll就会发现,再去汉化此软件,乱码问题已经解决了。我们依然以汉化题目为示例,OD中修改数据(如果你是大量汉化工作就别用OD了否则累死哦),注意要是utf-8的内存编码形式,关于编码常识可以在公众号内回复“编码”阅读,也可以点此链接 编码常识 ,修改标题registration为“测试”,“测试”的utf-8内存编码模式16进制数据是E6 B5 8B E8 AF 95 ,转换方法如下,有兴趣的也可以自己写工具notepad++写入内容,转码010editor查看16进制内容OD改字符串乱码解决

January 23, 2019 · 1 min · jiezi

PyQt5 简介

本教程的目的是带领你入门PyQt5。教程内所有代码都在Linux上测试通过。PyQt4 教程是PyQt4的教程,PyQt4是一个Python(同时支持2和3)版的Qt库。关于 PyQt5PyQt5 是Digia的一套Qt5应用框架与python的结合,同时支持2.x和3.x。本教程使用的是3.x。Qt库由Riverbank Computing开发,是最强大的GUI库之一 ,官方网站:www.riverbankcomputing.co.uk/news。PyQt5是由一系列Python模块组成。超过620个类,6000函数和方法。能在诸如Unix、Windows和Mac OS等主流操作系统上运行。PyQt5有两种证书,GPL和商业证书。PyQt5类分为很多模块,主要模块有:QtCore 包含了核心的非GUI的功能。主要和时间、文件与文件夹、各种数据、流、URLs、mime类文件、进程与线程一起使用。QtGui 包含了窗口系统、事件处理、2D图像、基本绘画、字体和文字类。QtWidgetsQtMultimediaQtBluetoothQtNetworkQtPositioningEnginioQtWebSocketsQtWebKitQtWebKitWidgetsQtXmlQtSvgQtSqlQtTestQtWidgets类包含了一系列创建桌面应用的UI元素。QtMultimedia包含了处理多媒体的内容和调用摄像头API的类。QtBluetooth模块包含了查找和连接蓝牙的类。QtNetwork包含了网络编程的类,这些工具能让TCP/IP和UDP开发变得更加方便和可靠。QtPositioning包含了定位的类,可以使用卫星、WiFi甚至文本。Engine包含了通过客户端进入和管理Qt Cloud的类。QtWebSockets包含了WebSocket协议的类。QtWebKit包含了一个基WebKit2的web浏览器。QtWebKitWidgets包含了基于QtWidgets的WebKit1的类。QtXml包含了处理xml的类,提供了SAX和DOM API的工具。QtSvg提供了显示SVG内容的类,Scalable Vector Graphics (SVG)是一种是一种基于可扩展标记语言(XML),用于描述二维矢量图形的图形格式(这句话来自于维基百科)。QtSql提供了处理数据库的工具。QtTest提供了测试PyQt5应用的工具。PyQt4和PyQt5的区别PyQt5不兼容PyQt4。PyQt5有一些巨大的改进。但是,迁移并不是很难,两者的区别如下:重新组合模块,一些模块已经被废弃(QtScript),有些被分为两个子模块(QtGui, QtWebKit)。添加了新的模块,比如QtBluetooth, QtPositioning,和Enginio。废弃了SINGAL()和SLOT()的调用方式,使用了新的信号和xx处理方式。不再支持被标记为废弃的或不建议使用的API。

January 10, 2019 · 1 min · jiezi