首页 > 其他分享 >Qt实现无边框窗口的拖动和缩放

Qt实现无边框窗口的拖动和缩放

时间:2024-08-11 10:52:55浏览次数:8  
标签:case 鼠标 缩放 拖动 int ev rect Qt

 在使用QT创建窗体的时候,为了使窗口美化,通常不使用QT自带的边框。会调用下面函数去除窗体边框。

setWindowFlags(Qt::FramelessWindowHint)

但是有个问题,当去除了QT自带边框后,窗体就变得不能移动了,也不能改变窗口大小了。这确实是个问题,该怎么去解决呢?

 1.重写mousePressEvent\ mouseMoveEvent mouseReleaseEvent事件

protected:
    void mousePressEvent(QMouseEvent* ev)override;
    void mouseReleaseEvent(QMouseEvent* ev)override;
    void mouseMoveEvent(QMouseEvent* ev)override;

.h文件

namespace {
    /* 这里我们将一个窗口划分为9个区域,分别为

 左上角(1, 1)、中上(1,2)、右上角(1, 3)

 左中  (2, 1)、 中间(2, 2)、右中  (2, 3)

 左下角(3, 1)、中下(3,2)、 右下角(3, 3)*/
    const int kMouseRegionLeft = 5;

    const int kMouseRegionTop = 5;

    const int kMouseRegionRight = 5;

    const int kMouseRegionBottom = 5;

}

// 鼠标的 活动范围的 枚举
enum MousePosition

{
    // 这个是上面图片划分的区域 1,1 区 就用 11 代表 , 1,2 就用12 代表 以此类推
    kMousePositionLeftTop = 11,

    kMousePositionTop = 12,

    kMousePositionRightTop = 13,

    kMousePositionLeft = 21,

    kMousePositionMid = 22,

    kMousePositionRight = 23,

    kMousePositionLeftBottom = 31,

    kMousePositionBottom = 32,

    kMousePositionRightBottom = 33,

};


private:
    //根据鼠标的设置鼠标样式,用于拉伸
    void SetMouseCursor(int x, int y);
    //判断鼠标的区域,用于拉伸
    int GetMouseRegion(int x, int y);
private:
    bool isPress;
    QPoint windowsLastPs;
    QPoint mousePs;
    int mouse_press_region = kMousePositionMid;


 .cpp文件

void SPlay::mousePressEvent(QMouseEvent* ev)
{
	if (ev->button() == Qt::LeftButton) {

		// 如果是鼠标左键
		// 获取当前窗口位置,以窗口左上角
		windowsLastPs = pos();
		// 获取鼠标在屏幕的位置  就是全局的坐标 以屏幕左上角为坐标系
		mousePs = ev->globalPos();

		isPress = true;
		// 获取鼠标在那个区域
		mouse_press_region = GetMouseRegion(ev->pos().x(), ev->pos().y());

	}
}

void SPlay::mouseReleaseEvent(QMouseEvent* ev)
{
	if (ev->button() == Qt::LeftButton) {
		isPress = false;
	}
	setCursor(QCursor{});
}

void SPlay::mouseMoveEvent(QMouseEvent* ev)
{
	// 设置鼠标的形状
	SetMouseCursor(ev->pos().x(), ev->pos().y());
	// 计算的鼠标移动偏移量, 就是鼠标全局坐标 - 减去点击时鼠标坐标
	QPoint point_offset = ev->globalPos() - mousePs;
	if ((ev->buttons() == Qt::LeftButton) && isPress)
	{
		if (mouse_press_region == kMousePositionMid)
		{
			// 如果鼠标是在窗口的中间位置,就是移动窗口
			move(windowsLastPs + point_offset);
		}
		else {
			// 其他部分 是拉伸窗口
			// 获取客户区
			QRect rect = geometry();
			switch (mouse_press_region)
			{
				// 左上角
			case kMousePositionLeftTop:
				rect.setTopLeft(rect.topLeft() + point_offset);
				break;
			case kMousePositionTop:
				rect.setTop(rect.top() + point_offset.y());
				break;
			case kMousePositionRightTop:
				rect.setTopRight(rect.topRight() + point_offset);
				break;
			case kMousePositionRight:
				rect.setRight(rect.right() + point_offset.x());
				break;
			case kMousePositionRightBottom:
				rect.setBottomRight(rect.bottomRight() + point_offset);
				break;
			case kMousePositionBottom:
				rect.setBottom(rect.bottom() + point_offset.y());
				break;
			case kMousePositionLeftBottom:
				rect.setBottomLeft(rect.bottomLeft() + point_offset);
				break;
			case kMousePositionLeft:
				rect.setLeft(rect.left() + point_offset.x());
				break;
			default:
				break;
			}
			setGeometry(rect);
			mousePs = ev->globalPos();
		}
	}
}

