多语言展示
当前在线:933今日阅读:75今日分享:44

Qt:可移动的树形数据报表

在软件开发中,需要对数据进行统计的时候,往往需要一个树形的表格窗口,并可以隐藏和移动。那么下面有三点小技术,可以实现它:1、Qt中的QTreeWidget的使用。2、Qt中QWidget的移动。3、Qt中窗口的自定义风格。
工具/原料
1

VS2013

2

Qt5.2

方法/步骤
1

Qt中的QTreeWidget和QTreeWidgetItem 的使用可以实现树形表。      按照MVC设计,Qt中提倡用QTreeView,但是没有提供对应的Model,可以通过自定义QStandardItemModel一起实现,但是比较复杂。不推荐使用。/*** @brief 初始化报表数据*/void ReportTree::initReportData(){ //根节点的数据项 QStringList itemStringlist; itemStringlist << 'All EventS' <<'10000' << '100%' << '100%'; QTreeWidgetItem *rootItem = new QTreeWidgetItem(ui.treeWidget, itemStringlist); QPixmap pixmap(10,10);//新建一个Pixmap图 pixmap.fill(QColor(Qt::black));//填充色 QIcon icon(pixmap); rootItem->setIcon(0, icon);//设置图标 //根节点的孩子节点1 QStringList leafStringList1; leafStringList1 << 'Gate1' << '8000'<<'80%'<<'80%'; QTreeWidgetItem *leafItem1 = new QTreeWidgetItem(rootItem, leafStringList1); pixmap.fill(QColor(Qt::red)); leafItem1->setIcon(0, pixmap); //根节点的孩子节点2 QStringList leafStringList2; leafStringList2 << 'Gate2' << '4000' << '40%' << '40%'; QTreeWidgetItem *leafItem2 = new QTreeWidgetItem(rootItem, leafStringList2); pixmap.fill(QColor(Qt::green)); leafItem2->setIcon(0, pixmap); //根节点的孩子节点3 QStringList leafStringList3; leafStringList3 << 'Gate3' << '2000' << '20%' << '20%'; QTreeWidgetItem *leafItem3 = new QTreeWidgetItem(rootItem, leafStringList3); pixmap.fill(QColor(Qt::blue)); leafItem3->setIcon(0, pixmap); //节点3的孩子节点1_in_3 QStringList leafStringList1_In_3; leafStringList1_In_3 << 'Gate1_in_3' << '1000' << '50%' << '10%'; QTreeWidgetItem *leafItem1_in_3 = new QTreeWidgetItem(leafItem3, leafStringList1_In_3); pixmap.fill(QColor(Qt::gray)); leafItem1_in_3->setIcon(0, pixmap); //给节点3添加孩子节点 leafItem3->addChild(leafItem1_in_3); //节点3的孩子节点2_in_3 QStringList leafStringList2_In_3; leafStringList2_In_3 << 'Gate2_in_3' << '500' << '40%' << '2%'; QTreeWidgetItem *leafItem2_in_3 = new QTreeWidgetItem(leafItem3, leafStringList2_In_3); pixmap.fill(QColor(Qt::darkCyan)); leafItem2_in_3->setIcon(0, pixmap); leafItem3->addChild(leafItem2_in_3); //给根节点添加孩子节点 rootItem->addChild(leafItem1); rootItem->addChild(leafItem2); rootItem->addChild(leafItem3);}

2

Qt中QWidget的移动。只需要重写一个QWidget的子类,将如下三个事件重载。即可实现在标题栏附近移动窗口。但是当前窗口的父窗口指定,而且当前窗口背景是透明的,需要QSS自定义颜色。//指定当前窗口要显示的父类窗口 reportTree = new ReportTree(this); reportTree->setVisible(false);void ReportTree::mousePressEvent(QMouseEvent *event){ //只能是鼠标左键移动和改变大小 if (event->button() == Qt::LeftButton) { if (event->y() > 33)//控制在标题栏内,才可以拖动窗口 { event->ignore(); return; } mouse_press = true; } //窗口移动距离 move_point = event->globalPos() - pos();}void ReportTree::mouseReleaseEvent(QMouseEvent *){ mouse_press = false;}void ReportTree::mouseMoveEvent(QMouseEvent *event){ if (event->y() <= 33)//控制在标题栏内,才可以拖动窗口 { setCursor(Qt::SizeAllCursor); } else { setCursor(Qt::ArrowCursor); } //移动窗口 if (mouse_press) { QPoint move_pos = event->globalPos(); move(move_pos - move_point); }}

3

Qt中窗口的自定义风格Qt本身的标题栏和VC一样风格,比较挫。当你在父窗口内显示QWidget,它会自动隐藏标题栏和边框。所以只需要自定义一个标题栏即可。至于关闭按钮的效果,通过QSS是无法实现的。只需要用自定义一个PushButton即可,实现正常,hover,pressed三种状态。PushButton::PushButton(QWidget *parent) :QPushButton(parent){ status = NORMAL; mouse_press = false;}PushButton::~PushButton(){}void PushButton::setPicName(QString pic_name){ this->pic_name = pic_name; setFixedSize(QPixmap(pic_name).size());}void PushButton::enterEvent(QEvent *){ status = ENTER; update();}void PushButton::mousePressEvent(QMouseEvent *event){ //若点击鼠标左键 if(event->button() == Qt::LeftButton) { mouse_press = true; status = PRESS; update(); }}void PushButton::mouseReleaseEvent(QMouseEvent *event){ //若点击鼠标左键 if(mouse_press  && this->rect().contains(event->pos())) { mouse_press = false; status = ENTER; update(); emit clicked(); }}void PushButton::mouseMoveEvent(QMouseEvent *event){ //控制在标题栏内,才可以拖动窗口 setCursor(Qt::ArrowCursor);}void PushButton::leaveEvent(QEvent *){ status = NORMAL; update();}void PushButton::paintEvent(QPaintEvent *){ QPainter painter(this); QPixmap pixmap; switch(status) { case NORMAL: { pixmap.load(pic_name); break; }     case ENTER: { pixmap.load(pic_name + QString('_hover')); break; }  case PRESS: { pixmap.load(pic_name + QString('_pressed')); break; }    case NOSTATUS: { pixmap.load(pic_name); break; }    default: pixmap.load(pic_name); } painter.drawPixmap(rect(),pixmap);}

4

作者:柳北风儿 博客

推荐信息