Qt5模型/视图结构-视图(View)
生活随笔
收集整理的這篇文章主要介紹了
Qt5模型/视图结构-视图(View)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
實現自定義的View,可繼承自QAbstractItemView類,對所需的純虛函數進行重定義與實現,對于QAbstractItemView類中的純虛函數,在子類中必須進行重定義,但不一定要實現,可根據需要選擇實現。
DEMO
mainwindow.h
#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow> #include <QStandardItem> #include <QTableView> #include <QMenuBar> #include <QMenu> #include <QAction> #include <QSplitter> #include "histogramview.h"class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = 0);~MainWindow();void creatAction();void creatMenu();void setupModel();void setupView();void openFile(QString); public slots:void slotOpen(); private:QMenu *fileMenu;QAction *openAct;QStandardItemModel *model;QTableView *table;QSplitter *splitter;HistogramView *histogram; };#endif // MAINWINDOW_Hhistogramview.h
#ifndef HISTOGRAMVIEW_H #define HISTOGRAMVIEW_H#include <QAbstractItemView> #include <QItemSelectionModel> #include <QRegion> #include <QMouseEvent> #include <QList>//自定義HistogramView類繼承自QAbstractItemView類,用于對表格數據進行柱狀圖顯示 class HistogramView:public QAbstractItemView {Q_OBJECT public:HistogramView(QWidget *parent=0);//虛函數的聲明//QAbstractItemView類中的純虛函數,這些純虛函數不一定要實現,可以根據//需要選擇性的實現,但一定要聲明QRect visualRect(const QModelIndex &index) const;void scrollTo(const QModelIndex &index,ScrollHint hint=EnsureVisible);//當鼠標在視圖中單擊或位置發生改變時觸發,它返回鼠標所在點的QModelIndex值,若鼠標//處在某個數據項的區域中,則返回此數據的Index值,否則返回一個空的IndexQModelIndex indexAt(const QPoint &point) const;//為selections賦初值void setSelectionModel(QItemSelectionModel *selectionModel);QRegion itemRegion(QModelIndex index);void paintEvent(QPaintEvent *);//柱狀統計圖可以被鼠標單擊選擇,選中后以不同的方式顯現void mousePressEvent(QMouseEvent *event); protected slots://當數據項發生改變時,此槽函數將響應void selectionChanged(const QItemSelection &selected,const QItemSelection &deselected);//當模型中的數據發生變更時,此槽函數響應void dataChanged(const QModelIndex &topLeft,const QModelIndex &bottomRight); protected://虛函數聲明QModelIndex moveCursor(QAbstractItemView::CursorAction cursorAction,Qt::KeyboardModifiers modifiers);int horizontalOffset() const;int verticalOffset() const;bool isIndexHidden(const QModelIndex &index) const;//將位于QRect內的數據項按照SelectionFlags(描述被選擇的數據項以何種方式進行更新)//指定的方式進行更新。void setSelection(const QRect &rect,QItemSelectionModel::SelectionFlags flags);QRegion visualRegionForSelection(const QItemSelection &selection) const; private:QItemSelectionModel *selections; //用于保存與視圖選擇項相關的內容QList<QRegion> MRegionList; //用于保存其中某一類型柱狀圖的區域范圍,而每個區域是QList中的一個值QList<QRegion> FRegionList;QList<QRegion> SRegionList; };#endif // HISTOGRAMVIEW_Hmainwindow.cpp
#include "mainwindow.h" #include <QFileDialog> #include <QFile> #include <QTextStream> #include <QStringList>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {creatAction();creatMenu();setupModel();setupView();setWindowTitle(tr("View Example"));resize(600,600); }MainWindow::~MainWindow() {}void MainWindow::creatAction() {openAct=new QAction(tr("打開"),this);connect(openAct,SIGNAL(triggered(bool)),this,SLOT(slotOpen())); }void MainWindow::creatMenu() {fileMenu=new QMenu(tr("文件"),this);fileMenu->addAction(openAct);menuBar()->addMenu(fileMenu); } //新建一個model,并設置表頭數據 void MainWindow::setupModel() {model=new QStandardItemModel(4,4,this);model->setHeaderData(0,Qt::Horizontal,tr("部門"));model->setHeaderData(1,Qt::Horizontal,tr("男"));model->setHeaderData(2,Qt::Horizontal,tr("女"));model->setHeaderData(3,Qt::Horizontal,tr("退休")); } void MainWindow::setupView() {/*table=new QTableView; //新建一個QTableViewtable->setModel(model); //為QTableView對象設置相同的ModelQItemSelectionModel *selectionModel=new QItemSelectionModel(model);table->setSelectionModel(selectionModel);//連接選擇模型的selectionModel()信號與QTabelView對象的selectionChanged()槽函數//以便使自定義的HistogramView對象中的選擇變化能夠反映到QTabelView對象的顯示中connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection)));splitter=new QSplitter;splitter->setOrientation(Qt::Vertical);splitter->addWidget(table);setCentralWidget(splitter);*/splitter=new QSplitter;splitter->setOrientation(Qt::Vertical);histogram=new HistogramView(splitter); //新建一個Histogram對象histogram->setModel(model); //為HistogramView對象設置相同的Modeltable=new QTableView;table->setModel(model);QItemSelectionModel *selectionModel=new QItemSelectionModel (model);table->setSelectionModel(selectionModel);histogram->setSelectionModel(selectionModel); //新建的QItemSelectionModel//對象作為QTableView對象和HistogramView//對象使用的選擇模型splitter->addWidget(table);splitter->addWidget(histogram);setCentralWidget(splitter);//連接槽函數,以便使QTableView對象中的選擇變化能夠反映到自定義的HistogramView對象的顯示中connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),table,SLOT(selectionChanged(QItemSelection,QItemSelection)));connect(selectionModel,SIGNAL(selectionChanged(QItemSelection,QItemSelection)),histogram,SLOT(selectionChanged(QItemSelection,QItemSelection)));} //slotOpne()槽函數完成打開標準文件對話框 void MainWindow::slotOpen() {QString name;name=QFileDialog::getOpenFileName(this,"打開",".","histogram files(*.txt)");if(!name.isEmpty()){openFile(name);} } //openFile()函數完成打開所選的文件的內容 void MainWindow::openFile(QString path) {if(!path.isEmpty()){QFile file(path);if(file.open(QFile::ReadOnly | QFile::Text)){QTextStream stream(&file);QString line;model->removeRows(0,model->rowCount(QModelIndex()),QModelIndex());int row=0;do{line=stream.readLine();if(!line.isEmpty()){model->insertRows(row,1,QModelIndex());QStringList pieces=line.split(",",QString::SkipEmptyParts);model->setData(model->index(row,0,QModelIndex()),pieces.value(0));model->setData(model->index(row,1,QModelIndex()),pieces.value(1));model->setData(model->index(row,2,QModelIndex()),pieces.value(2));model->setData(model->index(row,3,QModelIndex()),pieces.value(3));row++;}}while(!line.isEmpty());file.close();}} //end if(!path.isEmpty()) }histogramview.cpp
#include "histogramview.h" #include <QPainter>HistogramView::HistogramView(QWidget *parent):QAbstractItemView(parent) {} //paintEvent()函數完成柱狀統計圖繪制的工作 void HistogramView::paintEvent(QPaintEvent *) {//以viewport()作為繪圖設備新建一個QPainter對象QPainter painter(viewport());painter.setPen(Qt::black);int x0=40;int y0=250;/*完成了x,y坐標軸的繪制,并標注坐標軸的變量*///y坐標軸painter.drawLine(x0,y0,40,30);painter.drawLine(38,32,40,30);painter.drawLine(40,30,42,32);painter.drawText(20,30,tr("人數"));for(int i=0;i<5;i++){painter.drawLine(-1,-i*50,1,-i*50);painter.drawText(-20,-i*50,tr("%1").arg(i*5));}//x軸painter.drawLine(x0,y0,540,250);painter.drawLine(538,248,540,250);painter.drawLine(540,250,538,252);painter.drawText(545,250,tr("部門"));int posD=x0+20;int row;for(row=0;row<model()->rowCount(rootIndex());row++){QModelIndex index=model()->index(row,0,rootIndex());QString dep=model()->data(index).toString();painter.drawText(posD,y0+20,dep);posD+=50;}/*完成了表格第1列數據的柱狀統計圖的繪制*///男int posM=x0+20;MRegionList.clear();for(row=0;row<model()->rowCount(rootIndex());row++){QModelIndex index=model()->index(row,1,rootIndex());int male=model()->data(index).toDouble();int width=10;//使用不同畫刷顏色區別選中與未被選中的數據項if(selections->isSelected(index)){//Qt::Dense3Pattern是QBrush style//如果被選中,則畫刷的style改變painter.setBrush(QBrush(QColor(91,75,0,255),Qt::Dense3Pattern));}else{painter.setBrush(Qt::blue);}//根據當前數據項的值按照比例繪制一個方形表示此項數據painter.drawRect(QRect(posM,y0-male*10,width,male*10));QRegion regionM(posM,y0-male*10,width,male*10);//將此數據所占據的區域保存到MRegionList列表中,為后面的數據項做準備MRegionList.insert(row,regionM);posM+=50;} //end for(row=0;row<model()->rowCount(rootIndex());row++)/*完成了表格第2列數據的柱狀統計圖繪制*///女int posF=x0+30;FRegionList.clear();for(row=0;row<=model()->rowCount(rootIndex());row++){QModelIndex index=model()->index(row,2,rootIndex());int female=model()->data(index).toDouble();int width=10;if(selections->isSelected(index)){painter.setBrush(QBrush(Qt::red,Qt::Dense3Pattern));}else{painter.setBrush(Qt::red);}painter.drawRect(QRect(posF,y0-female*10,width,female*10));QRegion regionF(posF,y0-female*10,width,female*10);FRegionList.insert(row,regionF);posF+=50;} //end for(row=0;row<=model()->rowCount(rootIndex());row++)/*完成了表格第3列數據的柱狀統計圖的繪制*///退休int posS=x0+40;SRegionList.clear();for(row=0;row<=model()->rowCount(rootIndex());row++){QModelIndex index=model()->index(row,3,rootIndex());int retire=model()->data(index).toDouble();int width=10;if(selections->isSelected(index)){painter.setBrush(QBrush(Qt::green,Qt::Dense3Pattern));}else{painter.setBrush(Qt::green);}painter.drawRect(QRect(posS,y0-retire*10,width,retire*10));QRegion regionS(posS,y0-retire*10,width,retire*10);SRegionList.insert(row,regionS);posS+=50;} //end for(row=0;row<=model()->rowCount(rootIndex());row++) } //dataChanged函數實現當model中的數據更改時,調用繪圖設備的update()函數 //進行更新,反映數據的變化 void HistogramView::dataChanged(const QModelIndex &topLeft,const QModelIndex &bottomRight) {QAbstractItemView::dataChanged(topLeft,bottomRight);viewport()->update(); } //setSelectionModel()函數為selections賦初值 void HistogramView::setSelectionModel(QItemSelectionModel *selectionModel) {selections=selectionModel; } //selectionChanged()函數中完成當數據項發生變化時調用update()函數 //重繪繪圖設備即可工作 void HistogramView::selectionChanged(const QItemSelection &selected,const QItemSelection &deselected) {viewport()->update(); } //鼠標按下事件函數mousePressEvent(),在調用setSelection()函數時確定鼠標單擊 //點是否在某個數據項的區域內,并設置選擇項 void HistogramView::mousePressEvent(QMouseEvent *event) {QAbstractItemView::mousePressEvent(event);setSelection(QRect(event->pos().x(),event->pos().y(),1,1),QItemSelectionModel::SelectCurrent); } void HistogramView::setSelection(const QRect &rect,QItemSelectionModel::SelectionFlags flags) {int rows=model()->rowCount(rootIndex()); //獲取總行數int columns=model()->columnCount(rootIndex()); //獲取總列數//用于保存被選中的數據項的Index值,此處只實現了用鼠標單擊選擇,而沒有實現//鼠標拖曳框選,因此,鼠標動作只可能選中一個數據項。若實現框選,則可使用//QModelIndexList來保存所有被選中的數據項的Index值QModelIndex selectedIndex;for(int row=0;row<rows;++row){for(int column=1;column<columns;++column){QModelIndex index=model()->index(row,column,rootIndex());QRegion region=itemRegion(index); //返回指定index的數據項所占用的區域if(!region.intersected(rect).isEmpty())selectedIndex=index;}}if(selectedIndex.isValid())selections->select(selectedIndex,flags);else{QModelIndex noIndex;selections->select(noIndex,flags);} } QModelIndex HistogramView::indexAt(const QPoint &point) const {QPoint newPoint(point.x(),point.y());QRegion region;//男 列foreach(region,MRegionList) //檢查當前點是否處于第一列(男)數據的區域中{if(region.contains(newPoint)){int row=MRegionList.indexOf(region);QModelIndex index=model()->index(row,1,rootIndex());return index;}}//女 列foreach(region,FRegionList){if(region.contains(newPoint)){int row=FRegionList.indexOf(region);QModelIndex index=model()->index(row,2,rootIndex());return index;}}//合計 列foreach(region,FRegionList){if(region.contains(newPoint)){int row=FRegionList.indexOf(region);QModelIndex index=model()->index(row,2,rootIndex());return index;}}return QModelIndex(); } QRect HistogramView::visualRect(const QModelIndex &index)const{} void HistogramView::scrollTo(const QModelIndex &index,ScrollHint){} QModelIndex HistogramView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers){} int HistogramView::horizontalOffset()const{} int HistogramView::verticalOffset()const{} bool HistogramView::isIndexHidden(const QModelIndex &index)const{} QRegion HistogramView::visualRegionForSelection(const QItemSelection & selection)const{} QRegion HistogramView::itemRegion(QModelIndex index) {QRegion region;if (index.column() == 1) //男region = MRegionList[index.row()];if (index.column() == 2) //女region = FRegionList[index.row()];if (index.column() == 3) //退休region = SRegionList[index.row()];return region; }main.cpp
#include "mainwindow.h" #include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);MainWindow w;w.show();return a.exec(); }注意.pro文件如下
#------------------------------------------------- # # Project created by QtCreator 2018-09-05T19:29:45 # #-------------------------------------------------QT += core guigreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = CH803 TEMPLATE = appDEFINES += QT_DEPRECATED_WARNINGS #新增加的SOURCES += main.cpp\mainwindow.cpp \histogramview.cppHEADERS += mainwindow.h \histogramview.h在該目錄下新建文件histogram.txt
E:\QT\CH803\build-CH803-Desktop_Qt_5_6_2_MinGW_32bit-Debug內容如下
一部,12,3,5 二部,16,4,0 三部,18,4,2 四部,10,3,1 五部,11,4,3 六部,12,2,4 七部,14,3,5 八部,9,1,1運行效果如下
備注
這個程序里有幾個函數我還是沒搞懂,不太清楚其中的邏輯
參考資料《Qt5開發及實例》
轉載于:https://www.cnblogs.com/Manual-Linux/p/9679342.html
總結
以上是生活随笔為你收集整理的Qt5模型/视图结构-视图(View)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 顺丰速运一般几天到(顺丰快递单号查询)
- 下一篇: ANdroid O MeidiaPlay