void SPlay::SetMouseCursor(int x, int y)
{
	// 鼠标形状对象
	Qt::CursorShape cursor{};
	int region = GetMouseRegion(x, y);
	switch (region)
	{
	case kMousePositionLeftTop:
	case kMousePositionRightBottom:
		cursor = Qt::SizeFDiagCursor; break;
	case kMousePositionRightTop:
	case kMousePositionLeftBottom:
		cursor = Qt::SizeBDiagCursor; break;
	case kMousePositionLeft:
	case kMousePositionRight:
		cursor = Qt::SizeHorCursor; break;
	case kMousePositionTop:
	case kMousePositionBottom:
		cursor = Qt::SizeVerCursor; break;
	case kMousePositionMid:
		cursor = Qt::ArrowCursor; break;
	default:
		break;
	}
	setCursor(cursor);
}

int SPlay::GetMouseRegion(int x, int y)
{
	int region_x = 0, region_y = 0;
	// 鼠标的X坐标小于 边界5 说明他在最上层区域 第一区域
	if (x < kMouseRegionLeft)
	{
		region_x = 1;
	}
	else if (x > (this->width()/*窗体宽度*/ - kMouseRegionRight/*边界宽度5*/)) {
		// 如果鼠标X坐标 大于 最右侧的边界 说明他在第三区域
		region_x = 3;
	}
	else {
		region_x = 2;
	}
	if (y < kMouseRegionTop)
	{
		// 同理 鼠标Y坐标 小于上层边界5  说明鼠标在第一区域
		region_y = 1;
	}
	else if (y > (this->height() - kMouseRegionBottom)) {
		// 鼠标Y坐标的 大于 最下面的坐标,鼠标就在 第三区
		region_y = 3;
	}
	else {
		region_y = 2;
	}
	// 最后计算 表示区域的 数值 (x=1, y=1) 计算 = 1*10+1 =11 
	// x=2,y=3 = 3*10+2 = 32 在图的 3,2 区域
	return region_y * 10 + region_x;
}

2.QSizeGrip实现

#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include <QSizeGrip>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QWidget *widget = new QWidget;
    QVBoxLayout *layout = new QVBoxLayout(widget);
    widget->setLayout(layout);

    // 添加窗口内容
    // ...

    // 添加 QSizeGrip 控件
    QSizeGrip *sizeGrip = new QSizeGrip(widget);
    layout->addWidget(sizeGrip, 0, Qt::AlignBottom | Qt::AlignRight);

    // 设置窗口大小和位置
    widget->resize(400, 300);
    widget->move(100, 100);

    widget->show();

    return app.exec();
}

在这个示例中,我们首先创建一个QWidget对象和一个QVBoxLayout布局对象,并将布局设置为窗口的布局。然后,我们添加窗口的内容到布局中。

接下来,我们创建一个QSizeGrip对象,并将其添加到布局中的右下角。我们使用Qt::AlignBottom | Qt::AlignRight参数将QSizeGrip控件放置在窗口的右下角。

最后,我们设置窗口的大小和位置,并将其显示出来。

通过在无边框窗口中添加QSizeGrip控件,用户可以使用鼠标拖动控件来调整窗口的大小。

参考文章1:QT 创建一个 可移动、可拉伸的无边框窗体_qt 无边框窗口拉伸-CSDN博客

参考文章2:Qt实现无边框窗口实现拉伸的三种方法--附源码_qt 无边框窗口拉伸-CSDN博客

 参考小项目:https://github.com/a-mo-xi-wei/frameLessWindow

