【3】QT視圖和委托

按照本次的學習計劃來總結一下今天所學習的一些內容,仍然依據豆子博主所寫的關于QT文章進行學習,打算把這個看完之后,再看一下《Qt Quick 核心編程》,學習完之后再進行一個項目制作,然后就結束本次的學習計劃。總結的內容一般都是發送出本次學習所用到的完整代碼,然后添加自己所遇到的一些問題。

QFileSystemModel
//filesystemwidget.h
#ifndef FILESYSTEMWIDGET_H
#define FILESYSTEMWIDGET_H
#include <QDialog>
#include <QFileSystemModel>
#include <QTreeView>
#include <QPushButton>
#include <QLayout>
#include <QWidget>
#include <QInputDialog>
#include <QMessageBox>
#include <QHeaderView>

class FileSystemWidget:public QDialog
{
 Q_OBJECT
public:
 FileSystemWidget(QWidget *parent=0);

private:
 QFileSystemModel *model;
 QTreeView *treeView;
private slots:
 void mkdir();
 void rm();
};

#endif // FILESYSTEMWIDGET_H
//filesystemwidget.cpp
#include "filesystemwidget.h"

FileSystemWidget::FileSystemWidget(QWidget *parent):QDialog(parent)
{
 model=new QFileSystemModel;
 model->setRootPath(QDir::currentPath());

 treeView=new QTreeView(this);
 treeView->setModel(model);
 treeView->setRootIndex(model->index(QDir::currentPath()));

 //設置列頭,行頭
 treeView->setSortingEnabled(true);//直接加上這個就可以排序了

 QPushButton *mkdirButton=new QPushButton(tr("Make Directory..."),this);
 QPushButton *rmButton = new QPushButton(tr("Remove"),this);
 QHBoxLayout *buttonLayout =new QHBoxLayout;
 buttonLayout->addWidget(mkdirButton);
 buttonLayout->addWidget(rmButton);

 QVBoxLayout *layout=new QVBoxLayout;
 layout->addWidget(treeView);
 layout->addLayout(buttonLayout);

 setLayout(layout);
 setWindowTitle("File System Model");

 connect(mkdirButton,SIGNAL(clicked()),this,SLOT(mkdir()));
 connect(rmButton,SIGNAL(clicked()),this,SLOT(rm()));
}

//創建文件夾
void FileSystemWidget::mkdir()
{
 QModelIndex index=treeView->currentIndex();

 //IsValid即實例變量的值是否是個有效的對象句柄。
 if(!index.isValid()){
 return;
 }
 QString dirName=QInputDialog::getText(this,tr("Create Directory"),tr("Directory name"));

 if(!dirName.isEmpty()){
 if(!model->mkdir(index,dirName).isValid()){
 QMessageBox::information(this,tr("Create Directory"),tr("Failed to create the directory"));
 }
 }
}

//刪除文件
void FileSystemWidget::rm()
{
 QModelIndex index=treeView->currentIndex();
 if(!index.isValid()){
 return;
 }
 bool ok;
 if(model->fileInfo(index).isDir()){
 ok=model->rmdir(index);
 }else{
 ok=model->remove(index);
 }
 if(!ok){
 //arg函數用于替換%1
 QMessageBox::information(this,tr("remove"),tr("Failed to remove %1").arg(model->fileName(index)));
 }
}
//main.cpp
#include "filesystemwidget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
 QApplication a(argc, argv);

 FileSystemWidget w;
 w.show();

 return a.exec();
}
#QtfileSystemmodel.pro
QT += core gui

greaterThan(QT_MAJOR_VERSION,4): QT += widgets

TARGET = QtfileSystemmodel
TEMPLATE = app

SOURCES += main.cpp \
 filesystemwidget.cpp

HEADERS += \
 filesystemwidget.h

備注:為什么把pro文件發送出來呢?因為本次代碼我創建的是控制臺應用程序,那么想要運行出窗口就需要改一下這個pro文件,主要是添加gui和widgets。上午代碼總是運行不了,花了好長時間,才發現是QApplication沒有改過來,控制臺程序下它是QCoreApplication,這個我找了半天,太尷尬了。

視圖和委托
//listview.h
#ifndef LISTVIEW_H
#define LISTVIEW_H
#include <QStringList>
#include <QStringListModel>
#include <QListView>
#include <QPushButton>
#include <QLayout>
#include <QDialog>

class ListView:public QDialog
{
 Q_OBJECT
public:
 ListView();

private:
 QStringListModel *model;
 QListView *listView;

private slots:
 void showModel();
};

#endif // LISTVIEW_H
//spinboxdelegate.h
#ifndef SPINBOXDELEGATE_H
#define SPINBOXDELEGATE_H

#include <QStyledItemDelegate>

class SpinBoxDelegate:public QStyledItemDelegate
{
public:
 SpinBoxDelegate(QObject *parent=0):QStyledItemDelegate(parent){}

 //createEditor():返回一個組件。該組件會被作為用戶編輯數據時所使用的編輯器,從模型中接受數據,返回用戶返回的數據
 QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index) const;

 //setEditorData():提供上述組建在顯示時所需要的默認值
 void setEditorData(QWidget *editor,const QModelIndex &index)const;
 //返回給模型用戶修改過的數據
 void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index) const;
 //確保上述組件作為編輯器是能夠完整地顯示出來。
 void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index) const;
};

