欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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);
}

运行效果:

QT自绘带滚动条的Tab界面类的封装