天天看点

Qt隐藏框架的窗口部件的移动事件处理 问题描述:

问题描述:

我们的自定义的Qt窗口,大多采用了隐藏框架、然后自定义窗口标题栏的方式,实现了窗口的定制。但是在测试、使用过程中,经常出现拖动非标题栏位置窗口也跟着移动、甚至跳动的现象。

解决方案:

重写窗口部件的三个事件函数,mousePressEvent,mouseMoveEvent,mouseReleaseEvent。

在窗口类的内部定义一个记录鼠标按下位置的QPoint m_mousePressPoint;默认值是一个y值大于窗口标题栏高度的点,可设置为QPoint(0,100)。

在mousePressEvent事件中,判断是否是左键按下,若是,则记录鼠标按下的点,并获取鼠标按下时所在位置的窗口部件,并对鼠标按下的点重新定位:若鼠标按下点所在的窗口部件是标题栏内部的窗口部件,则按下点保持不变,否则,将按下点置为默认值。

在mouseMoveEvent事件中,通过按下点的位置与标题栏高度的对比,决定是否执行移动操作。若按下点的位置小于标题栏高度,则移动,否则不移动。(为了避免由于标题栏的部件的边界区域宽度较大时,造成拖动标题栏下边缘无效的情况发生,要考虑标题栏窗口部件相对于其父窗口(this)的相对位置)

在mouseReleaseEvent事件中,将按下点恢复到默认值(因为点击combobox后,不触发mousePressEvent,所以不会对按下点设置位置,而是保持上次的值,因此可能导致移动事件判断出错)。

参考代码如下:

QPoint SubstationAlarmDlg::m_mousePressPoint;//定义记录鼠标按下点。

void SubstationAlarmDlg::mousePressEvent(QMouseEvent* event)
{
	if(event->button()==Qt::LeftButton)//判断是否是左键点击
	{
		m_mousePressPoint = event->pos();
		QWidget *tempWidget = childAt(m_mousePressPoint);
		if (tempWidget == ui.label_5 ||tempWidget == ui.titlelabel ||tempWidget == ui.closeBtn
			||tempWidget == ui.label_2 ||tempWidget == ui.label_4 ||tempWidget == ui.label_6
			||tempWidget == ui.label ) //(不包含最大化、最小化、还原、关闭按钮)
		{
			;//判断按下点所处的部件是否为标题栏内的窗口部件,若是,不作为。
		}
		else
		{
			m_mousePressPoint = QPoint(0,100);//若不是,重置为初始值。
		}
	}
}


void SubstationAlarmDlg::mouseMoveEvent(QMouseEvent *event)
{
	QPoint tempPoint = event->pos();//获取事件发生位置
	QRect selfRect = ui.logoWidget->geometry();//获取窗口图标相对于父窗体的矩形
	int y = selfRect.y();//获取矩形的高度
	int tempHight = ui.logoWidget->height() + y;//获取标题栏最下线到父窗体最上线的距离(作为判断对比值)
	if (m_mousePressPoint.y() < tempHight)//对比,确定是否移动。
	{
		int tempX = tempPoint.x() - m_mousePressPoint.x();
		int tempY = tempPoint.y() - m_mousePressPoint.y();
		int nowX = this->x();
		int nowY = this->y();
		nowX += tempX;
		nowY += tempY;
		this->move(nowX, nowY);
	}
}


void SubstationAlarmDlg::mouseReleaseEvent(QMouseEvent *event)
{
	m_mousePressPoint = QPoint(0, 100);
}
      

继续阅读