#endif // SPINBOXDELEGATE_H
//listview.cpp
#include "listview.h"
#include "spinboxdelegate.h"

ListView::ListView():QDialog()
{
 QStringList data;
 data<<"0"<<"1"<<"2";
 model=new QStringListModel();
 model->setStringList(data);

 listView=new QListView();
 listView->setModel(model);
 //使用委托
 listView->setItemDelegate(new SpinBoxDelegate(listView));

 QPushButton *btnShow=new QPushButton(tr("Show Model"));
 connect(btnShow,SIGNAL(clicked()),this,SLOT(showModel()));

 QHBoxLayout *buttonLayout=new QHBoxLayout;
 buttonLayout->addWidget(btnShow);

 QVBoxLayout *layout=new QVBoxLayout;
 layout->addWidget(listView);
 layout->addLayout(buttonLayout);

 setLayout(layout);
}

void ListView::showModel()
{

}
//spinboxdelegate.cpp
#include "spinboxdelegate.h"
#include <QSpinBox>

QWidget *SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
{
 QSpinBox *editor=new QSpinBox(parent);
 editor->setMinimum(0);
 editor->setMaximum(100);
 return editor;
}

void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
 int value=index.model()->data(index,Qt::EditRole).toInt();
 //static_cast<type-id>(expression)該運算符把expression轉換為type-id類型,但沒有運行時類型檢查來保證轉換的安全性。
 QSpinBox *spinBox=static_cast<QSpinBox*>(editor);
 spinBox->setValue(value);
}

void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
 QSpinBox *spinBox=static_cast<QSpinBox*>(editor);
 spinBox->interpretText();
 int value=spinBox->value();
 model->setData(index,value,Qt::EditRole);
}

void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
 editor->setGeometry(option.rect);
}
//main.cpp
#include <QApplication>
#include "listview.h"

int main(int argc, char *argv[])
{
 QApplication a(argc, argv);
 ListView w;
 w.show();
 return a.exec();
}

備注:在 model/view 架構中,視圖是數據從模型到最終用戶的途徑。數據通過視圖向用戶進行顯示。
委托供視圖實現某種高級的編輯功能。
委托的接口由QAbstractItemDelegate定義。在這個類中,委托通過paint()
和sizeHint()兩個函數渲染用戶內容(也就是說,你必須自己將渲染器繪制出來)。為使用方便,從 4.4 開始,Qt 提供了另外的基于組件的子類:QItemDelegate和QStyledItemDelegate,默認的委托是QStyledItemDelegate。

視圖選擇
//main.cpp
#include <QApplication>
#include <QTableWidget>

int main(int argc, char *argv[])
{
 QApplication a(argc, argv);

 QTableWidget *tableWidget=new QTableWidget(8,4);

 //選擇單元格
 QItemSelectionModel *selectionModel=tableWidget->selectionModel();
 QModelIndex topLeft=tableWidget->model()->index(0,0,QModelIndex());
 QModelIndex bottomRight=tableWidget->model()->index(5,2,QModelIndex());
 //設為選區
 QItemSelection selection(topLeft,bottomRight);
 //select()函數的第一個參數就是需要選擇的選區,第二個參數是選區的標  志位。
 selectionModel->select(selection,QItemSelectionModel::Select);

 //獲得選區
 QModelIndexList indexes=selectionModel->selectedIndexes();
 QModelIndex index;

 foreach (index, indexes) {
 QString text=QString("(%1,%2)").arg(index.row()).arg(index.column());
 //model->setData(index,text);
 }

 QItemSelection toggleSelection;

 topLeft=tableWidget->model()->index(2,1,QModelIndex());
 bottomRight=tableWidget->model()->index(7,3,QModelIndex());
 toggleSelection.select(topLeft,bottomRight);

 //對前面的取反操作
 selectionModel->select(toggleSelection,QItemSelectionModel::Toggle);

 QItemSelection columnSelection;

 topLeft=tableWidget->model()->index(0,1,QModelIndex());
 bottomRight=tableWidget->model()->index(0,2,QModelIndex());
 columnSelection.select(topLeft,bottomRight);
 //整列選取
 selectionModel->select(columnSelection,QItemSelectionModel::Select | QItemSelectionModel::Columns);

 QItemSelection rowSelection;
 topLeft=tableWidget->model()->index(0,0,QModelIndex());
 bottomRight=tableWidget->model()->index(1,0,QModelIndex());
 rowSelection.select(topLeft,bottomRight);

 //整行選取
 selectionModel->select(rowSelection,QItemSelectionModel::Select | QItemSelectionModel::Rows);

 tableWidget->show();
 return a.exec();
}

備注:QT中使用QItemSelectionModel類獲取視圖中項目的選擇情況。如果需要創建一個選區,我們需要指定一個模型以及一對索引,使用這些數據創建一個QItemSelection對象。

今天的學習也就到這里就結束了,天氣寒冷都不想起床了,為早起的人兒致敬……

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容