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圖像對選中的區域進行白色填充。

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