接触Qt是很早之前的事情了,之前零零碎碎地看过一些视频教程,跟着做了一些demo,但随后就落下了。前一阵儿跟着网易云课堂的一个Qt课程重新学习了一下Qt基础,想要做一个自己的项目来练手。想过做个terminal,来弥补mac终端缺失ssh登录管理的缺陷;想过做个音乐播放器;想过做个小说爬虫客户端。不过翻来翻去,一直未找到step by step的视频教程来跟着联系。恰逢这两天找合适的rss阅读器,受到启发,不如自己试着写一下rss客户端?不错的是,在github上找到一个Qt的Rss项目 QuiteRSS<https://github.com/QuiteRSS/quiterss>,感觉还不错。不过结构过于复杂,界面功能繁多,因而考虑先做简化版本,后续逐步参考代码,补全功能。
代码目录:
代码目录
界面布局:
界面布局
后续在GitHub上又找到几个简单的项目:
- Masaru82/Qt5-RSSreader00 <https://github.com/Masaru82/Qt5-RSSreader00>,
- elanius/rss <https://github.com/elanius/rss>
- antonybro/RSSReaderQt <https://github.com/antonybro/RSSReaderQt>
其中RSSReaderQt是现版本(macOS 10.13,Qt 5.12)能正常运行的,因而以此为原型进行测试开发。
RSSReaderQt
该软件功能比较简单,尽管为非中文,但功能简单,也能猜出其大致含义。左侧的按钮为添加,右侧按钮为删除。点击Link之后,右侧会出现标题,点击标题,会用系统默认浏览器打开文章。实现了最基本的RSS阅读器的功能。因而接下来将以此为蓝本,进行RSS核心功能编写。
主程序界面
添加源界面
创建MainWindow类,继承于QMainWindow类,为主窗体界面。添加feedModel类,继承于QStandardItemModel,用于填充Rss源列表。- 添加表头
void FeedModel::creatHeader(){ setHorizontalHeaderItem(0,new QStandardItem("名称")); setHorizontalHeaderItem(1,new QStandardItem("链接")); }
- 添加条目
void FeedModel::AddItem(QString name, QString link){ QList<QStandardItem*> list; QStandardItem *nameitem = new QStandardItem(name); nameitem->setData(name); QStandardItem *linkitem = new QStandardItem(link); linkitem->setData(link); list<<nameitem<<linkitem; appendRow(list); }
创建addRssSource类,继承于QDialog类,用于创建添加源窗体。- 获取窗体中填入的name和link,清空窗体内容。
QString addRssSource::name() { return ui->lename->text(); } QString addRssSource::link() { return ui->lelink->text(); } void addRssSource::clearcnt() { ui->lename->clear(); ui->lelink->clear(); ui->lename->setFocus(); }
绑定主窗体“添加”按钮,将对话框内容填充到Rss源。void MainWindow::on_btnAdd_clicked(){ if(rsswin.exec()==QDialog::Accepted){ model->AddItem(rsswin.name(),rsswin.link()); rsswin.clearcnt(); } }
解析主窗体的tabview的link,并将解析内容展示在右侧tabview.- 创建newsModel类,并添加addItem方法。
void newsModel::addItem(QString title) { QStandardItem *titleitem=new QStandardItem(title); titleitem->setData(title); appendRow(titleitem); }
- 解析添加的rss链接,并将标题传到右侧tabview的titleitem中。
- 在pro文件中添加network和xml库
- 在mainwindow.h添加QtNetwork头文件
- 绑定左侧tableview,加载rss url参数。注意manager的初始化!未初始化无法解析数据!
manager=new QNetworkAccessManager(this); void MainWindow::on_tvRes_clicked(const QModelIndex &index) { QNetworkrequest request; request.setUrl(QUrl(feedmodel->item(index.row(),1)->data().toString())); request.setRawHeader("User-Agent","MyOwnBrowser 1.0"); reply=manager->get(request); connect(reply,SIGNAL(readyRead()),this,SLOT(anarss())); connect(reply,SIGNAL(error(QNetworkReply::NetworkError)), this,SLOT(error(QNetworkReply::NetworkError))); }
- 解析数据
void MainWindow::anarss() { QByteArray cnt=reply->readAll(); QXmlStreamReader xmlstream; xmlstream.addData(cnt); QString titleStr,linkStr,currentTag; newsmodel->removeRows(0,1000); while (!xmlstream.atEnd()) { xmlstream.readNext(); if(xmlstream.isStartElement()){ if(xmlstream.name()=="item"){ titleStr.clear(); linkStr.clear(); } currentTag=xmlstream.name().toString(); }else if(xmlstream.isEndElement()){ if(xmlstream.name()=="item"){ newsmodel->addItem(titleStr,linkStr); titleStr.clear(); linkStr.clear(); } }else if(xmlstream.isCharacters()&&!xmlstream.isWhitespace()){ if(currentTag == "title"){ titleStr = xmlstream.text().toString(); }else if(currentTag == "link"){ linkStr = xmlstream.text().toString(); } } } }
- 将url与系统浏览器绑定
void MainWindow::on_tvNewsList_clicked(const QModelIndex &index) { QDesktopServices::openUrl(QUrl(newsmodel->data(index,Qt::UserRole 1).toString())); }
此时核心程序已经完成。
,