标签:case,鼠标,缩放,拖动,int,ev,rect,Qt
From: https://blog.csdn.net/m0_74091159/article/details/141069966

相关文章

  • Python使用PyCharm创建一个简单的Qt Quick应用程序-hello_world_quick.py(读取qml文件
    """CreateaSimpleQuickApplication"""importsysfrompathlibimportPathfromPySide6.QtGuiimportQGuiApplicationfromPySide6.QtQmlimportQQmlApplicationEngine#打开文件,读取文件,并返回文件内容defread_file(file_path):"......
  • Python使用PyCharm创建一个简单的Qt Widgets应用程序-hello_world.py
    """CreateaSimpleQtWidgetsApplication"""importrandomimportsysfromPySide6importQtCore,QtWidgets#MainClassclassMyWidget(QtWidgets.QWidget):def__init__(self):super().__init__()self......
  • Python使用PyCharm创建一个简单的Qt Quick应用程序-hello_world_quick.py
    """CreateaSimpleQuickApplication"""importsysfromPySide6.QtGuiimportQGuiApplicationfromPySide6.QtQmlimportQQmlApplicationEngineQML="""importQtQuickimportQtQuick.ControlsimportQtQuick.Lay......
  • 扩展【从0制作自己的ros导航小车】C++_ROS_QT5联合编译,简单界面为ROS开发增添交互
    从0制作自己的ros导航小车前言一、环境搭建二、联合编译三、测试前言前面已经实现了导航功能,对于之后的一些开发,有交互能力是比较重要的,比如小车上连接一块屏幕,通过屏幕来选择模式,可视化等等。QT是不错的选择,但是需要做一些额外的工作,让QT与ROS能够建立联系,实现通信......
  • QT6配置opencv
    参考一个博主的步骤:Qt6MinGW+OpenCV+CMake+Windows11环境搭建详细记录_qt6安装opencv-CSDN博客链接放在这里了QT6默认大家都已经安装好了,没安装的可以去搜索QT6安装的教程1.安装opencv:Releases-OpenCV安装:我安装的opencv默认在C盘,根据自己安装的路径找到opencv目录下......
  • Qt自定义TreeWidget,实现展开折叠按钮在右侧,且一条竖直线上对齐
    效果如下:图片随便找的,可能需要调下样式,代码复制可用,留给有需要的人。 #ifndefCustomTreeWidget_h__#defineCustomTreeWidget_h__#include<QTreeWidget>#include<QPushButton>classCCustomTreeWidget:publicQTreeWidget{ Q_OBJECTpublic: CCustomTreeW......
  • 【QT】Qt 音视频
    Qt音视频Qt音视频1.Qt音频2.Qt视频Qt音视频在Qt中,音频主要是通过QSound类来实现。但是需要注意的是QSound类只支持播放wav格式的音频文件。也就是说如果想要添加音频效果,那么首先需要将非wav格式的音频文件转换为wav格式。通过帮助手册查看QSo......
  • 一个简单的录音软件(利用QT录音,ffmpeg进行音频重采样,fdk-aac编码)
             录音软件是一种非常有用的工具,可以帮助我们记录和存储语音信息。在本文中,我们将介绍一个简单的录音软件,该软件利用QT进行录音,使用ffmpeg进行音频重采样,并使用fdk-aac编码。一、 环境介绍  1、QT版本:QT5.12.62、编译器: MSVC2017643、ffmpeg版......
  • 利用QT和FFmpeg实现一个简单的视频播放器
              在当今的多媒体世界中,视频播放已成为不可或缺的一部分。从简单的媒体播放器到复杂的视频编辑软件,视频解码和显示技术无处不在。本示例使用Qt和FFmpeg构建一个简单的视频播放器。利用ffmpeg解码视频,通过QWidget渲染解码后的图像,支持进度条跳转、进度条显示,......
  • mqtt订阅和发布
    importpaho.mqtt.clientasmqttimporttimeMQTTHOST="192.168.0.4"MQTTPORT=1883mqttClient=mqtt.Client()#连接MQTT服务器defon_mqtt_connect():mqttClient.connect(MQTTHOST,MQTTPORT,60)mqttClient.loop_start()#publish消息defon_publish(t......