列表标题栏添加CheckBox

      前段时间项目上的要求,要实现一个列表(见下图1)。类似网页上的列表,可以通过选中标题栏的复选框,实现全选或者全不选的功能。但是看了很久,都没看到Qt哪个方法可以实现在标题栏添加控件。

      列表标题栏添加CheckBox_第1张图片

                                            图1


要实现这样的效果,也许我们首先想到的,就是直接生成一个CheckBox,用setGeometry()设置它的位置就可以了。当然这样是可以的,也是最简单的。但是有个问题:这样做,CheckBox就固定死了,而且没有跟标题栏连城一体,不会随着标题栏一起移动。结果如下图2

列表标题栏添加CheckBox_第2张图片

显然,这样的效果有点不爽。

后面想到了一种比较好的办法,就是自定义一个heander。通过setHeader()设置给列表。下面是我的部分实现代码

class MyCheckBox:public QCheckBox
{
	Q_OBJECT
public:
	MyCheckBox(QWidget *parent /*= NULL*/):QCheckBox(parent)
	{

	}
	~MyCheckBox(){}

protected:

	void mouseMoveEvent(QMouseEvent *e)
	{
		//HeaderView::mouseMoveEvent(e);
		QRect boxRect = this->rect();
		QPoint pos = e->pos();
		if (boxRect.contains(pos))
		{
			setCursor(Qt::ArrowCursor);
		}
	}
private:

};


class HanderView :public QHeaderView 
{

	Q_OBJECT
public:
	HanderView( Qt::Orientation orientation,QWidget *parent /*= NULL*/):QHeaderView(orientation,parent)
	{
		m_pCheckBox = new MyCheckBox(this);
		hasPaint = false;
	}
	~HanderView()
	{

	}
private slots:
protected:


	void resizeEvent(QResizeEvent *event)
	{
		int leftPos = this->sectionViewportPosition(0);
		m_pCheckBox->setGeometry(leftPos + 5,0,50,this->height());
		int sectionMinSize = 50;
		this->setMinimumSectionSize(sectionMinSize + sectionSizeFromContents(0).width());
		this->setDefaultSectionSize(sectionMinSize + sectionSizeFromContents(0).width());
	}

	void paintEvent(QPaintEvent *e)
	{
		QHeaderView::paintEvent(e);
		int leftPos = this->sectionViewportPosition(0);
		m_pCheckBox->setGeometry(leftPos + 5,0,50,this->height());
	}
private:
	MyCheckBox   *m_pCheckBox;
	bool hasPaint;
};

class MyTreeWidget:public QTreeWidget
{
	Q_OBJECT
public:
	MyTreeWidget(QWidget *parent = NULL);
	~MyTreeWidget();

protected:

private:
	HanderView   *m_pHeader;
};

MyTreeWidget::MyTreeWidget(QWidget *parent /* = NULL */):QTreeWidget(parent)
{
	m_pHeader = new HanderView(Qt::Horizontal,parent);
	this->setHeader(m_pHeader);
	QStringList list ;
	list<<"文件名"<<"文件大小"<<"文件类型"<<"创建日期";
	this->setHeaderLabels(list);
	header()->setDefaultAlignment(Qt::AlignCenter);
}

1、这里是为了保证鼠标在标题栏上是箭头状,因为Box靠近分割线,不这么做的话,鼠标移动到Box上面的时候也可能是Qt::SplitHCursor。这样对用户感觉有点不爽。大家可以试试注释这些代码看看就知道了

void mouseMoveEvent(QMouseEvent *e)  
{
	//HeaderView::mouseMoveEvent(e);
	QRect boxRect = this->rect();
	QPoint pos = e->pos();
	if (boxRect.contains(pos))
	{
	    setCursor(Qt::ArrowCursor);
	}
}
2、

int leftPos = this->sectionViewportPosition(0);
m_pCheckBox->setGeometry(leftPos + 5,0,50,this->height());
int sectionMinSize = 50;
this->setMinimumSectionSize(sectionMinSize + sectionSizeFromContents(0).width());
this->setDefaultSectionSize(sectionMinSize + sectionSizeFromContents(0).width());
设置列的最小宽度。
sectionSizeFromContents(0).width()这个可以根据标题栏的字符的长度调整列的宽度。


3、

int leftPos = this->sectionViewportPosition(0);
m_pCheckBox->setGeometry(leftPos + 5,0,50,this->height());
这里保证移动滚动条的时候,Box会跟着标题栏动。

效果如图3,图4

列表标题栏添加CheckBox_第3张图片列表标题栏添加CheckBox_第4张图片

                      图3                                                                                              图4


4、我们也可以把Box放在其他列,改一下index就可以了

int leftPos = this->sectionViewportPosition(1);
m_pCheckBox->setGeometry(leftPos + 5,0,50,this->height());
int sectionMinSize = 50;
this->setMinimumSectionSize(sectionMinSize + sectionSizeFromContents(1).width());
this->setDefaultSectionSize(sectionMinSize + sectionSizeFromContents(1).width());

int leftPos = this->sectionViewportPosition(1);
m_pCheckBox->setGeometry(leftPos + 5,0,50,this->height());
结果如图5,图6

列表标题栏添加CheckBox_第5张图片列表标题栏添加CheckBox_第6张图片

                                                    图5                                                                                                                                        图6





你可能感兴趣的:(qt)