一、简介
QTableWidget是QT对话框设计中常用的显示数据表格的控件,QTableWidget单元格数据是QTableWidgetItem对象来实现的,整个表格都需要用逐个单元格对象QTableWidgetItem构建起来。
二、详解
1、代码
(1)table.h
#ifndef TABLE_H
#define TABLE_H
#include <QtGui>
class Table : public QTableWidget
{
Q_OBJECT
public:
Table(QWidget *parent = 0);
~Table();
void setColumnValue(const int &columnSum, const QStringList &header); //set header value
void setHeaderWidth(const int &index, const int &width); //set header and column widhth for each index
void setHeaderHeight(const int &height); //set header height
void addRowValue(const int &height, const QStringList &value, const QIcon &fileIcon);
void setRowH(const int &index, const int &height);
void setItemFixed(bool flag);
bool getSelectedRow(QList<int> &rowList);
protected:
void contextMenuEvent(QContextMenuEvent *event);
QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers);
void keyPressEvent(QKeyEvent *event);
private:
void createActions();
private slots:
void slotItemEntered(QTableWidgetItem *item);
void slotActionRename();
void slotItemSelectionChanged();
private:
int tableWidth;
int tableHeight;
QList<int>rowHeghtList;
QList<int>rowWidthList;
QMenu *popMenu;
QAction *actionName;
QAction *actionSize;
QAction *actionType;
QAction *actionDate;
QAction *actionOpen;
QAction *actionDownload;
QAction *actionFlush;
QAction *actionDelete;
QAction *actionRename;
QAction *actionCreateFolder;
QTableWidgetItem *rightClickedItem;
QMap<QTableWidgetItem *, QString>fileMap;
bool dupFlag;
};
// custom item delegate class
class NoFocusDelegate : public QStyledItemDelegate
{
protected:
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
};
#endif // TABLE_H
(2)table.cpp
#include "table.h"
Table::Table(QWidget *parent)
: QTableWidget(parent)
, rightClickedItem(NULL)
, dupFlag(false)
{
rowHeghtList.clear();
rowWidthList.clear();
fileMap.clear();
this->setMouseTracking(true);
//setWindowTitle(tr("table"));
horizontalHeader()->setDefaultSectionSize(100);
verticalHeader()->setDefaultSectionSize(30); //设置默认行高
tableWidth = 100;
tableHeight = 30;
horizontalHeader()->setClickable(false); //设置表头不可点击(默认点击后进行排序
QFont font = horizontalHeader()->font(); //设置表头字体加粗
font.setBold(true);
horizontalHeader()->setFont(font);
horizontalHeader()->setStretchLastSection(true); //设置充满表宽度
horizontalHeader()->setMovable(false); //表头左右互换
//verticalHeader()->setResizeMode(QHeaderView::ResizeToContents);
setFrameShape(QFrame::NoFrame); //设置无边框
//setShowGrid(false); //设置不显示格子线
verticalHeader()->setVisible(false); //设置垂直头不可见
setSelectionMode(QAbstractItemView::ExtendedSelection); //可多选(Ctrl、Shift、 Ctrl+A都可以)
setSelectionBehavior(QAbstractItemView::SelectRows); //设置选择行为时每次选择一行
setEditTriggers(QAbstractItemView::NoEditTriggers); //设置不可编辑
setStyleSheet("selection-background-color:lightblue;"); //设置选中背景色
//horizontalHeader()->setStyleSheet("QHeaderView::section{background:skyblue;}"); //设置表头背景色
//setStyleSheet("background: rgb(56,56,56);alternate-background-color:rgb(48,51,55);selection-background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(56,56,56),stop:1 rgb(76,76,76));"); //设置选中背景色
horizontalHeader()->setStyleSheet("QHeaderView::section{background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(134, 245, 99, 255),stop:0.5 rgba(134, 148, 99, 255),stop:1 rgba(115, 87, 128, 255));color:rgb(25, 70, 100);padding-left: 1px;border: 1px solid #FFFF00;}"); //设置表头背景色
setAlternatingRowColors(true);
//setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
//setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
//设置水平、垂直滚动条样式
horizontalScrollBar()->setStyleSheet("QScrollBar{background:transparent; height:12px;}"
"QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}"
"QScrollBar::handle:hover{background:gray;}"
"QScrollBar::sub-line{background:transparent;}"
"QScrollBar::add-line{background:transparent;}");
verticalScrollBar()->setStyleSheet("QScrollBar{background:transparent; width:12px;}"
"QScrollBar::handle{background:lightgray; border:2px solid transparent; border-radius:5px;}"
"QScrollBar::handle:hover{background:gray;}"
"QScrollBar::sub-line{background:transparent;}"
"QScrollBar::add-line{background:transparent;}");
// set the item delegate to your table widget
setItemDelegate(new NoFocusDelegate()); //虚线边框去除
//setFocusPolicy(Qt::NoFocus); //去除选中虚线框
horizontalHeader()->setHighlightSections(false); //点击表时不对表头行光亮(获取焦点)
createActions();
setItemFixed(false);
connect(this, SIGNAL(itemEntered(QTableWidgetItem*)), this , SLOT(slotItemEntered(QTableWidgetItem*)));
connect(this, SIGNAL(itemSelectionChanged()), this , SLOT(slotItemSelectionChanged()));
//this->resize(600, 600);
}
Table::~Table()
{
}
void Table::setColumnValue(const int &columnSum, const QStringList &header)
{
setColumnCount(columnSum); //设置列数
this->setHorizontalHeaderLabels(header); //设置列的标签
}
void Table::setHeaderWidth(const int &index, const int &width)
{
horizontalHeader()->resizeSection(index,width);
if (rowWidthList.count() <= index + 1) {
rowWidthList.append(width);
}
else {
rowWidthList[index+1] = width;
}
tableWidth = 0;
for(int index = 0; index < rowWidthList.count(); index++)
tableWidth += rowWidthList.at(index);
resize(tableWidth, tableHeight);
}
void Table::setHeaderHeight(const int &height)
{
horizontalHeader()->setFixedHeight(height); //设置表头的高度
if (rowHeghtList.isEmpty()) {
rowHeghtList.append(height);
}
else {
rowHeghtList[0] = height;
}
tableHeight = 0;
for(int index = 0; index < rowHeghtList.count(); index++)
tableHeight += rowHeghtList.at(index);
resize(tableWidth, tableHeight);
}
void Table::addRowValue(const int &height, const QStringList &value, const QIcon &fileIcon)
{
int row_count = rowCount(); //获取表单行数
insertRow(row_count); //插入新行
setRowHeight(row_count, height);
for (int index = 0; index < columnCount(); index++) {
QTableWidgetItem *item = new QTableWidgetItem;
if (index == 0) {
item->setIcon(fileIcon);
item->setTextAlignment(Qt::AlignVCenter | Qt::AlignLeft);
fileMap.insert(item, value.at(index));
}
else {
item->setTextAlignment(Qt::AlignCenter);
}
item->setText(value.at(index));
setItem(row_count, index, item);
}
rowHeghtList.append(height);
tableHeight += height;
resize(tableWidth, tableHeight);
}
void NoFocusDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
{
QStyleOptionViewItem itemOption(option);
if (itemOption.state & QStyle::State_HasFocus)
itemOption.state = itemOption.state ^ QStyle::State_HasFocus;
QStyledItemDelegate::paint(painter, itemOption, index);
}
void Table::setRowH(const int &index, const int &height)
{
setRowHeight(index, height);
if (rowHeghtList.count() <= index + 1) {
rowHeghtList.append(height);
}
else {
rowHeghtList[index+1] = height;
}
tableHeight = 0;
for(int index = 0; index < rowHeghtList.count(); index++)
tableHeight += rowHeghtList.at(index);
resize(tableWidth, tableHeight);
}
void Table::createActions()
{
popMenu = new QMenu();
actionName = new QAction(this);
actionSize = new QAction(this);
actionType = new QAction(this);
actionDate = new QAction(this);
actionOpen = new QAction(this);
actionDownload = new QAction(this);
actionFlush = new QAction(this);
actionDelete = new QAction(this);
actionRename = new QAction(this);
actionCreateFolder = new QAction(this);
actionOpen->setText(tr("打开"));
actionDownload->setText(tr("下载"));
actionFlush->setText(tr("刷新"));
actionDelete->setText(tr("删除"));
actionRename->setText(tr("重命名"));
actionCreateFolder->setText(tr("新建文件夹"));
actionName->setText(tr("名称"));
actionSize->setText(tr("大小"));
actionType->setText(tr("项目类型"));
actionDate->setText(tr("修改日期"));
actionFlush->setShortcut(QKeySequence::Refresh);
connect(actionRename, SIGNAL(triggered()), this, SLOT(slotActionRename()));
}
void Table::contextMenuEvent(QContextMenuEvent *event)
{
popMenu->clear();
QPoint point = event->pos();
rightClickedItem = this->itemAt(point);
if(rightClickedItem != NULL) {
popMenu->addAction(actionDownload);
popMenu->addAction(actionFlush);
popMenu->addSeparator();
popMenu->addAction(actionDelete);
popMenu->addAction(actionRename);
popMenu->addSeparator();
popMenu->addAction(actionCreateFolder);
QMenu *sortStyle = popMenu->addMenu(tr("排序"));
sortStyle->addAction(actionName);
sortStyle->addAction(actionSize);
sortStyle->addAction(actionType);
sortStyle->addAction(actionDate);
popMenu->exec(QCursor::pos());
event->accept();
}
}
QModelIndex Table::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
{
//重写移动光标事件,当存在编辑项的时候,让光标永远位于当前项(编辑项),否则返回父类
if(rightClickedItem && rightClickedItem->row() >= 0) {
return currentIndex();
}
else {
return QTableWidget::moveCursor(cursorAction, modifiers);
}
}
void Table::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
QTableWidgetItem *item = currentItem();
if (item) {
closePersistentEditor(item);
openPersistentEditor(item);
slotItemSelectionChanged();
dupFlag = false;
}
}
}
void Table::slotItemSelectionChanged()
{
//关闭编辑项
if (rightClickedItem && dupFlag == false) {
int editRow = rightClickedItem->row();
QTableWidgetItem *item = this->item(editRow, 0);
QMap<QTableWidgetItem *, QString>::iterator it;
for (it = fileMap.begin(); it != fileMap.end(); ++it) {
if (it.key() != item) {
if (it.value() == item->text()) {
dupFlag = true;
}
}
}
if (dupFlag == false) {
this->closePersistentEditor(item);
rightClickedItem = NULL;
}
else {
QMessageBox::critical(this,tr("错误提示"),tr("文件重名"), tr("确定"));
setCurrentItem(item);
}
}
else {
dupFlag = false;
}
}
void Table::setItemFixed(bool flag)
{
if (flag == true)
horizontalHeader()->setResizeMode(QHeaderView::Fixed);
else
horizontalHeader()->setResizeMode(QHeaderView::Interactive);
}
bool Table::getSelectedRow(QList<int> &rowList)
{
//多选并获取所选行
QList<QTableWidgetItem *> items = this->selectedItems();
int itemCount = items.count();
if(itemCount <= 0) {
return false;
}
for (int index = 0; index < itemCount; index++) {
int itemRow = this->row(items.at(index));
rowList.append(itemRow);
}
return true;
}
void Table::slotItemEntered(QTableWidgetItem *item)
{
if(!item)
return;
QString name = item->text();
if (name.isEmpty())
return;
QToolTip::showText(QCursor::pos(), name);
}
void Table::slotActionRename()
{
//获得当前节点并获取编辑名称
if (rightClickedItem) {
int editRow = rightClickedItem->row();
QTableWidgetItem *item = this->item(editRow, 0); //编辑的行号及第一列
this->setCurrentCell(editRow, 0);
this->openPersistentEditor(item); //打开编辑项
this->editItem(item);
}
}
(3)tablewidget.h
#ifndef TABLEWIDGET_H
#define TABLEWIDGET_H
#include "table.h"
class TableWidget : public QWidget
{
Q_OBJECT
public:
TableWidget(QWidget *parent = 0);
~TableWidget();
private:
bool ScanFile(const QString & path);
private:
Table *table;
};
#endif // TABLEWIDGET_H
(4)tablewidget.cpp
#include "tablewidget.h"
TableWidget::TableWidget(QWidget *parent)
: QWidget(parent)
{
QTextCodec*codec = QTextCodec::codecForName("utf8");
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);
setWindowTitle(tr("文件浏览"));
table = new Table(this);
QStringList header;
header<<tr("文件名")<<tr("最后更改日期")<<tr("类型")<<tr("大小");
table->setColumnValue(4, header);
table->setHeaderWidth(0, 200);
table->setHeaderWidth(1, 150);
table->setHeaderWidth(2, 100);
table->setHeaderWidth(3, 100);
table->setHeaderHeight(30);
//table->setRowH(0, 200);
ScanFile(QApplication::applicationDirPath());
// table->setRowHeight(46);
resize(800, 800);
}
TableWidget::~TableWidget()
{
}
//Qt实现遍历文件夹和文件目录
bool TableWidget::ScanFile(const QString &path)
{
QDir dir(path);
if (!dir.exists())
return false;
// dir.setFilter(QDir::Dirs | QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot);
// QFileInfoList list = dir.entryInfoList();
// //QStringList list = dir.entryList();
// for(int index = 0; index < list.count(); index++) {
// QFileInfo fileInfo = list.at(index);
// if (fileInfo.isDir()) {
// ScanFile(fileInfo.filePath());
// }
// else {
// qDebug() << "----------" << fileInfo.absoluteFilePath();
// }
// }
QDirIterator dirIterator(path, QDir::Dirs | QDir::Files | QDir::NoSymLinks| QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
while(dirIterator.hasNext()) {
dirIterator.next();
QFileInfo fileInfo = dirIterator.fileInfo();
QString filePath = fileInfo.absoluteFilePath();
QFileIconProvider iconProvider;
QIcon icon;
if (fileInfo.isDir()) { //获取指定文件图标
icon = iconProvider.icon(QFileIconProvider::Folder);
}
else {
icon = iconProvider.icon(fileInfo);
}
QFileIconProvider icon_provider;
QString typeFile = icon_provider.type(fileInfo);
table->addRowValue(30, QStringList()<< filePath <<fileInfo.lastModified().toString("yyyy-MM-dd hh:mm:ss")
<<typeFile<<QString::number(fileInfo.size()/1024.0, 'f', 2)+"KB", icon);
}
return true;
}
(5)main.cpp
#include "tablewidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TableWidget w;
w.show();
return a.exec();
}
(6)运行结果
(7)总结
根据网上博客修改了:鼠标点击的选项会出现虚框、创建右键菜单、获取文件图标类型、右键编辑时Tab键的处理和重命名文件重名后表格更新的、递归扫描文件夹。
2、QTableWidget控件属性
一、禁止编辑表格
在默认情况下,表格里的字符是可以更改的。
比如双击一个单元格,就可以修改原来的内容,如果想禁止用户的这种操作,让这个表格对用户只读,可以这样:
ui.qtablewidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
二、设置表格为选择整行
/*设置表格为整行选中*/
ui.qtablewidget->setSelectionBehavior(QAbstractItemView::SelectRows);
三、设置单个选中和多个选中
单个选中意味着每次只可以选中一个单元格,多个就是相当于可以选择”一片“那种模式。
/*设置允许多个选中*/
ui.qtablewidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
四、表格表头的显示与隐藏
对于水平或垂直方向的表头,如果不想显示可以用以下方式进行(隐藏/显示)设置:
ui.qtablewidget->verticalHeader()->setVisible(true);
ui.qtablewidget->horizontalHeader()->setVisible(false);
五、设置具体单元格中字体的对齐方式
ui.qtablewidget->item(0, 0)->setTextAlignment(Qt::AlignHCenter);
六、设置具体单元格中字体格式
ui.qtablewidget->item(1, 0)->setBackgroundColor(QColor(0,60,10));
ui.qtablewidget->item(1, 0)->setTextColor(QColor(200,111,100));
ui.qtablewidget->item(1, 0)->setFont(QFont("Helvetica"));
七、设置具体单元格的值
ui.qtablewidget->setItem(1, 0, new QTableWidgetItem(str));
八、把QTableWidgetItem对象内容转换为QString
QString str =ui.qtablewidget->item(0, 0)->data(Qt::DisplayRole).toString();
九、具体单元格中添加控件
QComboBox *comBox = new QComboBox();
comBox->addItem("F");
comBox->addItem("M");
ui.qtablewidget->setCellWidget(0,3,comBox);
十、合并单元格
//合并单元格的效果
ui.qtablewidget->setSpan(2, 2, 3, 2);
//第一个参数:要改变的单元格行数
//第二个参数:要改变的单元格列数
//第三个参数:需要合并的行数
//第四个参数:需要合并的列数
十一、具体单元格中插入图片
ui.qtablewidget->setItem(3, 2, new QTableWidgetItem(QIcon("images/music.png"), "Music"));
十二、设置显示网格
ui.qtablewidget->setShowGrid(true);//显示表格线
十三、设置滚动条
ui.qtablewidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//去掉水平滚动条
十四、设置列标签
//初始化界面
QStringList HStrList;
HStrList.push_back(QString("name"));
HStrList.push_back(QString("id"));
HStrList.push_back(QString("age"));
HStrList.push_back(QString("sex"));
HStrList.push_back(QString("department"));
//设置行列数(只有列存在的前提下,才可以设置列标签)
int HlableCnt = HStrList.count();
ui.qtablewidget->setRowCount(10);
ui.qtablewidget->setColumnCount(HlableCnt);
//设置列标签
ui.qtablewidget->setHorizontalHeaderLabels(HStrList);
十五、设置行和列的大小设为与内容相匹配
ui.qtablewidget->resizeColumnsToContents();
ui.qtablewidget->resizeRowsToContents();
十六、设置字体
ui.qtablewidget->setFont(font); //设置字体
十七、获取某一单元格的内容
QString strText = ui.qtablewidget->item(0, 0)->text();
3、QTableWidget美化
QSS样式表(根据需求修改颜色):
QTableWidget
{
background: rgb(56,56,56);
alternate-background-color:rgb(48,51,55);
selection-background-color:qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(56,56,56),stop:1 rgb(66,66,66));
}
QHeaderView::section
{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(46,46,46),stop:1 rgb(56,56,56));
color: rgb(210,210,210);
padding-left: 4px;border: 1px solid #383838;
}
QScrollBar:vertical
{
border: 0px solid grey;
background: transparent;
width: 15px;
margin: 22px 0 22px 0;
}
QScrollBar::handle:vertical
{
background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgb(46,46,46),stop:1 rgb(66,66,66));
min-height: 20px;
}
QScrollBar::add-line:vertical
{
border: 0px solid grey;
background: rgb(66,66,66);
height: 20px;
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::sub-line:vertical
{
border: 0px solid grey;
background: rgb(56,56,56);
height: 20px;
subcontrol-position: top;
subcontrol-origin: margin;
}
QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical
{
border: 0px solid grey;
width: 3px;
height: 3px;
background: rgb(46,46,46);
}
QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
{
background: none;
}