QT自绘带滚动条的Tab界面类的封装
程序员文章站
2022-05-28 14:37:04
...
一、原理:
1、当拖动滚动条的滑块时,通过计算的拖动比例来拖动可视界面;
2、可视界面的拖动通过移动绘图的坐标系来完成;
3、点击Tab选项页时发送信号,传送其索引编号。
二、Tab界面类的封装:
头文件:
#ifndef ZZCLISTWIDGET_H
#define ZZCLISTWIDGET_H
#include <QWidget>
#include <QPainter>
#include <QResizeEvent>
#include <QScrollArea>
class zzcListWidget : public QWidget
{
Q_OBJECT
public:
zzcListWidget(QWidget *parent);
~zzcListWidget();
private:
QList<QString> listItem;
/*widget的整体背景*/
QColor bgColor;
/*矩形框填充颜色*/
QColor itemRectColor;
QColor itemRextColorHover;
QColor itemRctColorPress;
/*文字颜色*/
QColor textColor;
QColor textColorHover;
QColor textColorPress;
/*每一项的宽度和高度*/
int rowHeight; //每一项的高度
int rowWidth; //每一项的宽度
QColor rightRectColor;//滑块所在整个矩形的颜色
QColor scrollColor; //滑块的颜色
int ScrollWidth; //滑块的宽度
int ScrollHeight; //滑块的高度
int ScrollTop; //滑块左上角的y值
bool bPress; //左键是否按下
int mouseY; //鼠标点击滑块时的纵坐标
double p; //左侧随滑块的拖放比例
/*鼠标略过索引和点击索引*/
int curItemIndexHover;
int curItemIndexPress;
QString strUp; //向上箭头图标路径
QString strDown; //向下箭头图标路径
QPixmap pixUp;
QPixmap pixDown;
int pixHeight; //图标高度
int pixWidth; //图标宽度
private:
void resizeEvent(QResizeEvent* e);
void mouseMoveEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void paintEvent(QPaintEvent *e);
void drawbg(QPainter &painter);
void drawItemText(QPainter &painter);
void drawScrollBar(QPainter& painter);
public:
void addItem(QString item);
void setIconPath(QString strup,QString strdown);
signals:
void itemIndexChanged(int nindex);
};
#endif // ZZCLISTWIDGET_H
cpp文件:
#include "zzclistwidget.h"
#include "GBK.h"
#include <QDebug>
zzcListWidget::zzcListWidget(QWidget *parent)
: QWidget(parent)
{
rowHeight = 40;
curItemIndexHover = 0;
curItemIndexPress = 0;
bgColor = QColor(70,170,130);
itemRectColor = QColor(70,170,130);
itemRextColorHover = QColor(20,200,20);
itemRctColorPress = QColor(40,40,250);
textColor = QColor(0,0,0);
textColorHover = QColor(255,255,255);
textColorPress = QColor(250,100,10);
rightRectColor = QColor(30,130,90);
scrollColor = QColor(83,83,255);
ScrollTop = 20;
ScrollWidth = 20;
ScrollHeight = 20;
bPress = false;
mouseY = 0;
p = 1.0;
pixHeight = 20;
pixWidth = 20;
setMouseTracking(true);
setFixedWidth(170);
}
zzcListWidget::~zzcListWidget()
{
}
void zzcListWidget::addItem(QString item)
{
listItem.append(item);
update();
}
void zzcListWidget::setIconPath(QString strup,QString strdown)
{
strUp = strup;
strDown = strdown;
if(!strup.isEmpty())
pixUp.load(strup);
if(!strdown.isEmpty())
pixDown.load(strdown);
}
void zzcListWidget::resizeEvent(QResizeEvent* e)
{
rowWidth = width() - ScrollWidth;
}
void zzcListWidget::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing,true);
drawbg(painter);
drawItemText(painter);
drawScrollBar(painter);
}
/*
** 绘制整个widget背景
*/
void zzcListWidget::drawbg(QPainter &painter)
{
painter.save();
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(bgColor));
painter.drawRect(rect());
painter.restore();
}
void zzcListWidget::drawItemText(QPainter &painter)
{
painter.save();
painter.translate(QPoint(0,-(ScrollTop - pixHeight) * p ));
int nIndex = 0;
foreach(QString strText,listItem)
{
QRect rectTemp(0,rowHeight * nIndex,rowWidth,rowHeight);
if (curItemIndexPress == nIndex)/*绘制点击状态*/
{
QPen pen(Qt::NoBrush,2,Qt::DotLine);
pen.setColor(textColorPress);
painter.setPen(pen);
painter.drawRect(rectTemp.adjusted(2,2,-2,-2));
painter.fillRect(rectTemp.adjusted(2,2,-2,-2),QBrush(itemRctColorPress));
painter.drawText(rectTemp, Qt::AlignHCenter | Qt::AlignVCenter,strText);
}
else if (curItemIndexHover == nIndex)/*绘制鼠标经过状态*/
{
painter.setPen(QPen(textColorHover));
painter.fillRect(rectTemp,QBrush(itemRextColorHover));
painter.drawText(rectTemp, Qt::AlignHCenter | Qt::AlignVCenter,strText);
}
else
{
painter.setPen(QPen(textColor));
painter.fillRect(rectTemp,QBrush(itemRectColor));
painter.drawText(rectTemp, Qt::AlignHCenter | Qt::AlignVCenter,strText);
}
nIndex++;
}
painter.restore();
}
void zzcListWidget::drawScrollBar(QPainter& painter)
{
painter.save();
/*
* 计算滑块拖动的比例:p 和滑块的高度
*/
if (listItem.count() * rowHeight > height())
{
/*
** 滑块高度计算原理:图标高度*2 + 滑块高度 + 滑块拖动距离 = widget总高度(height)
*/
ScrollHeight = height() - (listItem.count() * rowHeight - height()) - pixHeight * 2;
if (ScrollHeight <= 0)
{
ScrollHeight = 20;
/*拖放比例*/
p = (double)(listItem.count() * rowHeight - height())/(double)(height() - pixHeight * 2 - ScrollHeight);
}
else
{
p = 1.0;
}
}
else{
ScrollHeight = 0;
}
/*
** 根据滑块的高度绘制滑块及其背景
*/
QRect rectup(rowWidth,0,ScrollWidth,pixHeight);
QRect rectdown(rowWidth,height() - pixHeight,ScrollWidth,pixHeight);
QRect rect(rowWidth,0,ScrollWidth,height());//背景矩形
QRect scrolrect(rowWidth,ScrollTop,ScrollWidth,ScrollHeight); //滑块矩形
/*绘制滑块所在整个矩形*/
painter.setPen(QPen(rightRectColor));
painter.drawRect(rect);
painter.fillRect(rect,QBrush(rightRectColor));
/*绘制滑块*/
if (ScrollTop > 20)
{
QPen scrollPen(scrollColor);
scrollPen.setWidth(2);
painter.setPen(scrollPen);
painter.setBrush(QBrush(scrollColor));
painter.drawRect(scrolrect.adjusted(2,3,-3,-3));
}
/*绘制上下箭头图标*/
painter.drawPixmap(rectup,pixUp);
painter.drawPixmap(rectdown,pixDown);
painter.restore();
}
void zzcListWidget::mouseMoveEvent(QMouseEvent *e)
{
if ((e->y()+ (ScrollTop - pixHeight) * p )/rowHeight < listItem.count() && e->x() < rowWidth)
{
//qDebug()<<e->y()<<endl;
if (curItemIndexHover != (e->y() + (ScrollTop - pixHeight) * p )/rowHeight)
{
curItemIndexHover = (e->y() + (ScrollTop - pixHeight) * p)/rowHeight;
}
}else{
curItemIndexHover = -1;
/*
** 拖动的时候计算 ScrollTop ,依据其值绘制滑块
*/
if (bPress && ScrollTop >= pixHeight && (ScrollTop + ScrollHeight) <= height() - pixHeight)
{
int mouseYTemp = e->y();
ScrollTop += mouseYTemp - mouseY;
mouseY = mouseYTemp;
if (ScrollTop < pixHeight)
ScrollTop = pixHeight;
if ((ScrollTop + ScrollHeight) > height() - pixHeight)
ScrollTop = height() - ScrollHeight - pixHeight;
}
}
update();
}
void zzcListWidget::mousePressEvent(QMouseEvent *e)
{
if ((e->y() + (ScrollTop - pixHeight) *p )/rowHeight < listItem.count() && e->x() < rowWidth)
{
if (curItemIndexPress != (e->y() + (ScrollTop - pixHeight) * p )/rowHeight)
{
curItemIndexPress = (e->y() + (ScrollTop - pixHeight) * p)/rowHeight;
emit itemIndexChanged(curItemIndexPress);
update();
}
}else if (e->x() > rowWidth && e->x() < width() && e->y() > ScrollTop && e->y() < (ScrollTop + ScrollHeight))
{
if (e->button() == Qt::LeftButton)
{
bPress = true;
mouseY = e->y();
}
}
}
void zzcListWidget::mouseReleaseEvent(QMouseEvent *e)
{
bPress = false;
}
三、封装类的使用:
1、调用addItem()函数添加Tab项;
ui.widget->addItem(GBK::ToUnicode("111111"));
2、调用setIconPath()函数设置滚动条的上下两个图标:
ui.widget->setIconPath(":/listWidgetClass/Resources/up.jpg",":/listWidgetClass/Resources/down.jpg");
完整的调用如下:
#ifndef LISTWIDGETCLASS_H
#define LISTWIDGETCLASS_H
#include <QtGui/QWidget>
#include "ui_listwidgetclass.h"
class listWidgetClass : public QWidget
{
Q_OBJECT
public:
listWidgetClass(QWidget *parent = 0, Qt::WFlags flags = 0);
~listWidgetClass();
private:
Ui::listWidgetClassClass ui;
private slots:
void OnCurtiemIndex(int nindex);
};
#endif // LISTWIDGETCLASS_H
#include "listwidgetclass.h"
#include "GBK.h"
#include <QScrollArea>
listWidgetClass::listWidgetClass(QWidget *parent, Qt::WFlags flags)
: QWidget(parent, flags)
{
ui.setupUi(this);
ui.widget->addItem(GBK::ToUnicode("111111"));
ui.widget->addItem(GBK::ToUnicode("222222"));
ui.widget->addItem(GBK::ToUnicode("333333"));
ui.widget->addItem(GBK::ToUnicode("444444"));
ui.widget->addItem(GBK::ToUnicode("555555"));
ui.widget->addItem(GBK::ToUnicode("666666"));
ui.widget->addItem(GBK::ToUnicode("111111"));
ui.widget->addItem(GBK::ToUnicode("222222"));
ui.widget->addItem(GBK::ToUnicode("333333"));
ui.widget->addItem(GBK::ToUnicode("444444"));
ui.widget->addItem(GBK::ToUnicode("555555"));
ui.widget->addItem(GBK::ToUnicode("666666"));
ui.widget->addItem(GBK::ToUnicode("111111"));
ui.widget->addItem(GBK::ToUnicode("222222"));
ui.widget->addItem(GBK::ToUnicode("333333"));
ui.widget->addItem(GBK::ToUnicode("444444"));
ui.widget->addItem(GBK::ToUnicode("555555"));
ui.widget->addItem(GBK::ToUnicode("666666"));
ui.widget->setIconPath(":/listWidgetClass/Resources/up.jpg",":/listWidgetClass/Resources/down.jpg");
connect(ui.widget,SIGNAL(itemIndexChanged(int)),this,SLOT(OnCurtiemIndex(int)));
}
listWidgetClass::~listWidgetClass()
{
}
void listWidgetClass::OnCurtiemIndex(int nindex)
{
ui.stackedWidget->setCurrentIndex(nindex);
}
运行效果:
上一篇: 简单的Html页面播放视频-小白学习1
下一篇: java:(一)基于UDP的单客户端连接
推荐阅读