含义:停靠区窗口,和状态栏、标题栏是一个等级
属性:
setAllowedAreas(Qt::DockWidgetAreas areas)
setFeatures(DockWidgetFeatures features)
含义:目录树
属性:
Columns页用于设计目录树的列,目录树可以有多个列。在设计器里可以添加、删除、移动列,设置列的文字、字体、前景色、背景色、文字对齐方式、图标等。
Items页面用于设计目录树的节点,可对每个节点设置属性,如文字、字体、图标等,特别是fags属性,可以设置节点是否可选、是否可编辑、是否有CheckBox等,还可以设置节点的CheckState。
private:
// 创建节点时用作type参数,自定义类型必须大于1000
enum treeItemType{
itTopItem = 1001,
itGroupItem,
itImageItem
};
enum treeColNum{
colItem=0,
colItemType=1
};
QLabel *LabFileName;// 显示状态栏文件名称
QPixmap curPixmap; // 当前图片
float pixRatio; // 当前图片比例
// 初始化目录树
void initTree();
void addFolderItem(QTreeWidgetItem *parItem,QString dirName); // 添加目录
QString getFinalFolderName(const QString &fullPathName); // 提取目录名称
void addImageItem(QTreeWidgetItem *parItem,QString aFilename); // 添加图片
void displayImage(QTreeWidgetItem *item); // 显示一个图片节点的图片
void changeItemCaption(QTreeWidgetItem *item); // 遍历改变节点标题
添加顶层节点
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 状态栏显示文件名
LabFileName = new QLabel("");
ui->statusBar->addWidget(LabFileName);
// 设置中心窗体
this->setCentralWidget(ui->scrollArea);
// 初始化目录树
initTree();
}
void MainWindow::initTree()
{
QString dataStr = "";
ui->treeWidget->clear(); // 清空目录树
QIcon icon;
icon.addFile(":/icons/icons/15.ico");
QTreeWidgetItem *item = new QTreeWidgetItem(MainWindow::itTopItem); //?
item->setIcon(MainWindow::colItem,icon); // 第一列图标
item->setText(MainWindow::colItem,"图片文件"); // 第一列文字
item->setText(MainWindow::colItemType,"type=itTopItem"); // 第二列文字
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsAutoTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
item->setCheckState(colItem,Qt::Checked); // 第一列勾选
item->setData(MainWindow::colItem,Qt::UserRole,QVariant(dataStr)); //?
ui->treeWidget->addTopLevelItem(item);// 添加顶层节点
}
void() TreeWidgetItem::setData(int column,int role,const QVariant &value)
如
item->setData(MainWindow:colItem,Qt::UserRole,QVariant (datastr));
它为节点的第1列,角色Qt:UserRole,设置了一个字符串数据dataStr.Qt:UserRole是枚举类型Qt:ItemDataRole中一个预定义的值。
定义3个函数
// 获取文件名称
QString MainWindow::getFinalFolderName(const QString &fullPathName)
{
return fullPathName.right(fullPathName.length()-fullPathName.lastIndexOf("/")-1);
}
// 添加节点函数
void MainWindow::addFolderItem(QTreeWidgetItem *parItem, QString dirName)
{
QIcon icon(":/icons/icons/open3.bmp");
QString NodeText = getFinalFolderName(dirName);
QTreeWidgetItem *item = new QTreeWidgetItem(MainWindow::itGroupItem); // 传入目录的节点类型type值1001
item->setIcon(colItem,icon);
item->setText(colItem,NodeText);
item->setText(colItemType,"type:itGroupItem");
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsAutoTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
item->setCheckState(colItem,Qt::Checked);
item->setData(colItem,Qt::UserRole,QVariant(dirName));
parItem->addChild(item); // 在父节点添加子节点
}
// action关联函数
void MainWindow::on_actAddFolder_triggered()
{
QString fullname = QFileDialog::getExistingDirectory();
if(!fullname.isEmpty()){
QTreeWidgetItem *parItem = ui->treeWidget->currentItem();
if(parItem){
addFolderItem(parItem,fullname);
}else {
// 创建弹窗
QMessageBox::critical(this, tr("危险弹窗"), tr("请选择目标节点"),QMessageBox::Save | QMessageBox::Discard, QMessageBox::Discard);
}
}
else {
return;
}
}
QFileDialog::getOpenFileNames函数可以实现添加多个文件
实现:
void MainWindow::addImageItem(QTreeWidgetItem *parItem, QString aFilename)
{
QIcon icon(":/icons/icons/31.ico");
QString NodeText = getFinalFolderName(aFilename);
QTreeWidgetItem *item;
item = new QTreeWidgetItem(MainWindow::itImageItem);
item->setIcon(colItem,icon);
item->setText(colItem,NodeText);
item->setText(colItemType,"type=itImageItem");
item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsAutoTristate | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
item->setData(colItem,Qt::UserRole,QVariant(aFilename));
parItem->addChild(item); // 在父节点添加子节点
}
void MainWindow::on_actAddFiles_triggered()
{
QStringList files = QFileDialog::getOpenFileNames(this,"选择一个或者多个文件","","Images(*.jpg)");
if(files.isEmpty())
return;
QTreeWidgetItem *parItem,*item;
item = ui->treeWidget->currentItem();
if(item){
if(item->type()==itImageItem) // 当前节点是图片节点
parItem = item->parent();
else {
parItem=item;
}
for (int i = 0;i
QTreeWidget会发出currentItemChanged信号
实现:
代码实现:
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->actAddFolder->setEnabled(true);
ui->actAddFiles->setEnabled(true);
ui->actDeleteItem->setEnabled(false);
break;
case itGroupItem:
ui->actAddFolder->setEnabled(true);
ui->actAddFiles->setEnabled(true);
ui->actDeleteItem->setEnabled(true);
break;
case itImageItem: // 当前选中为图片,不能添加子节点,显示图片
ui->actAddFolder->setEnabled(false);
ui->actAddFiles->setEnabled(true);
ui->actDeleteItem->setEnabled(true);
ui->actZoomFitH->setEnabled(true);
ui->actZoomFitW->setEnabled(true);
ui->actZoomIn->setEnabled(true);
ui->actZoomOut->setEnabled(true);
ui->actZoomRealSize->setEnabled(true);
displayImage(current);
break;
}
}
删除节点使用QTreeWidgetItem对象上的removeChild函数
实现:
代码实现:
void MainWindow::on_actDeleteItem_triggered()
{
QTreeWidgetItem *item = ui->treeWidget->currentItem();
QTreeWidgetItem *parItem = item->parent();
parItem->removeChild(item);
delete item; // 删除子节点的内存空间。removveChild只能从父节点中删除子节点,但不能移除子节点的内存空间。
}
使用递归调用
int topLevelItemCount():返回顶层节点个数。
QTree WidgetItemtopLevelItem(int index):返回序号为index的顶层节点。
int topLevelItemCount():返回顶层节点个数。
QTree WidgetItem*topLevelItem(int index):返回序号为index的顶层节点。
实现:
代码实现:
void MainWindow::on_actScanItems_triggered()
{
int cnt = ui->treeWidget->topLevelItemCount();
for(int i = 0;itreeWidget->topLevelItem(i); // 顶层节点
changeItemCaption(item); // 调用【更改节点标题】函数
}
}
void MainWindow::changeItemCaption(QTreeWidgetItem *item)
{
// 节点标题前加*
QString str = "*" + item->text(colItem);
item->setText(colItem,str);
if(item->childCount()>0){
for (int i = 0;ichildCount();i++) {
changeItemCaption(item->child(i));
}
}
}
curPixmap是在MainWindow中定义的一个QPixmap类型的变量,用于操作图片。QPixmap:load(QString&cfileName)直接将一个图片文件载入。
实现:
这里还显示不了,还未写自适应高度显示action;
void MainWindow::displayImage(QTreeWidgetItem *item)
{
QString filename = item->data(colItem,Qt::UserRole).toString(); // 获取文件名,之前用setData存的数据
LabFileName->setText(filename); // 状态栏显示图片名称
curPixmap.load(filename); // 当前图片
on_actZoomFitH_triggered(); // 自适应高度显示
}
QPixmap存储图片数据,可以缩放图片,有以下几个函数。
变量curPixmap保存了图片的原始副本,要缩放只需调用curPixmap的相应函数,返回缩放后的图片副本。在界面上的一个标签LabPicture上显示图片,使用了QLabel的setPixmap(const QPixmap&)函数。
void MainWindow::on_actZoomFitH_triggered()
{
// 自适应高度显示
int H = ui->scrollArea->height(); // 获取当前滑动块的高度
int realH = curPixmap.height(); // 获取当前图片的高度
pixRatio = float(H)/realH; // 当前图片显示的比例(必须是浮点数)
QPixmap pix = curPixmap.scaledToHeight(H-30); // 图片缩放指定高度
ui->label->setPixmap(pix); // label标签显示图片
}
void MainWindow::on_actZoomFitW_triggered()
{
// 自适应宽度显示
int W = ui->scrollArea->width(); // 获取当前滑动块的高度
int realW = curPixmap.width(); // 获取当前图片的高度
pixRatio = float(W)/realW; // 当前图片显示的比例(必须是浮点数)
QPixmap pix = curPixmap.scaledToWidth(W-30); // 图片缩放指定高度
ui->label->setPixmap(pix); // label标签显示图片
}
void MainWindow::on_actZoomIn_triggered()
{
// 放大显示
pixRatio = pixRatio*1.2;
int w = pixRatio*curPixmap.width();
int h = pixRatio*curPixmap.height();
QPixmap pix = curPixmap.scaled(w,h);
ui->label->setPixmap(pix);
}
void MainWindow::on_actZoomOut_triggered()
{
// 缩小显示
pixRatio = pixRatio*0.8;
int w = pixRatio*curPixmap.width();
int h = pixRatio*curPixmap.height();
QPixmap pix = curPixmap.scaled(w,h);
ui->label->setPixmap(pix);
}
void MainWindow::on_actZoomRealSize_triggered()
{
// 实际大小
pixRatio = 1;
ui->label->setPixmap(curPixmap);
}
只写action按钮的动作,手动拖动dockWidget时按钮的状态不会改变,需要使用dockWidget上的信号;
隐藏发射信号visibilityChanged(bool)
浮动、停靠信号topLevelChanged(bool)
void MainWindow::on_actDockVisible_toggled(bool arg1)
{
ui->dockWidget->setVisible(arg1);
}
void MainWindow::on_actDockFloat_toggled(bool arg1)
{
ui->dockWidget->setFloating(arg1);
}
void MainWindow::on_dockWidget_topLevelChanged(bool topLevel)
{
ui->actDockFloat->setChecked(topLevel);
}
void MainWindow::on_dockWidget_visibilityChanged(bool visible)
{
ui->actDockVisible->setChecked(visible);
}