Qt学习心得
目錄
Qt特性
Qt核心特點
Qt容器
Qt快捷鍵
Qt類庫模塊
Qt控件的使用
QSpinBox、QDoubleSpinBox
QTextEdit
進度條
時間控件
QPlainTextEdit
QComBox
QListWidget
QTreeWidget
QtableWidget
Model、View結構
QFileSystemModel
QStringListModel
QStandardItemModel
QItemSelectionModel
自定義代理
Qt對話框
QFileDialog
QColorDialog
QFontDialog
字符輸入對話框
整形輸入對話框
浮點數輸入對話框
條目輸入對話框
Question消息框
information消息框
warning消息框
critical消息框
about消息框
自定義對話框及調用
多窗體應用程序設計
SPlash和登錄窗口
文本文件讀寫
QFile IODevice讀寫文件
QTextSteam讀寫文件
解決漢字亂碼問題
二進制文件讀寫
使用QDataStream讀寫stm類型文件
使用QDataStream讀寫dat類型文件
使用DataStream讀取.dat文件
文件目錄操作
QPainter基本繪制
坐標系統和坐標轉換
視口坐標和窗口坐標
QtCharts
Qtchart繪制折線圖???????
QBarChart
繪制餅狀圖(QPieChart)
繪制堆積圖(QStackedBar)
繪制散點圖(Scatterchart)
Qt特性
Qt核心特點
元對象編譯器(Meta-Object Compiler,MOC)是一個預處理器 先將Qt的特性程序轉換為標準C++程序,在由標準C++編譯器進行編譯
使用信號與槽機制,只有添加Q_OBJECT宏,moc才能對類里的信號與槽進行預處理
Qt為C++語言增加的特性在Qt Core模塊里實現,由Qt的元對象系統實現。 包括:信號與槽機制、屬性系統、動態類型轉換等。
元對象系統(Meta-Object System)
QObject類是所有使用元對象系統的類的基類 在一個類的private部分聲明Q_OBJECT宏 MOC(元對象編譯器)為每個QObject的子類提供必要的代碼
可以使用Qobject對象對Qt的控件進行控制
QObject *obj = new QMyWidget; QWidget *widget = qobject_cast<QWidget *>(obj); QMyWidget *myWidget = qobject_cast<QMyWidget *>(obj); QLabel *label = qobject_cast<QLabel *>(obj); //不會報錯,label為NULL
qobject_cast<QWidget *> 為類型轉換,加了之前就相當于調用了指向QWidget的指針,可以對QWidget進行操作
qobject_cast<QLabel *>(obj);//obj原本指向QWidget,但使用QLabel對其進行指向,QWidget不包含QWidget的內容,因此返回的東西為Null;
Q_PROPERTY宏定義一個返回類型為type,名稱為name的屬性
class TestWidget : public QWidget {Q_OBJECTQ_CLASSINFO("author", "liu") }; ? ?TestWidget * test = new TestWidget;qDebug() << test->metaObject()->classInfo(0).name();qDebug() << test->metaObject()->classInfo(0).value();QClassInfo可以記錄類的附加信息,通過metaobject進行調用獲取
Qt容器
QMap是鍵值對關系 key不能重復 QMultiMap的key可以重復
QHash 和 QMap的區別 : QMap是連續存儲的,里面的值也是按順序存儲的 QHash里面的值不一定是按順序存儲的,而是按映射存儲的
QSet是基于散列表的
C++ Map是STL的一個關聯容器,它提供一對一(其中第一個可以稱為關鍵字,每個關鍵字只能在map中出現一次,第二個可能稱為該關鍵字的值) 對于迭代器來說,可以修改實值,而不能修改key
C++vector容器的定義 vector<int>::iterator i; //定義正向迭代器
vector<int>::reverse_iterator j; //用反向迭代器遍歷容器
Qt快捷鍵
F4 頭文件和cpp進行切換 F2定義和實現之間進行切換 F1光標所在的符號顯示幫助
Qt類庫模塊
其他模塊都依賴于Qt Core模塊,使用 qmake 構建,此模塊會自動被加入項目 QT -= gui qmake 構建時,Qt GUI 模塊是自動被加入項目的。如果項目中不使用 GUI 功能: QT += multimedia multimediawidgets QT += sql
Qt控件的使用
QSpinBox、QDoubleSpinBox
QSpinBox常用于現在整數prefix為前綴,sufix為后綴
QDoubleSpinBox常用于顯示double,可以設置顯示的小數點位數,前后綴方式與QSpinbox相同
QTextEdit
QTextEdit的palatte可以用來顯示顏色,可做控制面板使用
QColor ?color; int R=ui->SliderRed->value(); ?//讀取SliderRed的當前值 int G=ui->SliderGreen->value();//讀取 SliderGreen 的當前值 int B=ui->SliderBlue->value();//讀取 SliderBlue 的當前值 int alpha=ui->SliderAlpha->value();//讀取 SliderAlpha 的當前值 color.setRgb(R,G,B,alpha); //使用QColor的setRgb()函數 獲得顏色 ? QPalette pal=ui->textEdit->palette();//獲取textEdit原有的 palette pal.setColor(QPalette::Base,color); //設置palette的基色(即背景色) ? ui->textEdit->setPalette(pal);//設置為textEdit的palette,改變textEdit的底色進度條
QSlider為滑動條,值改變的槽函數為valuechanged(int)
QScollBar也為滑動條,類似網頁下面的滑動條,值改變的槽函數為valuechanged(int)
QProgressBa為進度條,可以顯示百分比及進度,類似軟件界面啟動加載界面,值改變的槽函數為valuechanged(int),但不可滑動類型QSlider和QScollBar改變他的值
QDial類似一個鐘表,滑動可以改變他的值,值改變的槽函數為valuechanged(int)
QLCDNumber
QLCDNumber常用于顯示數字和時間等,可以進行二進制、八進制、十進制、十六進制轉換顯示,也可以設置顯示的位數,通過display設置顯示的內容
ui->LCDDisaplay為ui界面的QLCDNumber控件
ui->LCDDisplay->display(value); //設置LCD顯示二進制數 ui->LCDDisplay->setDigitCount(8); ui->LCDDisplay->setBinMode(); //設置LCD顯示八進制數 ui->LCDDisplay->setDigitCount(4); ui->LCDDisplay->setOctMode(); //設置LCD顯示十六進制數 ui->LCDDisplay->setDigitCount(3); ui->LCDDisplay->setHexMode(); //設置LCD顯示十進制數 ui->LCDDisplay->setDigitCount(3); ui->LCDDisplay->setDecMode();時間控件
QTimeEdit用于顯示當前時間的時分秒
QDateTime curDateTime=QDateTime::currentDateTime(); //讀取當前日期時間 ? //editTime為QlineEdit控件,使用字符轉換顯示時間 ui->timeEdit->setTime(curDateTime.time()); //設置時間 ui->editTime->setText(curDateTime.toString("hh:mm:ss"));//轉換為字符串顯示QDateEdit用于顯示年月日
//editDate為QlineEdit控件,使用字符轉換顯示時間 ui->dateEdit->setDate(curDateTime.date());//設置日期 ui->editDate->setText(curDateTime.toString("yyyy-MM-dd"));//轉換為字符串顯示QDateTimeedit用于顯示完整的時間年月日時分秒
//editDateTime為QlineEdit控件,使用字符轉換顯示時間 ui->dateTimeEdit->setDateTime(curDateTime);//設置日期時間 ui->editDateTime->setText(curDateTime.toString("yyyy-MM-dd hh:mm:ss"));//轉換為字符串顯示QCalendarWidget為日歷控件,用于顯示日歷,槽函數為selectionChanged()函數,使用QDate可以獲取日歷上選擇的時間
void Dialog::on_calendarWidget_selectionChanged() { //在日歷上選擇日期QDate dt=ui->calendarWidget->selectedDate(); //讀取選擇的日期時間QString str=dt.toString("yyyy年M月d日");//轉換為字符串ui->editCalendar->setText(str); //字符串顯示日期 }QPlainTextEdit
可以通過設置Qt界面的Property中的lineWrapMode屬性來設置是否自動換行,NoWrap為不自動換行
appendPlainText()為在QPlainTextEdit后面添加內容
QPlainTextEdit的文字內容以QTextDocument類型儲存,函數document返回這個文檔對象的指針。 QTextDocument是內存中的文本對象,以文本塊的方式儲存,每個段落以換行符結束 QTextDocument提供一些函數實現對文本內容的存取 int blockCount(),返回文本塊個數 QTextBlock finBlockByNumber(int ),讀取一個文本塊,序號從0開始
QTextDocument * doc = ui->plainTextEdit->document(); int count = doc->blockCount();QIcon ico(":/imasges/icons/aim.ico");for (int i = 0; i < count ; i++){ui->comboBox->addItem(ico, doc->findBlockByNumber(i).text());}QComBox
?QIcon ico(":/imasges/icons/UNIT.ICO");QMap<QString, int> City_Zone;City_Zone.insert("北京",10);City_Zone.insert("上海",21);City_Zone.insert("天津",22);City_Zone.insert("大連",411);City_Zone.insert("錦州",416);City_Zone.insert("徐州",516);City_Zone.insert("福州",591);City_Zone.insert("青島",532); ?foreach(auto str, City_Zone.keys()){ui->comboBox2->addItem(ico, str, City_Zone.value(str));}通過foreach設置Qcombox的icon和值,addItem的第一個參數為icon,第二個參數為顯示的內容,第三個參數為value 槽事件 currentIndexChanged(const QSting & arg1);if(!arg1.isEmpty()){//獲取的是QComBox的第三個設置的值QString zone = ui->comboBox2->currentData().toString();ui->plainTextEdit->appendPlainText(arg1 + "區號" + zone);}槽事件中返回的參數為additem的第二個參數,currentData()為addItem中設置的第三個參數QListWidget
通過QListWidgetItem來獲取QListWidget上的表項
QListWidgetItem * aItem = ui->listWidget->item(i); //通過setFlags來設置QListWidget上的表項的可用、可編輯、可選擇等 aItem->setFlags(Qt::ItemIsSelectable|Qt::ItemIsEditable| Qt::ItemIsUserCheckable|Qt::ItemIsEnabled);QListWidgetItem可在前面添加Icon
QListWidgetItem * aItem; QIcon icon(":/images/icons/check2.ico"); QString str = QString::asprintf("New Insert append"); aItem = new QListWidgetItem(str); aItem->setIcon(icon); aItem->setCheckState(Qt::Checked); ui->listWidget->addItem(aItem);QActon可添加QMenu
QMenu * menu = new QMenu(this); menu->addAction(ui->actSelALL); menu->addAction(ui->actSelNone); menu->addAction(ui->actSelInvs); ui->actSelPopMenu->setMenu(menu);QDockWidegt
QDockWidegt設置可見性和浮動性
void MainWindow::on_actDockVisible_triggered(bool arg1) {ui->dockWidget->setVisible(arg1); } ? void MainWindow::on_actDockFloat_triggered(bool checked) {ui->dockWidget->setFloating(checked); }QDockWidegt自身具體槽事件,來監聽QDockWidegtd的可見性狀態和浮動性狀態topLevelChanged(bool topLevel)和visibilityChanged(bool visible)
void MainWindow::on_dockWidget_topLevelChanged(bool topLevel) {ui->actDockFloat->setChecked(topLevel); } ? void MainWindow::on_dockWidget_visibilityChanged(bool visible) {ui->actDockVisible->setChecked(visible); }QTreeWidget
QTreeWidget通過QTreeWidgetItem來獲取QTreeWidget的某項數據,QTreeWidgetItem的數據分為兩部分
可以通過枚舉類型對QTreeWidget節點類型進行區分
//枚舉類型treeItemType, 用于創建 QTreeWidgetItem 時作為節點的type, 自定義類型必須大于1000 //itTopItem 頂層節點; itGroupItem 組節點; itImageItem 圖片 enum ?treeItemType{itTopItem=1001,itGroupItem,itImageItem}; //枚舉類型,表示列號 enum ?treeColNum{colItem=0, colItemType=1}; //目錄樹列的編號定義 QTreeWidgetItem * parItem = ui->treeWidget->currentItem(); QTreeWidgetItem * item = new QTreeWidgetItem(itGroupItem); QIcon icon(":/images/icons/open3.bmp"); item->setIcon(colItem, icon); item->setText(colItem, dir); item->setText(colItemType, "type:group"); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsAutoTristate); //設置節點選項 item->setCheckState(colItem,Qt::Checked); //節點選中 ? //通過setData向QTreeWidgetItem里面設置數據 item->setData(colItem,Qt::UserRole,QVariant(fullname)); //設置角色為Qt::UserRole的Data,存儲完整目錄名稱 ? parItem->addChild(item); //在父節點下面添加子節點 //QTreeWidget的表項改變事件 void MainWindow::on_treeWidget_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) {Q_UNUSED(previous);if(current==NULL) return;//獲取之前設置的枚舉類型int var = current->type();switch (var){case itTopItem:ui->actAddFiles->setEnabled(true);ui->actAddFolder->setEnabled(true);ui->actDeleteItem->setEnabled(true);break;case itGroupItem:ui->actAddFiles->setEnabled(true);ui->actAddFolder->setEnabled(true);ui->actDeleteItem->setEnabled(true);break;case itImageItem:ui->actAddFiles->setEnabled(true);ui->actAddFolder->setEnabled(false);ui->actDeleteItem->setEnabled(true);ui->actZoomIn->setEnabled(true);ui->actZoomFitH->setEnabled(true);ui->actZoomFitW->setEnabled(true);ui->actZoomOut->setEnabled(true);ui->actZoomRealSize->setEnabled(true);LabFileName.setText(current->data(colItem,Qt::UserRole).toString());//獲取QTreeWidgetItem之前設置的數據curPixmap.load(current->data(colItem,Qt::UserRole).toString());on_actZoomFitW_triggered();} }QtableWidget
通過ui界面設置tabsCloseable設置QtableWidget是否具有關閉按鈕。
//將ui的center設置為Qtablewidget setCentralWidget(ui->tabWidget); ? //設置是否可見 ui->tabWidget->setVisible(false); ? //設置全屏顯示 //setWindowState(Qt::WindowMaximized);Model、View結構
?數據:如數據庫的一個數據表或SQL查詢結果,內存中的一個 StringList,或磁盤文件結構等。
?Model:與數據通信,并為視圖組件提供數據接口。
?View:是屏幕上的界面組件,視圖從數據模型獲得每個數據項的模型索引(model index),通過模型索引獲取數據
?代理:定制數據的界面顯示和編輯方式。在標準的視圖組件中,代理功能顯示一個數據,當數據被編輯時,提供一個編輯器,一般是QLineEdit 。
模型、視圖和代理之間使用信號和槽通信
數據類型
| QStringListModel | 用于處理字符串列表數據的數據模型類 |
| QStandardltemModel | 標準的基于項數據的數據模型類,每個項數據可以是任何數據類型 |
| QFileSystemModel | 計算機上文件系統的數據模型類 |
| QSortFilterProxyModel | 與其他數據模型結合,提供排序和過濾功能的數據模型類 |
| QSqlQueryModel | 用于數據庫SQL查詢結果的數據模型類 |
| QSqlTableModel | 用于數據庫的一個數據表的數據模型類 |
| QSqlRelationalTableModel | 用于關系型數據表的數據模型類 |
數據模型中存儲數據的基本單元都是項(item),每個項有一個行號、一個列號,還有一個父項
QModelIndex 表示模型索引的類。模型索引提供數據存取的一個臨時指針
//Table Model QModelIndex indexA = model->index(0, 0, QModelIndex()); QModelIndex indexC = model->index(2, 1, QModelIndex()); //Tree Model indexA 表示indexB的根節點 QModelIndex indexB = model->index(1, 0, indexA);QFileSystemModel
如同 Widnows 的資源管理器一樣。使用 QFileSystemModel 提供的接口函數,可以創建目錄、刪除目錄、重命名目錄,可以獲得文件名稱、目錄名稱、文件大小等參數,還可以獲得文件的詳細信息。
QFileSystemModel * model = new QFileSystemModel; model->setRootPath(QDir::currentPath());//通過QFileSystemModel,使用QTreeView、QListView、QTableView可以直接通過QModleIndex調用QFileSystemModel讀取的內容
//給出this指針,當窗體關閉的時候,指針會自動進行回收 //直接給TreeView ListView tableView設置文件模型,即可顯示文件基本信息(類似文件管理器) fileMode = new QFileSystemModel(this); fileMode->setRootPath(QDir::currentPath()); ui->treeView->setModel(fileMode); ui->listView->setModel(fileMode); ui->tableView->setModel(fileMode); ui->tableView->verticalHeader()->setVisible(false); ? //連接信號,當QTreeViewd的表項發生變化時,QListView、QTableView發生相應的變化 connect(ui->treeView, SIGNAL(clicked(QModelIndex)), ui->listView, SLOT(setRootIndex(QModelIndex))); connect(ui->treeView, SIGNAL(clicked(QModelIndex)), ui->tableView, SLOT(setRootIndex(QModelIndex)));可以通過QModelIndex來獲取QFileSystemModel存取的信息
void MainWindow::on_treeView_clicked(const QModelIndex &index) {//通過QFileSystemModel的QModelIndex來獲取文件名、文件大小、文件類型、及是否是文件夾ui->labName->setText(fileMode->fileName(index));ui->labPath->setText(fileMode->filePath(index));ui->labType->setText(fileMode->type(index));unsigned sz = fileMode->size(index) / 1024; ?if(sz < 1024){ui->labSize->setText(QString::asprintf("%d kb", sz));}else{ui->labSize->setText(QString::asprintf("%2F kb", (float)sz/1024));} ?ui->checkBox->setChecked(fileMode->isDir(index)); }QStringListModel
//定義QStringListModel QStringListModel ?*themodel;//設置QStringListModel 的數據
theModle = new QStringListModel(this); QStringList ? ? ? ? theStrList; //保存初始 StringList theStrList<<"北京"<<"上海"<<"天津"<<"河北"<<"山東"<<"四川"<<"重慶"<<"廣東"<<"河南"; //初始化 StringList theModle->setStringList(theStrList); //給QListView設置模式,即將QStringListModel的值給給QListView設置模式 ui->listView_2->setModel(theModle); //獲取QStringListModel設置的值QStringList strlist = theModle->stringList();//將從QStringListModel獲取的值設置到QPlainTextEdit中去foreach(auto str, strlist){ui->plainTextEdit_2->appendPlainText(str);}QStandardItemModel
#define FixedColumnCount 6 QStandardItemModel ?*theModel;//數據模型 QItemSelectionModel *theSelection;//Item選擇模型 ? //為tableView設置數據模型 打通了Mode和View之間的關系 theModel = new QStandardItemModel(10, FixedColumnCount, this); theSelection = new QItemSelectionModel(theModel); ui->tableView->setModel(theModel); //設置數據模型 ui->tableView->setSelectionModel(theSelection);//設置選擇模型QStandardItemModel添加數據
void MainWindow::iniModelFromStringList(QStringList& aFileContent) { //從一個StringList 獲取數據,初始化數據Modelint rowCnt=aFileContent.count(); //文本行數,第1行是標題theModel->setRowCount(rowCnt-1); //實際數據行數 ?//設置表頭QString header=aFileContent.at(0);//第1行是表頭//一個或多個空格、TAB等分隔符隔開的字符串, 分解為一個StringListQStringList headerList=header.split(QRegExp("\\s+"),QString::SkipEmptyParts);theModel->setHorizontalHeaderLabels(headerList); //設置表頭文字 ?//設置表格數據int j;QStandardItem ? *aItem;for (int i=1;i<rowCnt;i++){QString aLineText=aFileContent.at(i); //獲取 數據區 的一行//一個或多個空格、TAB等分隔符隔開的字符串, 分解為一個StringListQStringList tmpList=aLineText.split(QRegExp("\\s+"),QString::SkipEmptyParts);for (j=0;j<FixedColumnCount-1;j++) //tmpList的行數等于FixedColumnCount, 固定的{ //不包含最后一列aItem=new QStandardItem(tmpList.at(j));//創建itemtheModel->setItem(i-1,j,aItem); //為模型的某個行列位置設置Item} ?aItem=new QStandardItem(headerList.at(j));//最后一列是Checkable,需要設置aItem->setCheckable(true); //設置為Checkableif (tmpList.at(j)=="0")aItem->setCheckState(Qt::Unchecked); //根據數據設置check狀態elseaItem->setCheckState(Qt::Checked);theModel->setItem(i-1,j,aItem); //為模型的某個行列位置設置Item} } //設置QStandardItemModel表頭 QStringList ? ? headerList; headerList<<"Depth"<<"Measured Depth"<<"Direction"<<"Offset"<<"Quality"<<"Sampled"; theModel->setHorizontalHeaderLabels(headerList); //設置表頭文字 ? //設置QStandardItemModel行數 theModel->setColumnCount(5);使用文件輸入輸出流讀寫文件
//打開文件 QString curPath=QCoreApplication::applicationDirPath(); //獲取應用程序的路徑 //調用打開文件對話框打開一個文件 QString aFileName=QFileDialog::getOpenFileName(this,"打開一個文件",curPath, "井數據文件(*.txt);;所有文件(*.*)"); if (aFileName.isEmpty()) return; //如果未選擇文件,退出 ? QStringList fFileContent;//文件內容字符串列表 QFile aFile(aFileName); ?//以文件方式讀出 if (aFile.open(QIODevice::ReadOnly | QIODevice::Text)) //以只讀文本方式打開文件 {QTextStream aStream(&aFile); //用文本流讀取文件ui->plainTextEdit->clear();//清空while (!aStream.atEnd()){QString str=aStream.readLine();//讀取文件的一行ui->plainTextEdit->appendPlainText(str); //添加到文本框顯示fFileContent.append(str); //添加到 StringList}aFile.close();//關閉文件 ?this->LabCurFile->setText("當前文件:"+aFileName);//狀態欄顯示ui->actAppend->setEnabled(true); //更新Actions的enable屬性ui->actInsert->setEnabled(true);ui->actDelete->setEnabled(true);ui->actSave->setEnabled(true); ?iniModelFromStringList(fFileContent);//從StringList的內容初始化數據模型 ?//設置行列自適應ui->tableView->resizeRowsToContents();ui->tableView->resizeColumnsToContents(); }使用文件輸入輸出流保存文件
{ ? //打開文件QString curPath=QCoreApplication::applicationDirPath(); //獲取應用程序的路徑//調用打開文件對話框打開一個文件QString aFileName=QFileDialog::getSaveFileName(this,"選擇一個文件",curPath,"井數據文件(*.txt);;所有文件(*.*)");if (aFileName.isEmpty())return; //如果未選擇文件,退出 ?QFile aFile(aFileName); ?//以文件方式讀出if (!aFile.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) //以讀寫文本及覆蓋文本方式打開文件return; ?//以文件流對文件進行操作QTextStream stream(&aFile);QString str;ui->plainTextEdit->clear(); ?//獲取表頭數據QStandardItem * Item;for(int i = 0; i< theModel->columnCount(); i++){Item = theModel->horizontalHeaderItem(i);//加入兩個tab符,跟之前數據保持一致str = str + Item->text() + "\t\t";}//寫入數據stream << str << "\n";ui->plainTextEdit->appendPlainText(str); ?//獲取內容int j;//下表從0開始,因為上方已經將表頭元素分開for (int i = 0; i < theModel->rowCount(); i++){str = ""; ?for (j = 0; j < theModel->columnCount() - 1; j++){Item = theModel->item(i, j);str = str + Item->text()+ "\t\t";} ?//拿到最后一列Item = theModel->item(i, j);if(Item->checkState() == 1)str = str + "1";elsestr = str + "0"; ?//寫入數據stream << str << "\n";ui->plainTextEdit->appendPlainText(str); }QItemSelectionModel
QItemSelectionModel常與QStandardItemModel連用
theModel = new QStandardItemModel(10, FixedColumnCount, this); theSelection = new QItemSelectionModel(theModel);
QItemSelectionModel主要用于獲取view中選擇的數據項位于model的那個位置及表格的位置
向QStandardItemModel里面插入數據
//使用Qlist對數據進行添加行 QList<QStandardItem *> itemList; ? QStandardItem * item; //往Model里面添加數據 for (int i = 0; i < FixedColumnCount - 1; i++) {item = new QStandardItem("000");itemList<<item; } //獲取表頭元素最后一列的數據 QString str = theModel->headerData(theModel->columnCount() -1, Qt::Horizontal,Qt::DisplayRole).toString(); ? //設置最后一行 item = new QStandardItem(str); item->setCheckState(Qt::Checked); itemList<<item; ? int curRow = theSelection->currentIndex().row(); //在Model最后一行添加數據 theModel->insertRow(curRow,itemList); ? //重新設置最后一行的選擇模式 theSelection->clearSelection(); QModelIndex index = theModel->index(curRow, 0); theSelection->setCurrentIndex(index,QItemSelectionModel::Select);自定義代理
使用代理必須實現以下幾個函數:
?createEditor():創建用于編輯模型數據的widget組件,如QSpinBox,QComboBox。
?setEditorData():從數據模型獲取數據,供widget組件進行編輯 。
?setModelData():將widget上的數據更新到數據模型。
?updateEditorGeometry():用于給widget組件設置一個合適的大小。
QStyledItemDelegate為代理類,如果想要實現代理,需要繼承這個類,按f2進去可以了解要代理的部分,主要包括painting、editing、editor factory
將QlineEdit通過代理換成QSpinBox
//創建用于編輯模型數據的widget組件 QWidget *QIntDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {QSpinBox * editor = new QSpinBox(parent); ?//設置QSpinbox的屬性editor->setMinimum(0);editor->setMaximum(1000);editor->setFrame(false); ?return editor; } ? //從數據模型獲取數據,供widget組件進行編輯 void QIntDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const {//通過index獲取model 在通過model獲取數據int value = index.model()->data(index, Qt::EditRole).toInt(); ?//將類型轉換為QSpinbox類型QSpinBox * spinbox = static_cast<QSpinBox *>(editor); ?//設置值spinbox->setValue(value); } ? //將widget上的數據更新到數據模型 void QIntDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {//將類型轉換為QSpinbox類型QSpinBox * spinbox = static_cast<QSpinBox *>(editor); ?//拿到現在的取值spinbox->interpretText(); ?//設置modelint value = spinbox->value();model->setData(index, value, Qt::EditRole); } ? //用于給widget組件設置一個合適的大小 void QIntDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const {//設置大小editor->setGeometry(option.rect); }寫好代理類之后通過在tableview(視圖)上設置即可使用
QIntDelegate intSpinDelegate;//設置自定義代理 //調用代理 //為第0列設置自定義代理 ui->tableView->setItemDelegateForColumn(0, &intSpinDelegate);Qt對話框
標準對話框
QFileDialog
//選擇單個文件 QString curPath=QDir::currentPath();//獲取系統當前目錄 // QString curPath=QCoreApplication::applicationDirPath(); //獲取應用程序的路徑 QString dlgTitle="選擇一個文件"; //對話框標題 QString filter="文本文件(*.txt);;圖片文件(*.jpg *.gif *.png);;所有文件(*.*)"; //文件過濾器 ? QString aFileName=QFileDialog::getOpenFileName(this,dlgTitle,curPath,filter); ? if (!aFileName.isEmpty()) ui->plainTextEdit->appendPlainText(aFleName);QColorDialog
//設置QplaintTextEdit字體顏色 QPalette pal = ui->plainTextEdit->palette(); QColor inicolor = pal.color(QPalette::Text); ? //通過QColorDialog選擇的顏色返回出來 inicolor為初始的顏色 QColor color = QColorDialog::getColor(inicolor, this, "選擇顏色"); ? //將獲取的樣式設置到QplainTextEdit中 if(!color.isValid()) return; pal.setColor(QPalette::Text, color); ui->plainTextEdit->setPalette(pal);QFontDialog
//設置字體 bool ok = false; QFont iniFont = ui->plainTextEdit->font(); ? //第一個參數如果選擇成功 則返回true 否則返回false QFont font = QFontDialog::getFont(&ok, iniFont, this, "選擇字體"); ? //為QPliantTextEdit設置選擇的字體 if(!ok) return; ui->plainTextEdit->setFont(font);輸入對話框
字符輸入對話框
//輸入字符串 QString dlgTitle="輸入文字對話框"; QString txtLabel="請輸入文件名"; QString defaultInput="新建文件.txt"; QLineEdit::EchoMode echoMode=QLineEdit::Normal;//正常文字輸入 // ? QLineEdit::EchoMode echoMode=QLineEdit::Password;//密碼輸入 ? bool ok=false; QString text = QInputDialog::getText(this, dlgTitle,txtLabel, echoMode,defaultInput, &ok);整形輸入對話框
//輸入整數 QString dlgTitle="輸入整數對話框"; QString txtLabel="設置字體大小"; int defaultValue=ui->plainTextEdit->font().pointSize(); //現有字體大小 int minValue=6, maxValue=50,stepValue=1; //范圍,步長 bool ok=false; int inputValue = QInputDialog::getInt(this, dlgTitle,txtLabel, defaultValue, minValue,maxValue,stepValue,&ok); if (ok) //是否確認輸入 {QFont ? font=ui->plainTextEdit->font();font.setPointSize(inputValue);ui->plainTextEdit->setFont(font); }浮點數輸入對話框
//輸入浮點數 QString dlgTitle="輸入浮點數對話框"; QString txtLabel="輸入一個浮點數"; float defaultValue=3.13; ? float minValue=0, maxValue=10000; ?//范圍 int decimals=2;//小數點位數 ? bool ok=false; float inputValue = QInputDialog::getDouble(this, dlgTitle,txtLabel, defaultValue, minValue,maxValue,decimals,&ok); if (ok) //確認選擇 {QString str=QString::asprintf("輸入了一個浮點數:%.2f",inputValue);ui->plainTextEdit->appendPlainText(str); }條目輸入對話框
//條目選擇輸入 QStringList items; //ComboBox 列表的內容 items <<"優秀"<<"良好"<<"合格"<<"不合格"; ? QString dlgTitle="條目選擇對話框"; QString txtLabel="請選擇級別"; int ? ? curIndex=0; //初始選擇項 bool ? ?editable=true; //ComboBox是否可編輯 bool ? ?ok=false; QString text = QInputDialog::getItem(this, dlgTitle,txtLabel,items,curIndex,editable,&ok); ? if (ok && !text.isEmpty()) ui->plainTextEdit->appendPlainText(text);標準消息框
Question消息框
QString dlgTitle="Question消息框"; QString strInfo="文件已被修改,是否保存修改?"; ? QMessageBox::StandardButton ?defaultBtn=QMessageBox::NoButton; //缺省按鈕 ? QMessageBox::StandardButton result;//返回選擇的按鈕 result=QMessageBox::question(this, dlgTitle, strInfo, QMessageBox::Yes|QMessageBox::No |QMessageBox::Cancel, defaultBtn); ? if (result==QMessageBox::Yes) ui->plainTextEdit->appendPlainText("Question消息框: Yes 被選擇"); else if(result==QMessageBox::No) ui->plainTextEdit->appendPlainText("Question消息框: No 被選擇"); else if(result==QMessageBox::Cancel) ui->plainTextEdit->appendPlainText("Question消息框: Cancel 被選擇"); else ui->plainTextEdit->appendPlainText("Question消息框: 無選擇");information消息框
QString dlgTitle="information消息框"; QString strInfo="文件已經打開,字體大小已設置"; ? //QMessageBox::information(this, dlgTitle, strInfo);//使用缺省的按鈕 QMessageBox::information(this, dlgTitle, strInfo, QMessageBox::Ok,QMessageBox::NoButton);warning消息框
QString dlgTitle="warning 消息框"; QString strInfo="文件內容已經被修改"; ? QMessageBox::warning(this, dlgTitle, strInfo);critical消息框
QString dlgTitle="critical消息框"; QString strInfo="有不明程序訪問網絡"; QMessageBox::critical(this, dlgTitle, strInfo);about消息框
QString dlgTitle="about消息框"; QString strInfo="我開發的數據查看軟件 V1.0 \n 保留所有版權"; ? QMessageBox::about(this, dlgTitle, strInfo);自定義對話框及調用
如果想要在一個窗體調用使用另外一個窗體的元素,可以通過寫public方法,通過調用public方法實現調用,需要在被調用窗體發出信號供主窗體接收,如按確認按鈕發出accept()信號
首先在頭文件聲明方法
int ? ? rowCount();//獲取對話框輸入的行數 int ? ? columnCount();//獲取對話框輸入的列數 void ? ?setRowColumn(int row, int column); //初始對話框上兩個SpinBox的值在cpp實現方法
int QWDialogSize::rowCount() { //用于主窗口調用獲得行數的輸入值return ?ui->spinBoxRow->value(); } ? int QWDialogSize::columnCount() {//用于主窗口調用獲得列數的輸入值return ?ui->spinBoxColumn->value(); } ? void QWDialogSize::setRowColumn(int row, int column) { //初始化數據顯示ui->spinBoxRow->setValue(row);ui->spinBoxColumn->setValue(column); }在另外一個窗體添加頭文件,new出來然后調用
QWDialogSize ? ?*dlgTableSize=new QWDialogSize(this); //創建對話框dlgTableSize->setRowColumn(theModel->rowCount(),theModel->columnCount()); //對話框數據初始化 int ret=dlgTableSize->exec();// 以模態方式顯示對話框,用戶關閉對話框時返回 DialogCode值 if (ret==QDialog::Accepted) //OK鍵被按下,對話框關閉,若設置了setAttribute(Qt::WA_DeleteOnClose),對話框被釋放,無法獲得返回值 { //OK鍵被按下,獲取對話框上的輸入,設置行數和列數int cols=dlgTableSize->columnCount();theModel->setColumnCount(cols); ?int rows=dlgTableSize->rowCount();theModel->setRowCount(rows); } delete dlgTableSize; //刪除對話框 //如果不想刪除可以調用窗體的屬性,實現自動刪除 //dlgTableSize->setAttribute(Qt::WA_DeleteOnClose);調用父窗體的方法
MainWindow *parWind = (MainWindow*)parentWidget(); //獲取主窗口 //首先在父窗體new出來 傳入this,作為父窗體 dlgLocate = new QWDialogLocate(this); //創建對話框,傳遞指針 dlgLocate->setAttribute(Qt::WA_DeleteOnClose); //對話框關閉時自動刪除對話框對象,用于不需要讀取返回值的對話框 ? //后調用父窗口的public方法 #include "mainwindow.h" void QWDialogLocate::on_btnSetText_clicked() {//定位到單元格,并設置字符串int row=ui->spinBoxRow->value(); //行號int col=ui->spinBoxColumn->value();//列號 ?MainWindow *parWind = (MainWindow*)parentWidget(); //獲取主窗口parWind->setACellText(row,col,ui->edtCaption->text()); //設置單元格文字if (ui->chkBoxRow->isChecked()) //行增ui->spinBoxRow->setValue(1+ui->spinBoxRow->value()); ?if (ui->chkBoxColumn->isChecked()) //列增ui->spinBoxColumn->setValue(1+ui->spinBoxColumn->value()); }多窗體應用程序設計
//窗體的一些的屬性設置 void QWidget::setWindowState(Qt::WindowStates windowstate);| Qt::NonModal | 無模態,不會阻止其他窗口的輸入 |
| Qt::WindowModal | 窗口對于其父窗口、所有的上級父窗口都是模態的 |
| Qt::ApplicationModal | 窗口對整個應用程序是模態的,阻止所有窗口的輸入 |
| Qt:: WA_AcceptDrops | 允許窗體接收拖放來的組件 |
| Qt::WA_DeleteOnClose | 窗體關閉時刪除自己,釋放內存 |
| Qt::WA_Hover | 鼠標進入或移出窗體時產生paint事件 |
| Qt:: WAAcceptTouchEvents | 窗體是否接受觸屏事件 |
| Qt::Widget | 這是 QWidget 類的缺省類型。這種類型的窗體,如果它有父窗體,就作為父窗 體的子窗體;否則就作為一個獨立的窗口 |
| Qt::Window | 表明這個窗體是一個窗口,通常具有窗口的邊框、標題欄,而不管它是否有父窗體 |
| Qt::Dialog | 表明這個窗體是一個窗口,并且要顯示為對話框(例如在標題欄沒有最小化、 最大化按鈕)。這是 QDialog 類的缺省類型 |
| Qt::Popup | 表明這個窗體是用作彈出式菜單的窗體 |
| Qt::Tool | 表明這個窗體是工具窗體,具有更小的標題欄和關閉按鈕,通常作為工具欄的 窗體 |
| Qt::ToolTip | 表明這是用于 Tooltip 消息提示的窗體 |
| Qt::SplashScreen | 表明窗體是splash屏幕,是 QSplashScreen 類的缺省類型 |
| Qt::Desktop | 表明窗體是桌面,這是 QDesktopWidget 類的類型 |
| Qt::SubWindow | 表明窗體是子窗體,例如 QMdiSubWindow 就是這種類型 |
| Qt::MSWindowsFixedSizeDialogHint | 在 Windows 平臺上,使窗口具有更窄的邊框,用于固定大小的對話框 |
| Qt::FramelessWindowHint | 創建無邊框窗口 |
| WindowHint要定義窗體外觀定制窗體外觀的常量,需要先設置 Qt::Customize | |
| Qt::CustomizeWindowHint | 關閉缺省的窗口標題欄 |
| Qt::WindowTitleHint | 窗口有標題欄 |
| Qt::WindowSystemMenuHint | 有窗口系統菜單 |
| Qt::WindowMinimizeButtonHint | 有最小化按鈕 |
| Qt::WindowMaximizeButtonHint | 有最大化按鈕 |
| Qt::WindowMinMaxButtonsHint | 有最小化、最大化按鈕 |
| Qt::WindowCloseButtonHint | 有關閉按鈕 |
| Qt::Windo wContextHelpButtonHint | 有上下文幫助按鈕 |
| Qt::WindowStaysOnTopHint | 窗口總是處于最上層 |
| Qt::WindowStaysOnBottomHint | 窗口總是處于最下層 |
| Qt::WindowTransparentForlnput | 窗口只作為輸出,不接受輸入 |
QMainWindow創建的時候可以使用其他窗體作為父窗體,如:
QMainWindow * testMain = new QMainWindow(this); testMain->setAttribute(Qt::WA_DeleteOnClose); testMain->setWindowTitle("多實例窗口,指定父窗口"); testMain->show();但QWidget則一般不會使用QMainWindow作為它的父窗體,如果作為父窗體則貼在父窗體上不能移動,一般不傳入this指針使用
//不加入this窗體關閉不會進行自動回收 QFormDoc * fordoc = new QFormDoc(); //設置關閉時自動刪除 fordoc->setAttribute(Qt::WA_DeleteOnClose); //設置窗口標題 fordoc->setWindowTitle("基于QWidget的窗體,無父窗口,關閉時刪除"); //設置窗體透明度 fordoc->setWindowOpacity(0.7); fordoc->show();MDI應用程序設計
MDI模式的使用應加入頭文件 #include "QMdiSubWindow"
//設置MDI模式 級聯展開為分為幾個不同窗體打開 平鋪展開為幾個窗體在同一個大窗體展開 void MainWindow::on_actViewMode_triggered(bool checked) {if(checked){//設置為TableView模式ui->mdiArea->setViewMode(QMdiArea::TabbedView); ?//設置tableview模式窗體可關閉ui->mdiArea->setTabsClosable(true); ?//設置平鋪展開和級聯展開不可用ui->actCascade->setEnabled(false);ui->actTile->setEnabled(false);}else{//設置為窗體模式(默認模式)ui->mdiArea->setViewMode(QMdiArea::SubWindowView); ?//設置平鋪展開和級聯展開可用ui->actCascade->setEnabled(true);ui->actTile->setEnabled(true);} } ? ? //這兩種模式在QMdiArea::SubWindowView(窗體模式)進行使用 void MainWindow::on_actCascade_triggered() {//設置QMdiArea級聯模式ui->mdiArea->cascadeSubWindows(); ? } ? void MainWindow::on_actTile_triggered() {//設置QMdiArea平鋪模式ui->mdiArea->tileSubWindows(); } ? //當當前選擇的Widget發生改變時,狀態欄顯示文件地址 void MainWindow::on_mdiArea_subWindowActivated(QMdiSubWindow *arg1) {//如果沒有窗口的話 設置剪切復制等為不可用 清空狀態欄的內容if(ui->mdiArea->subWindowList().count() == 0){ui->actCopy->setEnabled(false);ui->actCut->setEnabled(false);ui->actFont->setEnabled(false);ui->actPaste->setEnabled(false);ui->statusBar->clearMessage();}else{//顯示主窗口的文件名FormDoc * mdoc = (FormDoc *)ui->mdiArea->activeSubWindow()->widget();ui->statusBar->showMessage(mdoc->GetcurrentFileName());} } //打開文件 FormDoc為自定義QWidget void MainWindow::on_actDoc_Open_triggered() {bool needNew = false;FormDoc * mdoc; ?//獲取QMdiArea的個數if(ui->mdiArea->subWindowList().count() > 0){// ui->mdiArea->activeSubWindow()獲取的是QMdiSubWindow對象//如果想要獲取相應的Qwidget 需要使用ui->mdiArea->activeSubWindow()->widget();后進行類型轉換mdoc = (FormDoc*)ui->mdiArea->activeSubWindow()->widget();needNew = mdoc->isFileOpened();}else{needNew = true;} ?if(needNew){mdoc = new FormDoc(this);//向獲取QMdiArea里面添加Widgetui->mdiArea->addSubWindow(mdoc);} ?QString fileName = QFileDialog::getOpenFileName(this, "open", "", "C程序文件(.h *cpp);;所有文件" );mdoc->loadFromFile(fileName);mdoc->show();ui->actCopy->setEnabled(true);ui->actCut->setEnabled(true);ui->actFont->setEnabled(true);ui->actPaste->setEnabled(true); } //加載文件 使用QTextStream對文件進行讀取 void FormDoc::loadFromFile(QString &aFileName) {QFile file(aFileName); ?//QIODevice::ReadOnly設置為只讀 QIODevice::Text設置為文本格式,會自動處理\n \t等字符if(file.open(QIODevice::ReadOnly)|QIODevice::Text){//使用QTextStream對文本進行操作QTextStream stream(&file); ?//填充QPlainTextui->plainTextEdit->clear();ui->plainTextEdit->setPlainText(stream.readAll()); ?//獲取文件的路徑和名稱mCurrentFile = aFileName;QFileInfo fileinfo(aFileName);QString str = fileinfo.fileName();setWindowTitle(str); ?//設置為true,代表文檔已經是打開的狀態m_isOpen = true;} }SPlash和登錄窗口
Qt有一個QSplashScreen類可以實現Splash窗口的功能,它提供了載入圖片,自動設置窗口無邊框效果等功能。
QSettings配置表的存入和讀取
#include <QSettings> //寫入注冊表 void DialogLogin::writeSettings() {//使用QSettings將信息寫入注冊表中 第一個參數為庫名 第二個參數為表名QSettings settings("LF-QT", "Simple6_5"); ?//為注冊表添加數據settings.setValue("Username", m_user);settings.setValue("PSWD", m_pswd);settings.setValue("saved", ui->chkBoxSave->isChecked());//是否保存 } ? //讀取配置表的數據 void DialogLogin::readSettings() {QSettings settings("LF-QT", "Simple6_5"); ?//獲取配置表數據 進行類型轉換//第一個參數為關鍵值 也就是SetValue的第一個參數,第二個參數為默認值bool saved = settings.value("saved", false).toBool();m_user = settings.value("Username", "user").toString(); ?//設置默認密碼 進行加密處理QString defaultPSWD = encrypt("123456");m_pswd = settings.value("PSWD", defaultPSWD).toString(); ?//如果勾選了 自動填充賬號if(saved){ui->editUser->setText(m_user);}ui->chkBoxSave->setChecked(saved); }使用哈希算法對md5進行加密
#include <QCryptographicHash> //對密碼進行加密 QString DialogLogin::encrypt(const QString &str) {QByteArray btArray;btArray.append(str); ?//使用哈希算法進行加密 加密格式為md5類型QCryptographicHash hash(QCryptographicHash::Md5);hash.addData(btArray); ?//接收加密后的結果 并進行十六進制類型轉換存儲QByteArray resultArray = hash.result();QString resultmd5 = resultArray.toHex();return resultmd5; }設置QDialog屬性
ui->editPSWD->setEchoMode(QLineEdit::Password); //密碼輸入編輯框設置為密碼輸入模式 this->setAttribute(Qt::WA_DeleteOnClose);//設置為關閉時刪除 this->setWindowFlags(Qt::SplashScreen); //設置為SplashScreen, 窗口無邊框,不在任務欄顯示使用鼠標事件使得無標頭的QDialog可以進行移動
#include <QMouseEvent> ? //頭文件 protected://用于鼠標拖動窗口的鼠標事件操作void mousePressEvent(QMouseEvent *event);void mouseMoveEvent(QMouseEvent *event);void mouseReleaseEvent(QMouseEvent *event);bool ? ?m_moving=false;//表示窗口是否在鼠標操作下移動QPoint ?m_lastPos; ?//上一次的鼠標位置 ? //cpp文件 void DialogLogin::mousePressEvent(QMouseEvent *event) {if(event->buttton == Qt::LeftButton){m_moving = true;//記錄移動的距離 globalPos()為鼠標點擊后的位置到(0,0)點距離 pos()為DialogLogin窗體到(0,0)點距離m_lastPos = event->globalPos() - pos();} ?return DialogLogin::mouseMoveEvent(event); } ? void DialogLogin::mouseMoveEvent(QMouseEvent *event) {if(m_moving && (event->buttton == Qt::LeftButton)){move(event->globalPos() - m_lastPos);m_lastPos = event->globalPos() - pos();} } ? void DialogLogin::mouseReleaseEvent(QMouseEvent *event) {m_moving = false; } ?文本文件讀寫
| QIODevice::ReadOnly | 以只讀方式打開 |
| QIODevice::WriteOnly | 以只寫方式打開 |
| QIODevice::ReadWrite | 以讀寫方式打開 |
| QIODevice::Append | 新增加的內容將被追加到文件末尾 |
| QIODevice::Truncate | 以重寫的方式打開,原有內容會被刪除 |
| QIODevice::Text | 在讀取時,將行結束符轉換成 \n;在寫入時,將行結束符轉換成本地格式,例如 Win32 平臺上是 \r\n |
QFile IODevice讀寫文件
#include <QFileDialog> //使用QFile讀取文件 void MainWindow::on_actOpen_IODevice_triggered() {//設置QFileDialog 屬性 獲得打開文件的文件路徑QString curPath = QCoreApplication::applicationDirPath();QString dlgTitle = "打開文件";QString filter = "程序(*.h *.cpp);;文本( *.txt);; 所有文件(*.*)";QString fileName = QFileDialog::getOpenFileName(this, curPath, dlgTitle, filter);if(fileName.isEmpty()) ?return; ?//使用QFile IODevice對文件進行讀取QFile file(fileName);if(file.open(QIODevice::ReadOnly | QIODevice::Text)){ui->plainTextEditIODevice->setPlainText(QString::fromLocal8Bit(file.readAll()));file.close();ui->tabWidget->setCurrentIndex(0);} } ? //使用QFile另存為文件 即寫文件 void MainWindow::on_actSave_IODevice_triggered() {//設置QFileDialog 屬性 獲得打開文件的文件路徑QString curPath = QCoreApplication::applicationDirPath();QString dlgTitle = "打開文件";QString filter = "程序(*.h);;文本( *.txt);; 所有文件(*.*)";QString fileName = QFileDialog::getSaveFileName(this, curPath, dlgTitle, filter);if(fileName.isEmpty()) ?return; ?//打開文件進行寫操作QFile file(fileName);if(file.open(QIODevice::WriteOnly | QIODevice::Text)){//獲取QPlainText的內容 并進行類型轉換后寫入文件內QString str = ui->plainTextEditIODevice->toPlainText(); ?//寫入文件QByteArray btyArray = str.toUtf8();file.write(btyArray, btyArray.length()); ?//關閉文件file.close(); ?//設置QtabWidget當前索引ui->tabWidget->setCurrentIndex(0);} }QTextSteam讀寫文件
#include <QFileDialog> #include <QTextStream> //使用QTextStream進行讀取 void MainWindow::on_actOpen_TextStream_triggered() {//設置QFileDialog 屬性 獲得打開文件的文件路徑QString curPath = QCoreApplication::applicationDirPath();QString dlgTitle = "打開文件";QString filter = "程序(*.h *.cpp);;文本( *.txt);; 所有文件(*.*)";QString fileName = QFileDialog::getOpenFileName(this, curPath, dlgTitle, filter);if(fileName.isEmpty()) ?return; ?//使用QFile對文件進行讀取QFile file(fileName);if(file.open(QIODevice::ReadOnly | QIODevice::Text)){//QTextStream可以一行一行讀取QTextStream stream(&file); ?//設置自動識別編碼stream.setAutoDetectUnicode(true); ?//使用一行一行讀取while(stream.atEnd()){ui->plainTextEditTextSteam->appendPlainText(stream.readLine());}//ui->plainTextEditTextSteam->setPlainText(stream.readAll());file.close();ui->tabWidget->setCurrentIndex(1);} } ? //使用QTextSTream進行另存為操作 即寫操作 void MainWindow::on_actSave_TextStream_triggered() {//設置QFileDialog 屬性 獲得打開文件的文件路徑QString curPath = QCoreApplication::applicationDirPath();QString dlgTitle = "打開文件";QString filter = "程序(*.h);;文本( *.txt);; 所有文件(*.*)";QString fileName = QFileDialog::getSaveFileName(this, curPath, dlgTitle, filter);if(fileName.isEmpty()) ?return; ?//打開文件進行寫操作QFile file(fileName);if(file.open(QIODevice::WriteOnly | QIODevice::Text)){QTextStream stream(&file); ?//設置自動識別編碼stream.setAutoDetectUnicode(true); ?//獲取QPlainText的內容 并進行類型轉換后寫入文件內QString str = ui->plainTextEditTextSteam->toPlainText(); ?//使用文件流寫入文件stream<< str;file.close();ui->tabWidget->setCurrentIndex(1);} }解決漢字亂碼問題
//解決漢字亂碼問題 一般寫在main函數內 其他文件讀寫操作都可解決亂碼問題 QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForLocale(codec); //解決漢字亂碼問題二進制文件讀寫
二進制文件存儲方式
主要分為兩種,一種的大地址在前面,一種是小地址在前面。
0x1234567的存儲方式
1、小地址在前 2、大地址在前
0x100 0x101 0x102 0x013 0x100 0x101 0x102 0x013
01 23 45 67 67 45 23 01
使用 QFile 和 QDataStream 進行二進制數據文件的讀寫
QFile 負責文件的 IO 設備接口,即與文件的物理交互; QDataStream 以數據流的方式讀取文件內容或寫入文件內容。Qt預定義編碼 標準編碼
以 Qt 預定義編碼保存的 stm 文件的格式定義
| 1 | rowCount | qintl6 | 行數 |
| 2 | colCount | qintl6 | 列數 |
| 3 | “Depth” | QString | 表頭標題1 |
| 4 | "Measured Depth" | QString | 表頭標題2 |
| 5 | "Direction" | QString | 表頭標題3 |
| 6 | "Offset" | QString | 表頭標題4 |
| 7 | "Quality" | QString | 表頭標題5 |
| 8 | "Sampled" | QString | 表頭標題6 |
| 9 | 第1行各列數據 | qint16 | 測深 |
| 10 | qreal | 垂深 | |
| 11 | qreal | 方位 | |
| 12 | qreal | 位移 | |
| 13 | QString | 固井質量 | |
| 14 | bool | 是否測井取樣 | |
| 15 | 第2行各列數據 |
使用QDataStream 讀取二進制文件(.stm,.dat都是二進制文件),首先寫的時候要根據各種數據類型進行寫入,讀出的時候要根據寫入的時候的數據類型進行寫出,寫入的時候要注意,因為是根據二進制代碼進行寫入,一個出錯,其余都會跟著出錯。
使用QDataStream讀寫stm類型文件
使用QDataStream 寫.stm文件 stm文件需要設置版本好號
#include <QFileDialog> #include <QDataStream> //theModel為QStandardItemModel ? //使用QDataStream進行寫文件 需要根據流的方式進行寫入 void MainWindow::on_actSave_triggered() {//設置QFileDialog 屬性 獲得打開文件的文件路徑QString curPath = QCoreApplication::applicationDirPath();QString dlgTitle = "保存文件";QString filter = "Qt預編碼文件(*.stm)";QString fileName = QFileDialog::getSaveFileName(this, curPath, dlgTitle, filter);if(fileName.isEmpty()) ?return; ?//使用QFile IODevice對文件進行讀取QFile file(fileName); ?//QIODevice::Truncate對文件進行覆蓋if(file.open(QIODevice::WriteOnly | QIODevice::Truncate)){//使用QDataStream讀取二進制文件QDataStream stream(&file); ?//設置QDataStream的版本號 不設置默認會給一個版本號stream.setVersion(QDataStream::Qt_5_0); ?//存入表格行數和列數qint16 rowCount = theModel->rowCount();qint16 colCount = theModel->columnCount();stream<<rowCount;stream<<colCount; ?//存入表頭文字for(int i = 0; i < colCount; i++){stream<<theModel->horizontalHeaderItem(i)->text();} ?//數據區域qint16 Depth;qreal MeasuredDepth, Direction, Offset;QString Quality;bool Sampled; ?//從表格中獲取數據填入文件中for(int i = 0 ; i < rowCount; i++){Depth = theModel->item(i , 0)->data(Qt::DisplayRole).toInt();stream<<Depth; ?MeasuredDepth = theModel->item(i , 1)->data(Qt::DisplayRole).toFloat();stream<<MeasuredDepth; ?Direction = theModel->item(i , 2)->data(Qt::DisplayRole).toFloat();stream<<Direction; ?Offset = theModel->item(i , 3)->data(Qt::DisplayRole).toFloat();stream<<Offset; ?Quality = theModel->item(i , 4)->data(Qt::DisplayRole).toString();stream<<Quality; ?//最后一項為勾選框Sampled = (theModel->item(i , 5)->checkState() == Qt::Checked);stream<<Sampled;}file.close();} }使用QDataSteam讀取二進制文件,需要按照寫入的格式進行讀取 讀取.stm文件
#include <QFileDialog> #include <QDataStream> //theModel為QStandardItemModel ? //打開二進制文件使用QStandardItemModel和QItemSelectionModel加載到Tabbleview中 void MainWindow::on_actOpen_triggered() {//設置QFileDialog 屬性 獲得打開文件的文件路徑QString curPath = QCoreApplication::applicationDirPath();QString dlgTitle = "打開文件";QString filter = "Qt預編碼文件(*.stm)";QString fileName = QFileDialog::getOpenFileName(this, curPath, dlgTitle, filter);if(fileName.isEmpty()) ?return; ?//使用QFile IODevice對文件進行讀取QFile file(fileName);if(file.open(QIODevice::ReadOnly)){//使用QDataStream讀取二進制文件QDataStream stream(&file); ?//設置QDataStream的版本號 不設置默認會給一個版本號stream.setVersion(QDataStream::Qt_5_0);//數據區域qint16 rowCount, colCount;stream>>rowCount;stream>>colCount;resetTableRow(rowCount); ?//將不需要的數據輸出給strQString str;for(int i = 0; i < colCount; i++){stream>>str;} ?//數據區域qint16 Depth;qreal MeasuredDepth, Direction, Offset;QString Quality;bool Sampled; ?//根據index獲取Item,使用item填充數據 一共有六行數據QStandardItem * item;QModelIndex index;for(int i = 0; i < rowCount; i++){stream>>Depth;index = theModel->index(i, 0);item = theModel->itemFromIndex(index);item->setData(Depth, Qt::DisplayRole); ?stream>>MeasuredDepth;index = theModel->index(i, 1);item = theModel->itemFromIndex(index);item->setData(MeasuredDepth, Qt::DisplayRole); ?stream>>Direction;index = theModel->index(i, 2);item = theModel->itemFromIndex(index);item->setData(Direction, Qt::DisplayRole); ?stream>>Offset;index = theModel->index(i, 3);item = theModel->itemFromIndex(index);item->setData(Offset, Qt::DisplayRole); ?stream>>Quality;index = theModel->index(i, 4);item = theModel->itemFromIndex(index);item->setData(Quality, Qt::DisplayRole); ?stream>>Sampled;index = theModel->index(i, 5);item = theModel->itemFromIndex(index);//設置選中狀態if(Sampled)item->setCheckState(Qt::Checked);elseitem->setCheckState(Qt::Unchecked);}file.close();} }使用QDataStream讀寫dat類型文件
寫dat文件 dat為標準編碼,可以不設置版本號 但是需要設置編碼格式
void MainWindow::on_actSaveBin_triggered() {//設置QFileDialog 屬性 獲得打開文件的文件路徑QString curPath = QCoreApplication::applicationDirPath();QString dlgTitle = "保存文件";QString filter = "Qt預編碼文件(*.dat)";QString fileName = QFileDialog::getSaveFileName(this, curPath, dlgTitle, filter);if(fileName.isEmpty()) ?return; ?//使用QFile IODevice對文件進行讀取QFile file(fileName); ?//QIODevice::Truncate對文件進行覆蓋if(file.open(QIODevice::WriteOnly | QIODevice::Truncate)){//使用QDataStream讀取二進制文件QDataStream stream(&file); ?//設置編碼規則 分為兩種stream.setByteOrder(QDataStream::LittleEndian); ?//存入表格行數和列數qint16 rowCount = theModel->rowCount();qint16 colCount = theModel->columnCount(); ?//寫的時候 整形浮點型使用writeRawData() 該方法是根據地址和大小寫入stream.writeRawData((char *) &rowCount, sizeof(qint16));stream.writeRawData((char *) &colCount, sizeof(qint16)); ? ?//存入表頭文字 QString型的寫入使用writeBytes()QByteArray btArray;for(int i = 0; i < colCount; i++){QString str = theModel->horizontalHeaderItem(i)->text();btArray = str.toUtf8();stream.writeBytes(btArray, btArray.length());} ?//數據區域qint16 Depth;qreal MeasuredDepth, Direction, Offset;QString Quality;bool Sampled; ?//從表格中獲取數據填入文件中for(int i = 0 ; i < rowCount; i++){Depth = theModel->item(i , 0)->data(Qt::DisplayRole).toInt();stream.writeRawData((char *) &Depth, sizeof(qint16)); ?MeasuredDepth = theModel->item(i , 1)->data(Qt::DisplayRole).toFloat();stream.writeRawData((char *) &MeasuredDepth, sizeof(qreal)); ?Direction = theModel->item(i , 2)->data(Qt::DisplayRole).toFloat();stream.writeRawData((char *) &Direction, sizeof(qreal)); ?Offset = theModel->item(i , 3)->data(Qt::DisplayRole).toFloat();stream.writeRawData((char *) &Offset, sizeof(qreal)); ?Quality = theModel->item(i , 4)->data(Qt::DisplayRole).toString();btArray = Quality.toUtf8();stream.writeBytes(btArray, btArray.length()); ?//最后一項為勾選框Sampled = (theModel->item(i , 5)->checkState() == Qt::Checked);qint8 yes = 1, no = 0;if(Sampled){stream.writeRawData((char *) &yes, sizeof(qint8));}else{stream.writeRawData((char *) &no, sizeof(qint8));}}} }使用DataStream讀取.dat文件
//打開.dat文件 void MainWindow::on_actOpenBin_triggered() {//設置QFileDialog 屬性 獲得打開文件的文件路徑QString curPath = QCoreApplication::applicationDirPath();QString dlgTitle = "打開文件";QString filter = "標準編碼(*.dat)";QString fileName = QFileDialog::getOpenFileName(this, curPath, dlgTitle, filter);if(fileName.isEmpty()) ?return; ?//使用QFile IODevice對文件進行讀取QFile file(fileName);if(file.open(QIODevice::ReadOnly)){//使用QDataStream讀取二進制文件QDataStream stream(&file); ?//設置編碼規則 分為兩種stream.setByteOrder(QDataStream::LittleEndian); ?qint16 rowCount,colCount; ?//根據數據類型的大小進行讀取數據 int類型使用readRawData進行讀取stream.readRawData((char *) &rowCount, sizeof(qint16));stream.readRawData((char *) &colCount, sizeof(qint16)); ?//初始化表格resetTableRow(rowCount); ?//使用readBytes讀取QString數據char * buf;uint strlen; ?//也就是 quint32for(int i = 0; i < colCount; i++){stream.readBytes(buf, strlen); ?//根據buf獲取相應的字符串數據 改例子不需要使用//QString str = QString::fromLocal8Bit(buf, strlen);} ?//數據區域qint16 Depth;qreal MeasuredDepth, Direction, Offset;QString Quality; ?//使用readRawData時不支持bool類型,因此使用qint8較小的一個類型qint8 Sampled; ?//根據index獲取Item,使用item填充數據 一共有六行數據QStandardItem * item;QModelIndex index;for(int i = 0; i < rowCount; i++){stream.readRawData((char *) &Depth, sizeof(qint16));index = theModel->index(i, 0);item = theModel->itemFromIndex(index);item->setData(Depth, Qt::DisplayRole); ?stream.readRawData((char *) &MeasuredDepth, sizeof(qreal));index = theModel->index(i, 1);item = theModel->itemFromIndex(index);item->setData(MeasuredDepth, Qt::DisplayRole); ?stream.readRawData((char *) &Direction, sizeof(qreal));index = theModel->index(i, 2);item = theModel->itemFromIndex(index);item->setData(Direction, Qt::DisplayRole); ?stream.readRawData((char *) &Offset, sizeof(qreal));index = theModel->index(i, 3);item = theModel->itemFromIndex(index);item->setData(Offset, Qt::DisplayRole); ?stream.readBytes(buf, strlen);QString Quality = QString::fromLocal8Bit(buf, strlen);index = theModel->index(i, 4);item = theModel->itemFromIndex(index);item->setData(Quality, Qt::DisplayRole); ?stream.readRawData((char *) &Offset, sizeof(qint8));index = theModel->index(i, 5);item = theModel->itemFromIndex(index);//設置選中狀態if(Sampled == 1)item->setCheckState(Qt::Checked);elseitem->setCheckState(Qt::Unchecked);}file.close();} }文件目錄操作
文件操作相關的類
QCoreApplication:用于提取應用程序路徑、程序名等文件信息 QFile:除了打開文件操作外,還有復制文件、刪除文件等功能 QFileInfo:用于提取文件信息,包括路徑、文件名、后綴 QDir:用于提取目錄或文件信息,獲取一個目錄下的文件或目錄列表,創建或刪除目錄和文件,文件重名等操作 QTemporaryDir 和 QTemporaryFile:用于創建臨時目錄和臨時文件。 QFileSystemWatcher:監聽目錄下文件的添加、刪除等變化
通過object對象獲取QPushbutton對象
//第一種寫法 void MainWindow::on_pushButton_68_clicked() {//通過sender()的object對象獲取QPushbutton對象 即可通過指針btn對點擊的按鈕進行操作QPushButton * btn = static_cast<QPushButton *>(sender()); ?//將QPushbutton的文本和提示內容添加到QPlainTextEdit中去ui->plainTextEdit_3->appendPlainText(btn->text());ui->plainTextEdit_3->appendPlainText(btn->toolTip()); } ? void MainWindow::on_pushButton_68_clicked() {GetBtnInfo(sender());//獲取當前的目錄添加到QPlainTextEdit中去ui->plainTextEdit_3->appendPlainText(QCoreApplication::applicationDirPath()); } ? //第二種寫法 //獲取點擊按鈕的文本和提示信息 void MainWindow::GetBtnInfo(QObject * obj) {QPushButton * btn = static_cast<QPushButton *>(obj); ?//將QPushbutton的文本和提示內容添加到QPlainTextEdit中去ui->plainTextEdit_3->appendPlainText(btn->text());ui->plainTextEdit_3->appendPlainText(btn->toolTip()); } QCoreApplication常用方法 applicationFilePath() : QString applicationName() : QString ? QFile常用方法 qint64 QFile::size() const //獲取當前文件的大小。對于打開的文件,該方法返回文件中可以讀取的字節數。 bool QIODevice::getChar(char *c) //從文件中讀取一個字符,并存儲到 c 中。讀取成功時,方法返回 true,否則返回 false。 bool QIODevice::putChar(char c) ? ?//向文件中寫入字符 c,成功時返回 true,否則返回 false。 QByteArray QIODevice::read(qint64 maxSize) //從文件中一次性最多讀取 maxSize 個字節,然后返回讀取到的字節。 qint64 QIODevice::read(char *data, qint64 maxSize) //從文件中一次性對多讀取 maxSize 個字節,讀取到的字節存儲到data指針指定的內存控件中。該方法返回成功讀取到的字節數。 QByteArray QIODevice::readAll() //讀取文件中所有的數據。 qint64 QIODevice::readLine(char *data, qint64 maxSize) //每次從文件中讀取一行數據或者讀取最多 maxSize-1 個字節,存儲到 data 中。該方法返回實際讀取到的字節數。 qint64 QIODevice::write(const char *data, qint64 maxSize) //向 data 數據一次性最多寫入 maxSize 個字節,該方法返回實際寫入的字節數。 qint64 QIODevice::write(const char *data) //將 data 數據寫入文件,該方法返回實際寫入的字節數。 qint64 QIODevice::write(const QByteArray &byteArray) //將 byteArray 數組中存儲的字節寫入文件,返回實際寫入的字節數。 bool QFile::copy(const QString &newName) //將當前文件的內容拷貝到名為 newName 的文件中,如果成功,方法返回 true,否則返回 false。copy 方法在執行復制操作之前,會關閉源文件。 bool QFile::rename(const QString &newName) //對當前文件進行重命名,新名稱為 newName,成功返回 true,失敗返回 false。 bool QFile::remove() //刪除當前文件,成功返回 true,失敗返回 false。QFileInfo常用方法 ? 一般用法: QFilelnfo filelnfo(path); QFilelnfo filelnfo;filelnfo.setFile(path); bool exists(); //判斷文件是否存在,若存在返回true。 qint64 size();//獲取文件大小,返回bytes。 QString path();//返回文件路徑,不包含文件名。 QString filePath();//返回文件路徑,包含文件名。 QString fileName();//返回文件名稱。 bool isFile();//判斷是否是文件。 bool isDir();//判斷是否是路徑。 bool isSymLink();//判斷是否是符號鏈接 QDateTime created();//創建時間 QDateTime lastModified();//最近修改時間 QDateTime lastRead();//最近讀時間 ? QDird的常用使用方法 mkdir();//創建一個目錄; rename();//對關聯目錄進行重命名; rmdir();//移除一個目錄; exists();//檢測目錄是否存在; refresh();//刷新目錄內容。 ? QTemporaryDir方法 QString errorString() const 如果isValid()返回false,則此函數返回錯誤字符串,該錯誤字符串解釋了為什么創建臨時目錄失敗。否則,這個函數返回一個空字符串。 QString filePath(const QString &fileName) const 返回臨時目錄中文件的路徑名稱。不檢查文件是否確實存在于目錄中。冗余多重分隔符或“。” 和fileName中的“..”目錄不會被刪除。 bool isValid() const 判斷生成的臨時目錄是否有效。 QString path() const 返回臨時目錄的路徑。如果無法創建QTemporaryDir,則為空。 bool remove() 刪除臨時目錄,包括其所有內容,并返回刪除狀態。 void setAutoRemove(bool b) 如果b為真,則將QTemporaryDir設置為自動刪除模式。 ? QTemporaryFile方法 void QTemporaryFile::setFileTemplate(const QString&name) 將文件名稱的靜態部分設置為名稱。如果文件模板包含將自動替換為文件名的唯一部分的XXXXXX,否則文件名將根據指定的靜態部分自動確定。 如果name包含相對文件路徑,則路徑將相對于當前工作目錄。如果你想使用系統的臨時目錄,你可以使用QDir :: tempPath()來構造名字。 bool open() 一個QTemporaryFile將永遠被打開了QIODevice::ReadWrite 模式,這可以方便地訪問文件中的數據。該函數在成功時將返回true,并將fileName()設置為使用的唯一文件名。QFileSystemWatcher方法bool addPath(const QString & path) 如果路徑存在,則添加至文件系統監控,如果路徑不存在或者已經被監控了,那么不添加。如果路徑是一個目錄,內容被修改或刪除時,會發射directoryChanged()信號;否則,當文件被修改、重命名或從磁盤上刪除時,會發出fileChanged()信號。如果監控成功,返回true;否則,返回false.監控失敗的原因通常依賴于系統,但也包括資源不存在、接入失敗、或總的監控數量限制等原因。 QStringList addPaths(const QStringList & paths) 添加每一個路徑至添加至文件系統監控,如果路徑不存在或者已經被監控了,那么不添加。返回值是不能被監控的路徑列表。 QStringList directories() const 返回一個被監控的目錄路徑列表。 QStringList files() const 返回一個被監控的文件路徑列表。 bool removePath(const QString & path) 從文件系統監控中刪除指定的路徑。如果監控被成功移除,返回true。刪除失敗的原因通常是與系統相關,但可能是由于路徑已經被刪除。 QStringList removePaths(const QStringList & paths) 從文件系統監控中刪除指定的路徑。返回值是一個無法刪除成功的路徑列表。QPainter基本繪制
Qt可以使用相同的 API 在屏幕和繪圖設備上進行繪制,它主要基于QPainter、QPaintDevice 和 QPaintEngine 這三個類。 QPainter:用來進行繪圖操作的類 QPaintDevice:抽象的二維界面,是中間媒介 QPaintEngine:提供了一些接口,可用于 QPainter 在不同的設備上進行繪制
QPainter 可以在繼承自 QPaintDevice 類的任何對象上進行繪制操作
QPainter 一般在部件的繪圖事件 paintEvent() 中進行繪制。當窗口程序需要升級或者重新繪制時,調用此成員函數。使用 repaint()和 update() 后,調用函數 paintEvent()。
QPainter的3個主要設置是: pen, brush, fontpainter.setPen(QPen(..));painter.setBruch(QBrush(..));painter.setFont(QFont(..));painter.setRenderHint(QPainter::Antialiasing);設置了bursh之后, 畫的是效果即填充QPainter的屬性影響繪制的圖形 通常使用painter.drawXXX(..)來繪制圖形
//設置派生類 Q_DECL_OVERRIDE表示父類一定要存在 否則會提示報錯 void paintEvent(QPaintEvent * event) Q_DECL_OVERRIDE; #include<QPainter> void Widget::paintEvent(QPaintEvent * event) {QPainter painter(this); ?//獲取窗體的長和寬int w = this->width();int h = this->height(); ?//設置點抗鋸齒和文字抗鋸齒 // ? painter.setRenderHint(QPainter::Antialiasing); // ? painter.setRenderHint(QPainter::TextAntialiasing); ?QPen pen; ?//設置畫筆的寬度pen.setWidth(20); ?//設置畫筆的顏色pen.setColor(Qt::red); ?//設置線的類型 設置為圓和虛線形pen.setStyle(Qt::DashDotDotLine); ?//設置接口出處類型 設置為圓角類型pen.setJoinStyle(Qt::RoundJoin); ?//為畫家設置畫筆painter.setPen(pen); ?//設置填充顏色和類型QBrush brush;brush.setColor(Qt::yellow);brush.setStyle(Qt::Dense1Pattern);painter.setBrush(brush);設置線性漸變 // ? QLinearGradient linearGrad(rect.left(),rect.top(),rect.right(),rect.bottom()); //對角線 // ? QLinearGradient linearGrad(rect.left(),rect.top(),rect.right(),rect.top());//從左到右 // ? linearGrad.setColorAt(0,Qt::blue);//起點顏色 // ? linearGrad.setColorAt(0.5,Qt::green);//起點顏色 // ? linearGrad.setColorAt(1,Qt::red);//終點顏色 // ? linearGrad.setSpread(QGradient::ReflectSpread); //展布模式 QGradient::PadSpread ,QGradient::RepeatSpread, QGradient::ReflectSpread // ? painter.setBrush(linearGrad););// ? //畫矩形 // ? QRect rect(w/4, h/4, w/2, h/2); // ? painter.drawRect(rect);// ? //畫圖片和文字 // ? QRect rect(w/4, h/4, w/2, h/2); // ? QImage image(":images/images/qt.jpg"); // ? painter.drawImage(rect, image); // ? QFont font; // ? font.setPointSize(30); // ? painter.setFont(font); // ? painter.drawText(rect, "Hello Qt"); ?//繪制多邊形QPoint points[] = {QPoint(w/3, h/3), QPoint(w/2, h/2), QPoint(w/5, 2 * h/5)};painter.drawPolyline(points, 3); }坐標系統和坐標轉換
對坐標進行平移和旋轉,實際上是對原始坐標系統進行平移旋轉,即改變了原點(0,0)位置和方向
| 坐標變換 | void translate(qreal dx,qreal dy) void rotate(qreal angle) void scale(qreal sx,qreal sy) void shear(qrael sh,qreal sy) | 坐標系統一定的偏移量,坐標原點平移到新的點 坐標系統順時針旋轉一個角度 坐標系統縮放 坐標系統做扭轉變換 |
| 狀態保存與恢復 | void save() void restore() void resetTransform() | 保存painter當前的狀態,就是將當前狀態壓入棧 恢復上一次狀態,就是從堆棧中彈出上次的狀態 復位所有的坐標變換 |
視口坐標和窗口坐標
視口: 繪圖設備的任意一個矩形區域的物理坐標,可以只選取物理坐標的一個矩形區域用于繪圖。視口默認情況下等于繪圖設備的整個矩形區。 窗口: 對應于視口的矩形區域,只不過是用邏輯坐標定義的坐標系,窗口坐標的中心在矩形中心。
void Widget::paintEvent(QPaintEvent * event) {Q_UNUSED(event);QPainter painter(this);int w = this->width();int h = this->height(); ?//設置抗鋸齒painter.setRenderHint(QPainter::Antialiasing); ?//設置視口的大小 根據窗口的最小長度設置矩形框int side = qMin(w, h);QRect rect( (w - side) / 2, (h - side) / 2, side, side);painter.drawRect(rect); ?//設置視口坐標painter.setViewport(rect); ?//畫橢圓 設置窗口坐標 左上角坐標為-100,100 中心點為0,0 長度為200,寬度為200painter.setWindow(-100, -100, 200, 200); ? // ? //相當于在0,0點畫了一個矩形 再到矩形框內畫橢圓 // ? painter.drawEllipse(0, 0, 50, 50); ?//設置顏色漸變效果 前兩個參數為漸變的起始點 后兩個坐標為漸變的終止點QLinearGradient linearGrad(0, 0, 100, 0); ?//設置起始點顏色和終止點顏色 0為起點 1為終點linearGrad.setColorAt(0, Qt::yellow);linearGrad.setColorAt(1, Qt::green); ?//設置發散的形式 為按邊界顏色發散linearGrad.setSpread(QGradient::PadSpread);painter.setBrush(linearGrad); ?//設置復合模式painter.setCompositionMode(QPainter::CompositionMode_Difference); ?//根據旋轉畫圖案for (int i = 0; i < 36; i++){//旋轉painter.rotate(10); ?//設置橢圓的中心點 使用窗口坐標繪制 50相當于是半徑painter.drawEllipse(QPoint(50,0), 50, 50);} }QtCharts
Qt Charts概述
Qt Charts基于Qt的Graphics View架構,其核心組件是QChartView和QChart ? QChartView是顯示圖標的視圖,基類為QGraphicsView ? QChart的基類是QGraphicsItem
要在項目中使用 Qt Charts 模塊,必須在項目的配置文件 . pro 文件中增加下面的一行語句 : QT += charts 在需要使用 QtCharts 的類的頭文件或源程序文件中 , 要使用如下的包含語句 : #include <QtCharts> //using namespace QtCharts ; QT_CHARTS_USE_NAMESPACE //使用宏定義
//,pro中加charts QT += charts ? #include "mainwindow.h" #include "ui_mainwindow.h" #include <QChartView> #include <QLineSeries> #include <QtMath> #include <QValueAxis> ? //加入宏定義 或者就要加入命名空間 using namespace QtCharts ; QT_CHARTS_USE_NAMESPACE ? MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);QChartView * chartView = new QChartView(this);QChart * chart = new QChart;chart->setTitle("簡單函數曲線"); ?//給chartview設置chart并鋪滿整個窗體chartView->setChart(chart);this->setCentralWidget(chartView); ?//創建折線序列QLineSeries * series0 = new QLineSeries;QLineSeries * series1 = new QLineSeries;series0->setName("sin曲線");series1->setName("cos曲線"); ?//為表格添加曲線chart->addSeries(series0);chart->addSeries(series1); ?//為序列添加數值qreal t=0,y1,y2,intv=0.1;int cnt=100;for(int i=0;i<cnt;i++){y1=qSin(t);//+qrand();series0->append(t,y1);y2=qCos(t);series1->append(t,y2);t+=intv;} ?//創建坐標軸QValueAxis * axisX =new QValueAxis;QValueAxis * axisY = new QValueAxis; ?//設置x軸axisX->setRange(0, 10);chart->setAxisX(axisX, series0);chart->setAxisX(axisX, series1); ?//設置Y軸axisY->setRange(-1, 1);chart->setAxisY(axisY, series0);chart->setAxisY(axisY, series1); }Qtchart繪制折線圖
對QChart的進行方法縮小
//chartview為QChartView控件 chart為Qhart控件 chartview->setchart(chart); //縮小表格 void MainWindow::on_actZoomOut_triggered() {ui->chartview->chart()->zoom(0.8); } //放大表格 void MainWindow::on_actZoomIn_triggered() {ui->chartview->chart()->zoom(1.2); } //恢復原始大小 void MainWindow::on_actZoomReset_triggered() {ui->chartview->chart()->zoomReset(); }創建圖表
//頭文件 #include <QtCharts> #include <QValueAxis> QT_CHARTS_USE_NAMESPACE private:Ui::MainWindow *ui;QLineSeries * curSeries;QValueAxis * curAxis; ? //創建圖表 void MainWindow::createChart() {QChart * chart = new QChart();chart->setTitle("簡單的曲線");ui->chartview->setChart(chart); ?//設置抗鋸齒模式ui->chartview->setRenderHint(QPainter::Antialiasing); ?QLineSeries * series0 = new QLineSeries;QLineSeries * series1 = new QLineSeries;series0->setName("sin曲線");series1->setName("cos曲線");curSeries = series0; ?//設置筆的樣式QPen pen;pen.setStyle(Qt::DotLine);pen.setWidth(2);pen.setColor(Qt::red);series0->setPen(pen);pen.setStyle(Qt::SolidLine);pen.setColor(Qt::blue);series1->setPen(pen); ?//為Chart添加序列chart->addSeries(series0);chart->addSeries(series1); ?//設置坐標軸QValueAxis * axisX = new QValueAxis;QValueAxis * axisY = new QValueAxis;curAxis = axisX; ?//設置坐標軸屬性axisX->setRange(0, 10);axisX->setTitleText("time(secs)"); ?//設置坐標軸為一位小數axisX->setLabelFormat("%.1f"); ?//設置中間格子一共多少條線axisX->setTickCount(11); ?//設置小分格axisX->setMinorTickCount(4); ?axisY->setRange(-1.5, 1.5);axisY->setTickCount(3);axisY->setMinorTickCount(4);axisY->setTitleText("value"); ?//為chart設置坐標軸chart->setAxisX(axisX, series0);chart->setAxisX(axisX, series1);chart->setAxisY(axisY, series0);chart->setAxisY(axisY, series1); }為圖標添加數據
//更新數據 void MainWindow::prepareData() {//獲取chart表格的序列QLineSeries * series0 = (QLineSeries *)ui->chartview->chart()->series().at(0);QLineSeries * series1 = (QLineSeries *)ui->chartview->chart()->series().at(1); ?//為序列添加數據series0->clear();series1->clear();int cnt = 100;srand(QTime::currentTime().second());qreal t = 0, y1, y2, intv = 0.1;qreal rd;for (int i = 0; i < cnt; i++){rd=(qrand() % 10)-5; //隨機數,-5~+5y1=qSin(t)+rd/50;*series0<<QPointF(t,y1); ?//序列添加數據點 // ? ? ? series0->append(t,y1); //序列添加數據點 ?rd=(qrand() % 10)-5; //隨機數,-5~+5y2=qCos(t)+rd/50; // ? ? ? series1->append(t,y2); //序列添加數據點*series1<<QPointF(t,y2); //序列添加數據點t+=intv;} }設置圖表和圖例
//設置圖表的標題 void MainWindow::on_btnSetTitle_clicked() {QChart * chart = ui->chartview->chart();chart->setTitle(ui->editTitle->text()); } ? //設置圖表標題字體 void MainWindow::on_btnSetTitleFont_clicked() {QFont font = ui->chartview->chart()->titleFont();bool ok =false;font = QFontDialog::getFont(&ok, font);if(ok){ui->chartview->chart()->setTitleFont(font);} } ? //設置圖例的位置 圖例為顯示曲線名字的一小塊區域 void MainWindow::on_radioButton_clicked() {ui->chartview->chart()->legend()->setAlignment(Qt::AlignTop); } void MainWindow::on_radioButton_2_clicked() {ui->chartview->chart()->legend()->setAlignment(Qt::AlignBottom); } void MainWindow::on_radioButton_3_clicked() {ui->chartview->chart()->legend()->setAlignment(Qt::AlignLeft); } void MainWindow::on_radioButton_4_clicked() {ui->chartview->chart()->legend()->setAlignment(Qt::AlignRight); } ? //設置圖例是否可見 void MainWindow::on_chkLegendVisible_clicked(bool checked) {ui->chartview->chart()->legend()->setVisible(checked); } //設置圖例背景是否可見 void MainWindow::on_chkBoxLegendBackground_clicked(bool checked) {ui->chartview->chart()->legend()->setBackgroundVisible(checked); } ? //設置圖例的字體 void MainWindow::on_btnLegendFont_clicked() {QFont font = ui->chartview->chart()->legend()->font();bool ok =false;font = QFontDialog::getFont(&ok, font);if(ok){ui->chartview->chart()->legend()->setFont(font);} } ? //設置圖例標簽顏色 void MainWindow::on_btnLegendlabelColor_clicked() {QColor color = ui->chartview->chart()->legend()->labelColor();color = QColorDialog::getColor(color);if(color.isValid()){ui->chartview->chart()->legend()->setLabelColor(color);} } ? //設置圖表的邊距 spinMarginBottom,spinMarginTop為QSpinBox用于控制邊距的距離 void MainWindow::on_btnSetMargin_clicked() {QMargins mgs;mgs.setBottom(ui->spinMarginBottom->value());mgs.setTop(ui->spinMarginTop->value());mgs.setLeft(ui->spinMarginLeft->value());mgs.setRight(ui->spinMarginRight->value());ui->chartview->chart()->setMargins(mgs); } ? //設置圖表的動畫效果 具體可以進入Qt函數進行了解 通過枚舉進行設置 void MainWindow::on_cBoxAnimation_currentIndexChanged(int index) {ui->chartview->chart()->setAnimationOptions((QChart::AnimationOption) index); } ? //設置圖表的主題 void MainWindow::on_cBoxTheme_currentIndexChanged(int index) {ui->chartview->chart()->setTheme(QChart::ChartTheme(index)); }QDialgoPen獲取畫筆
//頭文件 #include <QDialog> #include <QPen> public:explicit DialogPen(QWidget *parent = nullptr);~DialogPen(); ?//使用靜態函數獲取畫筆static QPen getPen(QPen pen,bool & ok);void ? ?setPen(QPen pen); //設置QPen,用于對話框的界面顯示QPen ? ?getPen(); //獲取對話框設置的QPen的屬性 ? private:QPen m_pen; ? //cpp #include "dialogpen.h" #include "ui_dialogpen.h" #include <QColorDialog> ? DialogPen::DialogPen(QWidget *parent) :QDialog(parent),ui(new Ui::DialogPen) {ui->setupUi(this); ?//“線型”ComboBox的選擇項設置ui->comboPenStyle->clear();ui->comboPenStyle->addItem("NoPen",0);ui->comboPenStyle->addItem("SolidLine",1);ui->comboPenStyle->addItem("DashLine",2);ui->comboPenStyle->addItem("DotLine",3);ui->comboPenStyle->addItem("DashDotLine",4);ui->comboPenStyle->addItem("DashDotDotLine",5);ui->comboPenStyle->addItem("CustomDashLine",6); ?ui->comboPenStyle->setCurrentIndex(1); } ? DialogPen::~DialogPen() {delete ui; } ? //使用靜態函數獲取畫筆 QPen DialogPen::getPen(QPen inipen, bool &ok) {QPen pen;DialogPen * dlg = new DialogPen;dlg->setPen(inipen);int ret = dlg->exec();if(ret == QDialog::Accepted){pen = dlg->getPen();ok = true;}else{pen = inipen;ok = false;} ?delete ?dlg;return ?pen; } ? void DialogPen::setPen(QPen pen) { //設置QPen,并刷新顯示界面m_pen=pen; ?ui->spinWidth->setValue(pen.width()); //線寬int i=static_cast<int>(pen.style()); ?//枚舉類型轉換為整型ui->comboPenStyle->setCurrentIndex(i); ?QColor ?color=pen.color();ui->btnColor->setAutoFillBackground(true); //設置顏色按鈕的背景色QString str=QString::asprintf("background-color: rgb(%d, %d, %d);",color.red(),color.green(),color.blue());ui->btnColor->setStyleSheet(str); } ? QPen DialogPen::getPen() {//獲得設置的屬性m_pen.setStyle(Qt::PenStyle(ui->comboPenStyle->currentIndex())); //線型m_pen.setWidth(ui->spinWidth->value()); //線寬 ?QColor ?color;color=ui->btnColor->palette().color(QPalette::Button);m_pen.setColor(color); //顏色return ?m_pen; } ? //選擇顏色 void DialogPen::on_btnColor_clicked() {QColor color = m_pen.color();color = QColorDialog::getColor(color); ?if(color.isValid()){QString str = QString::asprintf("background-color: rgb(%d, %d, %d);", color.red(), color.green(), color.blue());ui->btnColor->setStyleSheet(str);} }設置曲線和坐標點
//根據RadioButton判斷選中的是哪個曲線 void MainWindow::on_radioSeries0_clicked() {if(ui->radioSeries0->isChecked()){curSeries = (QLineSeries *)ui->chartview->chart()->series().at(0);}else{curSeries = (QLineSeries *)ui->chartview->chart()->series().at(1);} ?//獲取curSeries的值,更新界面ui->editSeriesName->setText(curSeries->name());ui->chkSeriesVisible->setChecked(curSeries->isVisible());ui->chkPointVisible->setChecked(curSeries->pointsVisible());ui->sliderSeriesOpacity->setValue(curSeries->opacity() * 10);ui->chkPointLabelVisible->setChecked(curSeries->pointLabelsVisible()); } void MainWindow::on_radioSeries1_clicked() {on_radioSeries0_clicked(); } ? //設置曲線的名字 void MainWindow::on_btnSeriesName_clicked() {curSeries->setName(ui->editSeriesName->text()); } ? //設置系列是否可見 void MainWindow::on_chkSeriesVisible_clicked(bool checked) {curSeries->setVisible(ui->chkSeriesVisible->isChecked()); } ? //設置數據點是否可見 void MainWindow::on_chkPointVisible_clicked(bool checked) {curSeries->setPointsVisible(ui->chkPointVisible->isChecked()); } ? //設置曲線顏色 void MainWindow::on_btnSeriesColor_clicked() {QColor color = curSeries->color();color = QColorDialog::getColor(color);if(color.isValid()){curSeries->setColor(color);} } ? //設置曲線的pen void MainWindow::on_btnSeriesPen_clicked() {bool ok = false;QPen pen = curSeries->pen();pen = DialogPen::getPen(pen, ok);if(ok){curSeries->setPen(pen);} } ? //改變曲線的透明度 void MainWindow::on_sliderSeriesOpacity_valueChanged(int value) {curSeries->setOpacity(value / 10.0); } ? //設置數據點標簽是否可見 數據點標簽是在曲線周圍顯示曲線的x,y的標簽 void MainWindow::on_chkPointLabelVisible_clicked(bool checked) {curSeries->setPointLabelsVisible(checked); } ? //設置數據點標簽的顏色 void MainWindow::on_btnSeriesLabColor_clicked() {QColor color = curSeries->pointLabelsColor();color = QColorDialog::getColor(color);if(color.isValid()){curSeries->setPointLabelsColor(color);} } ? //設置數據點標簽字體 void MainWindow::on_btnSeriesLabFont_clicked() {QFont font = curSeries->pointLabelsFont();bool ok = false;font = QFontDialog::getFont(&ok, font);if(ok){curSeries->setPointLabelsFont(font);} } ? //根據RadioButton選擇的是哪個設置數據點標簽樣式 顯示y的值 顯示x和y的值 //"@xPoint, @yPoint" 10,20 無括號 "(@xPoint, @yPoint)" (10, 20)有括號 void MainWindow::on_radioSeriesLabFormat0_clicked() {if(ui->radioSeriesLabFormat0->isChecked()){curSeries->setPointLabelsFormat("@yPoint");}else{curSeries->setPointLabelsFormat("(@xPoint, @yPoint)");} } void MainWindow::on_radioSeriesLabFormat1_clicked() {on_radioSeriesLabFormat0_clicked(); }設置坐標軸
坐標軸分為x軸和y軸,根據QValueAxis獲取x軸或y軸。
坐標軸有兩種網格線,一種是大格子,一種是小格子,小格子為大格子再切分,setTickCount設置大格子條數,setMinorTickCount設置小格子條數。具體案例參考samp9_2
QValueAxis * curAxis; //根據RadioButton選擇的是x軸還是y軸進行設置 void MainWindow::on_radioX_clicked() {//獲取當前坐標軸// 在Qt 5.12.1中編譯時提示 QChart::axisX()和QChart::axisY()函數過時,應使用 QChart::axes()函數// ? if (ui->radioX->isChecked())// ? ? ? curAxis=(QValueAxis*)ui->chartView->chart()->axisX();// ? else// ? ? ? curAxis=(QValueAxis*)ui->chartView->chart()->axisY(); ?// 下面是針對Qt 5.12.1修改的代碼,在Qt5.9.1里編譯也沒問題QList<QAbstractAxis*> axes;if (ui->radioX->isChecked())axes=ui->chartview->chart()->axes(Qt::Horizontal);elseaxes=ui->chartview->chart()->axes(Qt::Vertical);curAxis=(QValueAxis*)axes[0]; ? ?//獲取坐標軸的各種屬性,顯示到界面上ui->spinAxisMin->setValue(curAxis->min());ui->spinAxisMax->setValue(curAxis->max()); ?ui->editAxisTitle->setText(curAxis->titleText());ui->chkBoxAxisTitle->setChecked(curAxis->isTitleVisible()); ?ui->editAxisLabelFormat->setText(curAxis->labelFormat());ui->chkBoxLabelsVisible->setChecked(curAxis->labelsVisible()); ?ui->chkGridLineVisible->setChecked(curAxis->isGridLineVisible());ui->chkAxisLineVisible->setChecked(curAxis->isLineVisible()); ?ui->spinTickCount->setValue(curAxis->tickCount());ui->chkAxisLineVisible->setChecked(curAxis->isLineVisible()); ?ui->spinMinorTickCount->setValue(curAxis->minorTickCount());ui->chkMinorTickVisible->setChecked(curAxis->isMinorGridLineVisible()); } void MainWindow::on_radioY_clicked() {on_radioX_clicked(); } ? //設置坐標軸是否可見 void MainWindow::on_chkBoxVisible_clicked(bool checked) {curAxis->setVisible(checked); } ? //設置坐標軸的范圍 void MainWindow::on_btnSetAxisRange_clicked() {curAxis->setRange(ui->spinAxisMin->value(), ui->spinAxisMax->value()); } ? //設置坐標軸的標題 void MainWindow::on_btnAxisSetTitle_clicked() {curAxis->setTitleText(ui->editAxisTitle->text()); } ? //設置坐標軸標題是否可見 void MainWindow::on_chkBoxAxisTitle_clicked(bool checked) {curAxis->setTitleVisible(checked); } ? //設置軸刻度標簽格式 void MainWindow::on_pushButton_clicked() {curAxis->setLabelFormat(ui->editAxisLabelFormat->text()); } ? //設置軸刻度標簽文字的顏色 void MainWindow::on_btnAxisLabelColor_clicked() {QColor color= curAxis->labelsColor();color = QColorDialog::getColor(color);if (color.isValid())curAxis->setLabelsColor(color); } ? //設置軸刻度標簽文字的字體 void MainWindow::on_btnAxisLabelFont_clicked() {QFont font=curAxis->labelsFont();bool ok=false;font=QFontDialog::getFont(&ok,font);if (ok)curAxis->setLabelsFont(font); } ? //設置軸刻度標簽是否可見 void MainWindow::on_chkBoxLabelsVisible_clicked(bool checked) {curAxis->setLabelsVisible(checked); } ? //設置坐標軸網格線的顏色 void MainWindow::on_btnGridLineColor_clicked() {QColor color = curAxis->gridLineColor();color = QColorDialog::getColor(color);if (color.isValid())curAxis->setGridLineColor(color); } ? //設置坐標軸網格線的pen void MainWindow::on_pushButton_10_clicked() {QPen pen;pen = curAxis->gridLinePen();bool ok=false;pen = DialogPen::getPen(pen,ok);if (ok)curAxis->setGridLinePen(pen); } ? //設置坐標軸大格子豎線的數量 void MainWindow::on_spinTickCount_valueChanged(int arg1) {curAxis->setTickCount(arg1); } ? //設置坐標軸小格子豎線的數量 void MainWindow::on_spinMinorTickCount_valueChanged(int arg1) {curAxis->setMinorTickCount(arg1); } ? //設置坐標軸線是否可見 void MainWindow::on_chkAxisLineVisible_clicked(bool checked) {curAxis->setLineVisible(checked); } ? //設置坐標軸線的pen void MainWindow::on_btnAxisLinePen_clicked() {QPen pen;pen = curAxis->linePen();bool ok = false;pen = DialogPen::getPen(pen, ok);if (ok)curAxis->setLinePen(pen); } ? //設置坐標軸線的顏色 void MainWindow::on_btnAxisLinePenColor_clicked() {QColor color = curAxis->linePenColor();color = QColorDialog::getColor(color);if(color.isValid())curAxis->setLinePenColor(color); } ? //設置坐標軸小格子線是否可見 void MainWindow::on_chkMinorTickVisible_clicked(bool checked) {curAxis->setMinorGridLineVisible(checked); } ? //設置坐標軸小格子線的顏色 void MainWindow::on_btnMinorColor_clicked() {QColor color = curAxis->minorGridLineColor();color = QColorDialog::getColor(color);if(color.isValid())curAxis->setMinorGridLineColor(color); } ? //設置坐標軸小格子線的pen void MainWindow::on_btnMinorPen_clicked() {QPen pen;pen = curAxis->minorGridLinePen();bool ok = false;pen = DialogPen::getPen(pen, ok);if (ok)curAxis->setMinorGridLinePen(pen); } ?常見圖表的繪制
QBarChart
QBarChart為柱狀圖,可以顯示多個柱狀圖,通過QBarSet設置數據,QBarSeries添加QBarSet數據集
通過QStandardItemModel設置數據
//頭文件 #include ? <QStandardItemModel> #include ? <QItemSelectionModel> ? #include ? <QtCharts> ?//必須這么設置 QT_CHARTS_USE_NAMESPACE ? #define ? ? fixedColumnCount ? 5 ? ?//數據模型的列數 #define ? ? iniDataRowCount ? 6 ? //學生個數 ? #define ? ? colNoName ? ? ? 0 ? //姓名的列編號 #define ? ? colNoMath ? ? ? 1 ? //數學的列編號 #define ? ? colNoChinese ? 2 ? //語文的列編號 #define ? ? colNoEnglish ? 3 ? //英語的列編號 #define ? ? colNoAverage ? 4 ? //平均分的列編號QStandardItemModel ?*theModel;//數據模型 ? void ? ?iniData();//初始化數據 void ? ?surveyData();//統計數據 ? void ? ?iniBarChart(); //柱狀圖初始化 void ? ?buildBarChart();//構建柱狀圖 ? //cpp //初始化數據 void MainWindow::iniData() {//為model設置表頭QStringList headerList;headerList<<"姓名"<<"數學"<<"語文"<<"英語"<<"平均分";theModel->setHorizontalHeaderLabels(headerList); ?//為model添加數據for (int i = 0; i < theModel->rowCount(); i++){QString stuName = QString::asprintf("學生%2d", i + 1);QStandardItem * aItem = new QStandardItem(stuName);aItem->setTextAlignment(Qt::AlignHCenter);theModel->setItem(i, colNoName, aItem);qreal avgScore = 0;for (int j = colNoMath; j <= colNoEnglish; j++){qreal score = 50 + qrand() % 50;//隨機生成一個50-99的數aItem = new QStandardItem(QString::asprintf("%.0f", score));aItem->setTextAlignment(Qt::AlignHCenter);theModel->setItem(i, j, aItem);avgScore += score;} ?//求取平均分進行填充aItem = new QStandardItem(QString::asprintf("%.1f", avgScore/3));aItem->setTextAlignment(Qt::AlignHCenter); ?//設置平均分數據不可修改aItem->setFlags(aItem->flags() & !Qt::ItemIsEditable);theModel->setItem(i, colNoAverage, aItem);} } ? //統計數據 void MainWindow::surveyData() {for (int i = colNoMath; i <= colNoAverage; i++){qreal minVal = 100, maxVal = 0, val, sum = 0;int cnt50 = 0, cnt60 =0, cnt70 = 0, cnt80 = 0, cnt90 = 0;for (int j = 0; j < theModel->rowCount(); j++){val = theModel->item(j, i)->text().toDouble();if(val > maxVal) maxVal = val;if(val < minVal) minVal = val; ?if(val < 60) cnt50++;else if(val < 70) cnt60++;else if(val < 80) cnt70++;else if(val < 90) cnt80++;else cnt90++;sum += val;} ?//選擇設計的Qtree只有父節點 所以都是topLevelItemQTreeWidgetItem * aItem = ui->treeWidget->topLevelItem(0);aItem->setTextAlignment(i, Qt::AlignHCenter);aItem->setText(i, QString::number(cnt50)); ?aItem = ui->treeWidget->topLevelItem(1);aItem->setTextAlignment(i, Qt::AlignHCenter);aItem->setText(i, QString::number(cnt60)); ?aItem = ui->treeWidget->topLevelItem(2);aItem->setTextAlignment(i, Qt::AlignHCenter);aItem->setText(i, QString::number(cnt70)); ?aItem = ui->treeWidget->topLevelItem(3);aItem->setTextAlignment(i, Qt::AlignHCenter);aItem->setText(i, QString::number(cnt80)); ?aItem = ui->treeWidget->topLevelItem(4);aItem->setTextAlignment(i, Qt::AlignHCenter);aItem->setText(i, QString::number(cnt90)); ?aItem = ui->treeWidget->topLevelItem(5);aItem->setTextAlignment(i, Qt::AlignHCenter);aItem->setText(i, QString::number(sum / iniDataRowCount)); ?aItem = ui->treeWidget->topLevelItem(6);aItem->setTextAlignment(i, Qt::AlignHCenter);aItem->setText(i, QString::number(maxVal)); ?aItem = ui->treeWidget->topLevelItem(7);aItem->setTextAlignment(i, Qt::AlignHCenter);aItem->setText(i, QString::number(minVal));} } ? //初始化數據 void MainWindow::on_actGenData_triggered() {iniData(); } ? //統計數據 void MainWindow::on_actTongJi_triggered() {surveyData(); }繪制柱狀圖(BarChart)
//初始化柱狀圖 chartViewBar為QChartView控件 void MainWindow::iniBarChart() {QChart * chart = new QChart;chart->setTitle("Barchart演示"); ?//設置動畫效果chart->setAnimationOptions(QChart::SeriesAnimations);ui->chartViewBar->setChart(chart); ?//設置抗鋸齒模式ui->chartViewBar->setRenderHint(QPainter::Antialiasing); } ? //構建柱狀圖 void MainWindow::buildBarChart() {QChart * chart = ui->chartViewBar->chart(); ?//先清除chart,因為經常要刷新,可能會形成多個坐標軸chart->removeAllSeries();if(chart->axisX() != NULL){chart->removeAxis(chart->axisX());chart->removeAxis(chart->axisY());} ?//數據集 QBarSet用于顯示柱狀圖即三門課的成績 QLineSeries用于顯示折線圖即平均分QBarSet * setMath = new QBarSet(theModel->horizontalHeaderItem(colNoMath)->text());QBarSet * setChinese = new QBarSet(theModel->horizontalHeaderItem(colNoChinese)->text());QBarSet * setEnglish = new QBarSet(theModel->horizontalHeaderItem(colNoEnglish)->text());QLineSeries * Line = new QLineSeries; ?//為QLineSeries設置penQPen pen;pen.setColor(Qt::red);pen.setWidth(2);Line->setPen(pen);Line->setName(theModel->horizontalHeaderItem(colNoAverage)->text()); ?//從model從取到數據,為序列添加數據for (int i = 0; i < theModel->rowCount(); i++){setMath->append(theModel->item(i, colNoMath)->text().toInt());setChinese->append(theModel->item(i, colNoChinese)->text().toInt());setEnglish->append(theModel->item(i, colNoEnglish)->text().toInt());Line->append(QPointF(i, theModel->item(i, colNoMath)->text().toFloat()));} ?//序列QBarSeries * seriers = new QBarSeries;seriers->append(setMath);seriers->append(setChinese);seriers->append(setEnglish); ?//為chartview添加序列chart->addSeries(seriers);chart->addSeries(Line); ?//設置坐標軸 QBarCategoryAxis為x軸 QValueAxis為Y軸QStringList categories;for(int i = 0; i < theModel->rowCount(); i++){categories<< theModel->item(i, colNoName)->text();} ?QBarCategoryAxis * axisX = new QBarCategoryAxis;axisX->setCategories(categories);chart->setAxisX(axisX, seriers);chart->setAxisX(axisX, Line); ?QValueAxis * axisY = new QValueAxis;axisY->setRange(0, 100);axisY->setTitleText("分數");chart->setAxisY(axisY, seriers);chart->setAxisY(axisY, Line); ?//設置標簽位于表格下面chart->legend()->setAlignment(Qt::AlignBottom); }繪制餅狀圖(QPieChart)
餅狀圖主要通過QPieSeries來設置數據,chart添加QPieSeries,為餅狀圖添加餅狀塊通過QPieSeries的a QPieSlice *QPieSeries::append(QString label, qreal value) 函數, 繪制餅狀圖時,需要繪制的對象都是一個系列series,使用apppend函數添加,第一個參數是series的名稱,第二個參數是這個系列所占的比例大小float類型
//構建餅圖 void MainWindow::buildPieChart() {QChart * chart = ui->chartViewPie->chart(); ?//先清除chart,因為經常要刷新,可能會形成多個坐標軸chart->removeAllSeries();if(chart->axisX() != NULL){chart->removeAxis(chart->axisX());chart->removeAxis(chart->axisY());} ?//為QpieChart準備數據QPieSeries * seriers = new QPieSeries; ?//設置餅狀圖中間空白圓圈的大小seriers->setHoleSize(ui->spinHoleSize->value()); ?//設置餅狀圖的大小seriers->setPieSize(ui->spinPieSize->value()); ?//獲取CheckBOX選中的科目int colNo = ui->cBoxCourse->currentIndex() + 1;for(int i = 0; i < 5; i++){QTreeWidgetItem * item = ui->treeWidget->topLevelItem(i); ?//繪制餅狀圖時,需要繪制的對象都是一個系列series,使用apppend函數添加,//第一個參數是series的名稱,第二個參數是這個系列所占的比例大小float類型//QPieSeries的append函數相當于就是添加了QPieSlice餅狀塊seriers->append( item->text(0), item->text(colNo).toFloat() );} ?//設置餅狀塊QPieSlice * slice;for (int i =0; i < 5; i++){//獲取分塊slice =seriers->slices().at(i); ?//設置分塊的標簽slice->setLabel(slice->label()+QString::asprintf(": %.0f人, %.1f%%",slice->value(),slice->percentage()*100)); ?//當鼠標略過的時候,顯示突出connect(slice, SIGNAL(hovered(bool)), this, SLOT(on_PieSliceHighlight(bool )));} ?//最后一個設置為explodedslice->setExploded(true); ?//只影響當前的slices,必須添加完slice之后再設置seriers->setLabelsVisible(true); ?//設置標題為當前展示的科目chart->setTitle("PieChart-------" + ui->cBoxCourse->currentText()); ?//為餅狀圖添加序列chart->addSeries(seriers); ?//將標簽放在餅狀圖右邊chart->legend()->setAlignment(Qt::AlignRight); } ? void MainWindow::on_btnDrawPieChart_clicked() {iniPiewChart();buildPieChart(); } ? //當鼠標掠過餅塊時突出顯示 void MainWindow::on_PieSliceHighlight(bool show) {//獲取掠過的餅塊QPieSlice * slice = (QPieSlice*)sender(); ?//設置是否突出顯示slice->setExploded(show); } ? //根據槽函數設置餅狀圖內部圓圈大小 void MainWindow::on_spinHoleSize_valueChanged(double arg1) {QPieSeries * series;series = (QPieSeries *)ui->chartViewPie->chart()->series().at(0);series->setHoleSize(arg1); } ? //根據槽函數設置餅狀圖圓圈大小 void MainWindow::on_spinPieSize_valueChanged(double arg1) {QPieSeries * series;series = (QPieSeries *)ui->chartViewPie->chart()->series().at(0);series->setPieSize(arg1); } ? //根據枚舉量設置主題 void MainWindow::on_cBoxTheme_currentIndexChanged(int index) {ui->chartViewPie->chart()->setTheme(QChart::ChartTheme(index)); }繪制堆積圖(QStackedBar)
堆積圖是指一個柱狀圖里面包括多份數據,可以用來設置一個學生的總分,根據堆積圖可以清晰地看出每個學生的每門科目的分數及總分。
//堆積圖初始化 void MainWindow::iniStackedBar() {QChart * chart = new QChart;chart->setTitle("Stackedchart演示"); ?//設置動畫效果chart->setAnimationOptions(QChart::SeriesAnimations);ui->chartViewStackedBar->setChart(chart); ?//設置抗鋸齒模式ui->chartViewStackedBar->setRenderHint(QPainter::Antialiasing); } ? //構建堆積圖 void MainWindow::buildStackedBar() {QChart * chart = ui->chartViewStackedBar->chart(); ?//先清除chart,因為經常要刷新,可能會形成多個坐標軸chart->removeAllSeries();if(chart->axisX() != NULL){chart->removeAxis(chart->axisX());chart->removeAxis(chart->axisY());} ?//數據集 QBarSet用于顯示柱狀圖即三門課的成績QBarSet * setMath = new QBarSet(theModel->horizontalHeaderItem(colNoMath)->text());QBarSet * setChinese = new QBarSet(theModel->horizontalHeaderItem(colNoChinese)->text());QBarSet * setEnglish = new QBarSet(theModel->horizontalHeaderItem(colNoEnglish)->text()); ?//為堆積圖添加數據集QStringList categories;for(int i = 0; i < theModel->rowCount(); i++){categories << theModel->item(i, colNoName)->text();setMath->append(theModel->item(i, colNoMath)->text().toFloat());setChinese->append(theModel->item(i, colNoChinese)->text().toFloat());setEnglish->append(theModel->item(i, colNoEnglish)->text().toFloat());} ?QStackedBarSeries * series = new QStackedBarSeries;series->append(setMath);series->append(setChinese);series->append(setEnglish); ?//添加坐標軸QBarCategoryAxis * axisX = new QBarCategoryAxis;axisX->append(categories);chart->setAxisX(axisX, series); ?QValueAxis *axisY = new QValueAxis;axisY->setRange(0, 300);axisY->setTitleText("總分");chart->setAxisY(axisY); ? ?//為表格添加序列化chart->addSeries(series); }繪制百分比堆積圖(QPercentBar)
QPercentBar類似于QStackedBar,但是QPercentBar顯示的是各個部分占總部分的百分比。
//初始化 void MainWindow::iniPercentBar() {QChart * chart = new QChart;chart->setTitle("PercentBar演示"); ?//設置動畫效果chart->setAnimationOptions(QChart::SeriesAnimations);ui->chartViewPercentBar->setChart(chart); ?//設置抗鋸齒模式ui->chartViewPercentBar->setRenderHint(QPainter::Antialiasing); } ? //構建圖表 void MainWindow::buildPercentBar() {QChart * chart = ui->chartViewPercentBar->chart(); ?//先清除chart,因為經常要刷新,可能會形成多個坐標軸chart->removeAllSeries();if(chart->axisX() != NULL){chart->removeAxis(chart->axisX());chart->removeAxis(chart->axisY());} ?//數據集 QBarSet用于顯示柱狀圖即三門課的成績QBarSet * setMath = new QBarSet(theModel->horizontalHeaderItem(colNoMath)->text());QBarSet * setChinese = new QBarSet(theModel->horizontalHeaderItem(colNoChinese)->text());QBarSet * setEnglish = new QBarSet(theModel->horizontalHeaderItem(colNoEnglish)->text()); ?//為堆積圖添加數據集QStringList categories;for(int i = 0; i < 5; i++){categories << ui->treeWidget->topLevelItem(i)->text(colNoName);setMath->append(ui->treeWidget->topLevelItem(i)->text(colNoMath).toFloat());setChinese->append(ui->treeWidget->topLevelItem(i)->text(colNoChinese).toFloat());setEnglish->append(ui->treeWidget->topLevelItem(i)->text(colNoEnglish).toFloat());} ?QStackedBarSeries * series = new QStackedBarSeries;series->append(setMath);series->append(setChinese);series->append(setEnglish); ?//添加坐標軸QBarCategoryAxis * axisX = new QBarCategoryAxis;axisX->append(categories);chart->setAxisX(axisX, series); ?QValueAxis *axisY = new QValueAxis;axisY->setRange(0, 100);axisY->setTitleText("分數");chart->setAxisY(axisY); ? ?//為表格添加序列化chart->addSeries(series); }繪制散點圖(Scatterchart)
散點采用QScatterSeries,可以對散點大小及樣式進行設置,使用append進行添加點,表格addSeries將序列加入。
//初始化 void MainWindow::iniScatterChart() {QChart * chart = new QChart;chart->setTitle("ScatterChart演示"); ?//設置動畫效果chart->setAnimationOptions(QChart::SeriesAnimations);ui->chartViewStackedBar->setChart(chart); ?//設置抗鋸齒模式ui->chartViewStackedBar->setRenderHint(QPainter::Antialiasing); } ? //構建圖表 void MainWindow::buildScatterChart() {//獲取ScatterChart指針QChart * chart = ui->chartViewScatter->chart(); ?//清除之前的序列chart->removeAllSeries(); ?//防止出現多個坐標軸if(chart->axisX() != NULL){chart->removeAxis(chart->axisX());chart->removeAxis(chart->axisY());} ?//設置線的樣式QSplineSeries * seriesLine = new QSplineSeries;seriesLine->setName("spline");QPen pen;pen.setWidth(2);pen.setColor(Qt::red);seriesLine->setPen(pen); ?//設置散點的樣式QScatterSeries * series0 = new QScatterSeries;series0->setName("散點");series0->setMarkerShape(QScatterSeries::MarkerShapeCircle);series0->setBorderColor(Qt::black);series0->setBrush(Qt::blue); ?//設置大小series0->setMarkerSize(12); ?//添加數據for(int i = 0; i < 10; i++){int x = qrand() % 20;int y = qrand() % 20;series0->append(x, y);seriesLine->append(x, y);} ?//為表格添加序列chart->addSeries(series0);chart->addSeries(seriesLine); ?//創建默認坐標軸chart->createDefaultAxes();chart->axisX()->setTitleText("X軸");chart->axisX()->setRange(-2, 22);chart->axisY()->setTitleText("Y軸");chart->axisY()->setRange(-2, 22); }總結
- 上一篇: 文件下载协议 HTTP、FTP、P2P
- 下一篇: 计算机ab级考试试题真题,全国计算机一级