当前位置: 首页 > news >正文

沧州网站制作报价网站平台建设实训总结

沧州网站制作报价,网站平台建设实训总结,廉江新闻最新消息,优质采官方网站安徽外径建设集团赶上了实习的末班车,现在在做QML开发,第一天的学习成果,一个计时器.逻辑挺简单的,纯QML实现,代码在仓库,可以对比文档和提交记录学习起来更清晰 QT-Timer 学习使用c的listmodel 学习使用了如何用c的listmodel来存储数据. 新建一个TImeListModel类继承自QAbstractListModel c…赶上了实习的末班车,现在在做QML开发,第一天的学习成果,一个计时器.逻辑挺简单的,纯QML实现,代码在仓库,可以对比文档和提交记录学习起来更清晰 QT-Timer 学习使用c的listmodel 学习使用了如何用c的listmodel来存储数据. 新建一个TImeListModel类继承自QAbstractListModel class TimeListModel : public QAbstractListModel {Q_OBJECT public:explicit TimeListModel(QObject *parent nullptr);创建一个结构体存储数据对,在用一个列表存储所有的数据,这个datalist就是listview private:// 定义一个结构体来存储列表项的数据包括 idnumber 和 timeStrstruct Data{QString m_idnumber; // 存储编号QString m_timeStr; // 存储时间字符串};// 使用 QList 来存储所有 Data 结构体的数据QListData m_datalist;然后重写三个函数,这三个函数是必须重写的,直接复制就行,都不用改.在定义一个枚举以便 QML 通过这些角色从模型中获取数据。具体来说NumberRole 和 TimerRole 代表不同的数据属性能够让 ListView 或其他基于模型的视图组件根据这些角色来访问对应的字段。 // 返回模型中数据的总数用于 ListView 获取到数据的数量// 这个函数是 QAbstractListModel 的纯虚函数必须实现int rowCount(const QModelIndex parent QModelIndex()) const override;// 返回模型的角色名称用于在 QML 中根据角色访问数据// 例如NumberRole 对应的别名可以被 ListView 使用virtual QHashint, QByteArray roleNames() const override;// 获取指定行和角色的数据这个函数会在 ListView 渲染数据时被调用// 数据是从 QList 中的 Data 结构体获取的QVariant data(const QModelIndex index, int role Qt::DisplayRole) const override;// 枚举角色用于指定 QML 中访问数据的键值// NumberRole 和 TimerRole 允许 QML 中根据不同的键来访问数据enum DataRoles{NumberRole Qt::UserRole 1, // 用户自定义的角色从 Qt::UserRole 开始TimerRole, // 时间角色};重写这三个函数的实现,根据你的数据直接抄就行,数据的个数与结构体和枚举对应 rowCount获取列表里元素的个数 roleNames设置角色与对应的名称,这样可以在qml使用model.m_idnumber来访问列表元素的idnumber data用于获取索引和角色的数据 // 返回列表项的数量用于 ListView 知道有多少项要显示 int TimeListModel::rowCount(const QModelIndex parent) const {// 返回数据列表的大小return m_datalist.size(); }// 定义数据角色的名称映射用于在 QML 中使用这些角色名称来访问数据 QHashint, QByteArray TimeListModel::roleNames() const {// 设置角色与对应的名称这样可以在 QML 中通过 m_idnumber 和 m_timeStr 获取对应的数据QHashint,QByteArray roles;roles[NumberRole] m_idnumber; // 角色 NumberRole 对应 m_idnumberroles[TimerRole] m_timeStr; // 角色 TimerRole 对应 m_timeStrreturn roles; }// 获取指定索引行和角色的数据用于 ListView 显示数据 QVariant TimeListModel::data(const QModelIndex index, int role) const {int row index.row(); // 获取当前索引的行号// 检查索引是否有效避免访问越界if(row 0 || row m_datalist.count()) {return QVariant(); // 返回无效数据}// 获取当前行对应的数据const Data data m_datalist[row];// 根据传入的角色返回不同的数据switch(role) {case NumberRole:return data.m_idnumber; // 返回编号数据case TimerRole:return data.m_timeStr; // 返回时间字符串数据default:return QVariant(); // 返回空值} }除了三个必须重写的函数,一般我们会添加一个增加数据 append和删除数据的函数,我这边直接清空就行使用 clear.将这两个函数暴露给QML,使用 Q_INVOKABLE添加上这个后,这两个函数可以在qml中调用 // Q_INVOKABLE 使得这些方法可以从 QML 中被调用// append 函数用于向模型中添加数据接收 idnumber 和 timeStr 两个字符串Q_INVOKABLE void append(const QString idnumber , const QString timeStr);// 清空模型中的所有数据Q_INVOKABLE void clear(); 实现这两个函数,添加数据时需要发送信号,添加时发送,添加完成发送,这样listView会在界面上实时刷新,如果想插入到末尾,发送信号位置是开始位置m_datalist.lastIndexOf(),结束位置也是 // 向数据列表中添加一项新数据 void TimeListModel::append(const QString idnumber, const QString timeStr) {// 通知视图模型即将插入一行新数据索引 0 表示新数据会插入到列表的最前面emit beginInsertRows(QModelIndex(), 0, 0);// 使用 prepend 将新的 Data 结构体添加到列表的开头m_datalist.prepend({idnumber, timeStr});// 通知视图模型插入操作完成ListView 会根据此信号刷新显示emit endInsertRows(); }// 清除所有数据 void TimeListModel::clear() {int row m_datalist.count(); // 获取当前数据的行数// 只有当数据列表不为空时才执行清除操作if(row 0) {// 通知视图模型即将移除所有行范围从 0 到最后一行emit beginRemoveRows(QModelIndex(), 0, m_datalist.size() - 1);// 清空数据列表m_datalist.clear();// 通知视图模型移除操作完成emit endRemoveRows();} else {return; // 如果没有数据直接返回} }随后在main.cpp中注册这个listmodel,引入头文件,实例化model,这样在qml中可以使用m_TimeListModel这个对象.第二种方法需要在qml中实例化对象 //把写好的list模型注册到qml中TimeListModel listmodel;engine.rootContext()-setContextProperty(m_TimeListModel,listmodel);//第二种方法qmlRegisterTypeTimeListModel(com.timeListModel,1,0,TimeListModel);//在qml中import导入import com.timeListModel 1.0TimeListModel{id:m_TimeListModel}现在可以把qml中ListView中原来的model替换为m_TimeListModel,在原来的逻辑中使用append和clear ListView{id:list1anchors.fill:parentanchors.margins: 20 //让元素离listview有边界clip: truemodel:m_TimeListModeldelegate: recordlistspacing: 5}m_TimeListModel.append(index.toString(),totaltime); TimeListModel.clear()多线程优化 在使用的过程中发现自己的计时器时间会慢,并且一直点击记录的话时间1s可以走10s,排查发现是在计时器的间隔取得太小了,取了1太过于消耗资源,改成10的话能解决这个问题.同时也想尝试使用线程来解决. 新建TimerThread 类继承自QObject,只有这样才能使用线程.我们需要发送时间和运行的状态,因此使用信号和QML文件通信 #ifndef TIMERTHREAD_H #define TIMERTHREAD_H#include QObject #include QTimer #include QThread #include cmath/******************************************************************************** file timerthread.h* brief 把计时放入线程** author 纯真丁一郎* date 2024/09/18* Blog https://www.relxdingyilang.cn/* history*****************************************************************************/class TimerThread : public QObject {Q_OBJECT public:explicit TimerThread(QObject *parent nullptr);//判断运行状态bool isRunning false;QString caculateTime(int totaltime);signals:void timeUpdated(QString totaltimestr); //发送时间给主界面void sig_isRunning(bool isRunning);//发送状态public slots:void start();void stop();void pause();void onTimeout();private:int m_totaltime; //总时间QTimer *timer; };#endif // TIMERTHREAD_H cpp里实现计时的功能启动计时器,计算时间格式.使用定时器的timeout信号,让我们的时间增加 #include timerthread.hTimerThread::TimerThread(QObject *parent): QObject{parent} {m_totaltime 0;timer new QTimer(this);connect(timer,QTimer::timeout,this,TimerThread::onTimeout);}void TimerThread::start(){timer-start(1);isRunning true;emit sig_isRunning(isRunning); }void TimerThread::pause(){timer-stop();isRunning false;emit sig_isRunning(isRunning); }void TimerThread::stop(){timer-stop();isRunning false;m_totaltime 0;emit sig_isRunning(isRunning); }void TimerThread::onTimeout(){//计时m_totaltime 1;emit timeUpdated(caculateTime(m_totaltime)); }QString TimerThread::caculateTime(int totaltime){//格式化字符串int millisecond totaltime % 1000;millisecond std::floor(millisecond/10);int second int(std::floor(totaltime /1000) )% 60;int minute int(std::floor(totaltime/1000 /60)) % 60;QString result (minute10 ? 0:) QString::number(minute):(second10 ? 0:) QString::number(second) :(millisecond10 ? 0:)QString::number(millisecond);return result; } 在main.cpp里实现多线程,实例化timerThread类,在实例化一个工作线程,把我们自己的类放入工作线程,启动工作线程即可. 同时我们需要qmlRegisterType来注册我们的类,这样才能让QML文件知道要与这个文件通信 //注册计时线程,并将计时线程移动到工作线程TimerThread timerThread;QThread workerThread;timerThread.moveToThread(workerThread);//启动工作线程workerThread.start();QQmlApplicationEngine engine;qmlRegisterTypeTimerThread(com.timerthread,1,0,TimerThread); main.qml的修改,首先使用import倒入我们的timerThread类,这样我们就可以在qml中实例化,可以加上idimport com.timerthread 1.0 定义两个变量,接受我们信号发送的参数.发送的参数的作用域只在Connection里,所以需要外部变量来接收,方便我们的使用.on信号名,接的第一个字母大写!!! property bool isrunning: falseproperty string totaltime: TimerThread{id:timerThread}Connections{target:timerThread// 使用传递过来的 totaltime 参数,信号传递出来的参数在connect内部可以直接使用,在外部不行onTimeUpdated:{timerDisplay.text totaltimestrtotaltime totaltimestr//console.log(totaltime)}onSig_isRunning:{isrunning isRunningconsole.log(isRunning)}}后边就将原来的一些变量替换为新接收的变量就行. 使用多线程的方式,定时器间隔取1也能精确计时,线程起到了作用 实际上 创建的timerThread并没有被使用,在qml中又实例化了另一个TimerThread对象,这两是不同的实例,放入线程的并没有被使用 尝试解决线程的bug 一开始是在main.cpp里moveTothread然后注册这个对象到上下文再在qml直接访问对象内部。但是这样会报错,这个C类和Qml引擎不再同一个线程里 QQmlEngine: Illegal attempt to connect to TimerThread(0x88fd60) that is in a different thread than the QML engine QQmlApplicationEngine(0x88fd30. //注册计时线程,并将计时线程移动到工作线程TimerThread timerThread;QThread workerThread;timerThread.moveToThread(workerThread);//启动工作线程workerThread.start();QQmlApplicationEngine engine;engine.rootContext()-setContextProperty(TimerThread,timerThread);使用重写run的方法 失败,线程号是一样的 使用中间类的方法,moveToThread 参考这篇文章https://www.cnblogs.com/judes/p/11249300.html 参考这篇文章https://www.cnblogs.com/judes/p/11249300.html 线程分离 TimerThread_test2 类负责实际的定时器逻辑并运行在一个单独的线程中。TimerInterface 类作为 TimerThread_test2 和 QML 之间的桥梁管理线程的生命周期并处理信号和槽的连接。 信号和槽机制 TimerThread_test2 通过信号 timeUpdated 和 sig_isRunning 将定时器的状态和时间信息发送给 TimerInterface。TimerInterface 通过信号 sig_timeUpdated 和 sig_isRunning 将这些信息进一步传递给 QML。 QML 集成 通过将 TimerInterface 注册为 QML 类型可以在 QML 中直接调用 TimerInterface 的方法和接收信号。 我是新建了一个新类TimerThread_test2,把TimerThread里的东西都复制进来.这个方法的原理就是使用一个中间类TimerInterface,TimerInterface给qml调用是运行在主线程中,它发出信号再去调用子线程中的TimerThread_test2. TimerThread_test2文件里新建一个类TimerInterface(继承自QObject),它的成员变量为下 private:QThread m_Thread;QString m_timeStr;TimerThread_test2 m_TimerThread_test2;在TimerInterface的构造函数里,将 m_TimerThread_test2移动到子线程里,将本来qml调用m_TimerThread_test2的信号全通过TimerInterface调用,将m_TimerThread_test2要发送给qml文件的数据全通过TimerInterface发送,这样就完成了这个类的编写.(详细代码在后边,逻辑其实很简单) TimerInterface::TimerInterface(QObject *parent) : QObject(parent) {m_TimerThread_test2.moveToThread(m_Thread);.....中间逻辑先省略m_Thread.start(); }随后我们在main.cpp中引入头文件注册 qmlRegisterTypeTimerInterface(tool,1,0,TimerThread_test);在qml文件中import import tool 1.0然后我们就可以使用这个类,修改逻辑.start,stop,pause. TimerThread_test{id:m_TimerThread;}Connections{target:m_TimerThread// 使用传递过来的 totaltime 参数,信号传递出来的参数在connect内部可以直接使用,在外部不行// function onTimeUpdated(totaltimestr){// timerDisplay.text totaltimestr// totaltime totaltimestr// //console.log(totaltime)// }function onSig_isRunning(isRunning){isrunning isRunning// console.log(isRunning)}}当我们点击开始后,可以发现中间类Interface是在主线程的,定时器是在子线程运行,多线程的方案实现成功. 完整代码,.h文件 #ifndef TIMERTHREAD_TEST2_H #define TIMERTHREAD_TEST2_H#include QObject #include QTimer #include QThread #include cmath #include QDebugclass TimerThread_test2 : public QObject {Q_OBJECT public:// explicit TimerThread_test2(QString timeStr);explicit TimerThread_test2(QObject *parent nullptr);//判断运行状态bool isRunning false;QString caculateTime(int totaltime);void getid();signals:void timeUpdated(QString totaltimestr); //发送时间给主界面void sig_isRunning(bool isRunning);//发送状态public slots:void start();void stop();void pause();void onTimeout();private:int m_totaltime; //总时间QTimer *timer;QString m_timeStr; };class TimerInterface: public QObject{Q_OBJECT// Q_PROPERTY(QString timeStr READ getData NOTIFY dataChanged) public:explicit TimerInterface(QObject *parent nullptr);~TimerInterface();Q_INVOKABLE void start();Q_INVOKABLE void pause();Q_INVOKABLE void stop();void get_is_Running(bool is_running);void get_Updated(QString timeStr); signals:void sig_start();void sig_stop();void sig_pause();void sig_isRunning(bool is_running);void sig_timeUpdated(QString timeStr); private:QThread m_Thread;QString m_timeStr;TimerThread_test2 m_TimerThread_test2; };#endif // TIMERTHREAD_TEST2_H.cpp文件 #include timerthread_test2.h// TimerThread_test2::TimerThread_test2(QString timeStr): m_timeStr(timeStr) TimerThread_test2::TimerThread_test2(QObject *parent) : QObject(parent) {m_totaltime 0;timer new QTimer(this);connect(timer,QTimer::timeout,this,TimerThread_test2::onTimeout); }void TimerThread_test2::start(){timer-start(1);isRunning true;emit sig_isRunning(isRunning);//qDebug() TimerThread_test2: start;getid(); }void TimerThread_test2::pause(){timer-stop();isRunning false;emit sig_isRunning(isRunning); }void TimerThread_test2::stop(){timer-stop();isRunning false;m_totaltime 0;emit sig_isRunning(isRunning); }void TimerThread_test2::onTimeout(){//计时m_totaltime 1;//格式化字符串int millisecond m_totaltime % 1000;millisecond std::floor(millisecond/10);int second int(std::floor(m_totaltime /1000) )% 60;int minute int(std::floor(m_totaltime/1000 /60)) % 60;QString result (minute10 ? 0:) QString::number(minute):(second10 ? 0:) QString::number(second) :(millisecond10 ? 0:)QString::number(millisecond);emit timeUpdated(result); } void TimerThread_test2::getid(){qDebug() 定时器线程ID: QThread::currentThreadId(); }// TimerInterface::TimerInterface() : m_TimerThread_test2(m_timeStr) TimerInterface::TimerInterface(QObject *parent) : QObject(parent) {m_TimerThread_test2.moveToThread(m_Thread);connect(this,TimerInterface::sig_start,m_TimerThread_test2,TimerThread_test2::start);connect(this,TimerInterface::sig_pause,m_TimerThread_test2,TimerThread_test2::pause);connect(this,TimerInterface::sig_stop,m_TimerThread_test2,TimerThread_test2::stop);connect(m_TimerThread_test2,TimerThread_test2::timeUpdated,this, TimerInterface::get_Updated);connect(m_TimerThread_test2,TimerThread_test2::sig_isRunning,this,TimerInterface::get_is_Running);m_Thread.start(); }TimerInterface::~TimerInterface() {m_Thread.quit();m_Thread.wait(); }void TimerInterface::start() {emit sig_start();qDebug() TimerInterface start in : QThread::currentThreadId(); }void TimerInterface::pause() {emit sig_pause(); }void TimerInterface::stop() {emit sig_stop(); }void TimerInterface::get_is_Running(bool is_running) {sig_isRunning(is_running); }void TimerInterface::get_Updated(QString timeStr) {emit sig_timeUpdated(timeStr); }
http://www.w-s-a.com/news/153252/

相关文章:

  • 建设银行网站模板为什么企业要建设自己的企业文化
  • 网站建设必知免费手机网站建站系统
  • ssh可以做wap网站么嘉兴seo排名
  • 站内优化包括哪些帝国做企业网站
  • 做网站seo赚钱吗网络维护和故障维修
  • 企业网站可以自己做摄影网站开发背景怎么写
  • 网站百度指数seo最好的工具
  • 宝安专业网站建设推荐设计感强的网站
  • 网站建设 6万元北京知名的品牌设计公司
  • 网站建设的总体需求是什么vmware 下wordpress
  • 光谷网站建设请检查网络
  • 申请建设网站的报告书商务网站开发课程体会
  • 网站开发实训总结致谢群晖wordpress设置
  • 关于酒店网站建设的摘要天津市建设工程信息网官网首页
  • 网站alexa排名查询手机网站制作器
  • 建设小辣猫的网站电子毕业设计网站建设
  • 询广西南宁网站运营礼品定制
  • 建筑公司网站作用免费查看招标信息的网站
  • 建筑设计公司名字起名大全html网站 怎么做seo
  • 网站群建设模板迁移原站迁移pc巩义网站建设案例课堂
  • 烟台高端网站开发wordpress 设置权限
  • 中小企业网站制作流程网站开发和设计人员的岗位要求
  • 公司网站建设多少费用河北城乡建设官网站
  • 国科联创网站建设广告传媒公司招聘信息
  • 网站后台文章删了 怎么前台还有一级做爰片软件网站
  • 辽宁省建设注册中心网站wordpress 博客插件
  • 做电商看的网站有哪些网站建设需求策划书
  • 关于网站建设交易流程的描述一句话哪些网站用户体验好
  • 男女做暖暖的网站大全深圳平台网站建设外包
  • 凯里展示型网站设计抖音代运营收费详细价格