Qt操作:鼠标事件(鼠标事件座标)+程序退出前弹出确认退出对话框(QMessageBox的使用,closeEvent()函数重写)

Qt操作:鼠标事件(鼠标事件座标)+程序退出前弹出确认退出对话框(QMessageBox的使用)

程序功能

基本功能:打开一张图片,建立一张与之对应的大小一致的全黑灰度图,用鼠标在图片上选取ROI;选中ROI的同时,灰度图对应的位置填充为白色。
附加功能:用户选择ROI后在未保存灰度图的情况下点击退出程序,需对用户进行提醒是否保存当前选中的ROI

鼠标事件

鼠标座标
相对座标(鼠标在widget中,且对于当前的widget的座标):x(),y()。
Qpoint windowPos() 程序窗口座标:鼠标在程序窗口的相对位置
screenPos():屏幕座标
QWidget::mapToGlobal(ev->Pos()):由本地座标转换成屏幕座标
QCursor::pos():获得鼠标的屏幕座标

鼠标按键状态
buttons()& Qt::LeftButton :左键
Qt::RightButton :右键 Qt::MidButton:中间键

&是“与”运算
三个键可以同时发生:通过与运算可以得到按键状态

鼠标事件重载
在这里插入图片描述

本次任务复杂点: 如何得到当前鼠标点击的位置相对于图片的准确位置
捕获鼠标事件有两种方式(此次使用1):
1.直接使用相应的鼠标事件函数

void mousePressEvent(QMouseEvent *event)
void mouseReleaseEvent(QMouseEvent *event)

2.使用事件过滤器

相对图片位置的获取
捕获鼠标事件之前,首先获取当前图片相对于显示该图片的Qlabel的偏差(xoffset,yoffset),以及显示相对于图片像素的比例(Qlabel和图片可能大小不一致,因而需要进行一次转换)。

ui.tmp->setAlignment(Qt::AlignCenter);
ui.tmp->setPixmap(QPixmap::fromImage(imgshow).scaled(ui.tmp->size().width(),
ui.tmp->size().height()*1.1, Qt::KeepAspectRatio));	
xoffset = (ui.tmp->contentsRect().width() - ui.tmp->pixmap()->rect().width()) / 2;
yoffset = (ui.tmp->contentsRect().height() - ui.tmp->pixmap()->rect().height()) / 2;
rate_label = double((ui.tmp->contentsRect().width() - 2 * xoffset)) / img.cols;

然后获得鼠标事件(使用的方式1)

void choose_ROI::mousePressEvent(QMouseEvent *event)
{
	QPoint leftButtomRightPoint = event->globalPos();
	leftButtomRightPoint = ui.tmp->mapFromGlobal(leftButtomRightPoint);

	if (leftButtomRightPoint.x() < ui.tmp->width()&& leftButtomRightPoint.x()>0
		&& leftButtomRightPoint.y() < ui.tmp->height()&&leftButtomRightPoint.y()>0)
	{
		//leftButtomRightPoint = ui.tmp->mapFromGlobal(leftButtomRightPoint);
		left_point.x = (leftButtomRightPoint.x() - xoffset);
		left_point.y = (leftButtomRightPoint.y() - yoffset);
		
	}

}

代码分析:
event->globalPos();获取当前鼠标相对于全局的位置
通过ui.tmp->mapFromGlobal(leftButtomRightPoint);转化成鼠标当前所在控件上的位置
然后我这里又进行了是否点击在相应的位置上的判断(if语句)
容易得到left_point.x left_point.y,这就是鼠标在当前Qlabel上相对于图片的位置。要进行图片的操作(比如标记ROI)只需要最后一步操作得到该位置相对于图片的绝对位置:

left_point.x = left_point.x/rate_label;
left_point.y = left_point.y /rate_label;
right_point.x = right_point.x/rate_label;
right_point.y = right_point.y /rate_label;

最后图片操作

    Rect rect;
	rect.x = left_point.x;
	rect.y = left_point.y;
	rect.width = right_point.x- left_point.x;
	rect.height = right_point.y - left_point.y;
	rect &= Rect(0, 0, imgROI.cols, imgROI.rows);//(防止内存错误)
	imgROI(rect).setTo(255);//填充

程序退出前弹出确认退出对话框

重写void closeEvent(QCloseEvent *ev)函数,对关闭对话框进行控制。

void choose_ROI::closeEvent(QCloseEvent *ev)
{
	char buf_save[100];
	sprintf(buf_save, "roi");
	char buf_downFrame[100];
	sprintf(buf_downFrame, "是否保存对ROI的修改?");
	QString strInfo = QString::fromLocal8Bit(buf_downFrame);
	string buf_downFrame1 = strInfo.toStdString();
	if (ROIflag == 0 || ROIflag == 1)
	{
		QMessageBox::StandardButton r = QMessageBox::warning(this, " ",
			buf_downFrame1.c_str(), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);

		if (r == QMessageBox::No)
		{
			ev->accept();
		}
		else
		{
			ev->ignore();
//			svae_Roi();//这是我保存图片的函数
		}
	}
}

代码解析:
首先需要解决中文字符的编码问题利用QString::fromLocal8Bit()将char 转化成Qstring,这种转化方式指定编码方式。然后将该Qstring转化成std 的string。最终显示的时候是char*类型,再调用一次.c_str()就可以了。

然后是QMessageBox的使用,QMessageBox::warning(this, " ", buf_downFrame1.c_str(), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);中的QMessageBox::Yes | QMessageBox::No, QMessageBox::No可以缺省。其余请直接看代码。

效果展示

在这里插入图片描述
说明: 红色框是选择为ROI的区域,右边ROI图像对选中的区域进行白色填充。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章