整理:Qt编写窗体应用时用到的一些功能


整理使用Qt编写窗体应用时用到的一些功能。

1.隐藏任务栏图标

使用QWidget类中的setWindowFlags方法:

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
	...
	this->setWindowFlags(Qt::Tool | Qt::X11BypassWindowManagerHint);	//隐藏任务栏图标
	...
}

2.显示系统托盘图标

通过QSystemTrayIcon类实现此功能:设置一全局指针QSystemTrayIcon *在构造函数中创建系统托盘图标。

//在头文件中
...
class QSystemTrayIcon;
class QMenu;
...
class Widget : public QWidget
{
	...
private:
	QSystemTrayIcon *m_sys_tray;	//系统托盘图标
	QMenu *m_sys_tray_menu;			//系统托盘弹出菜单
	...
}
//在源文件中
...
#include <QSystemTrayIcon>
#include <QMenu>
...
Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
	...
	m_sys_tray = new QSystemTrayIcon;				//新建一个QSystemTrayIcon指针
	QIcon icon(":/img/images/sysTray.png");			//系统托盘图标
	m_sys_tray->setIcon(icon);						//设置系统托盘图标
	m_sys_tray->setToolTip("This is a demo.");		//设置系统托盘图标提示
	m_sys_tray = new QMenu;							//新建一个QMenu指针
	m_sys_tray_menu->addAction(ui->actionQuit);		//为菜单添加菜单项
	m_sys_tray->setContextMenu(m_sys_tray_menu);	//为系统托盘设置弹出菜单
	m_sys_tray->show();								//显示系统托盘
	m_sys_tray->showMenssage("Tips", "I'm here!");	//设置系统托盘信息提示
	...
}

3.窗体始终置顶

通过QWidget类中的setWindowFlagssetWindowFlag方法,设置Qt::WindowStaysOnTopHint枚举项:

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
	...
	this->setWindowFlag(Qt::WindowStaysOnTopHint);	//设置窗体始终置顶
	...
}

4.窗体背景透明及无边框

通过QWidget类中的setWindowFlagssetWindowFlag方法,设置Qt::FramlessWindowHint枚举项,使窗体无边框,同时需要QWidget类中的setAttribute方法设置Qt::WA_TranslucentBacground枚举项使窗体背景透明。
需要注意的是,设置Qt::FramlessWindowHint会使窗体无法移动和改变大小,因为Qt是通过检测鼠标移动窗体的边框来实现窗体移动和改变大小,窗体无边框自然无法移动窗体和改变大小,一般需要配合第5个功能。而且由于关闭、最大化、最小化灯功能也在边框上,因此需要设置系统托盘图标之类以满足能使窗体关闭,程序结束的功能。若使窗口关闭,需要使用setAttribute方法设置Qt::WA_QuitOnClose枚举项,以使窗体正常关闭以及程序正常退出。

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
	...
	this->setWindowFlag(Qt::FramlessWindowHint);		//设置窗体无边框
	this->setAttribute(Qt::WA_TranslucentBackground);	//设置窗体背景透明
	this->setAttribute(Qt::WA_QuitOnClose);
	...
}

5.窗体无边框时实现移动功能

为实现窗体无边框移动,需要重写QWidget类中的mousePressEvent(QMouseEvent*), mouseMoveEvent(QMouseEvent*), mouseReleaseEvent(QMouseEvent*)三个方法。
首先设置一个全局变量m_is_left_button_pressed记录鼠标左键的状态,只有鼠标左键在窗体的有效区域内(即能够触发mousePressEvent方法的区域)单击才会为true,否则为false
然后鼠标左键在窗体有效区域内单击时记录其相对窗体的坐标,记录在m_mouse_pos中;
根据鼠标的移动更新窗体的位置,使用QWidget中的move方法。

void Widget::mousePressEvent(QMouseEvent *event)
{
	if(event->button() == Qt::LeftButton){			//若鼠标左键暗笑
		m_is_left_button_pressed = true;			//修改状态
		m_mouse_pos = event->pos();					//记录相对坐标
	}
}

void Widget::mouseMoveEvent(QmouseEvent *event)
{
	if(m_is_left_button_pressed){					//若鼠标左键依然按下
		move(event->globalPos() - m_mouse_pos);		//移动窗体
	}
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
	if(event->button() == Qt::LeftButton){			//若鼠标左键释放
		m_is_left_button_pressed = false;			//修改状态
	}
}

6.窗体贴边隐藏

窗体贴边隐藏需要重写QWidget类中的mouseMoveEvent(QMouseEvent*), enterEvent(QEvent*), leaveEvent(QEvent*)方法。
首先,通过鼠标移动的位置判断窗体的位置,这里创建一个函数isWindowInScreen来实现,这里窗体的位置通过设置一个枚举类来实现,并设置一全局变量记录窗体位置:

class Widget : public QWidget
{
	...
private:
	//窗体位置枚举类型
	enum WindowPosition {
		WP_None = 0,						//窗体在屏幕中央
		WP_Left,							//窗体贴左侧
		WP_Right,							//窗体贴右侧
		WP_Up,								//窗体贴上侧
		WP_Down								//窗体贴下侧
	};
	WindowPosition m_window_position;		//记录窗体位置
	int m_screen_width;						//屏幕水平分辨率
	int m_screen_height;					//屏幕垂直分辨率
	...
}

另外需要获取用户的屏幕分辨率,记录在全局变量m_screen_widthm_screen_height中:

Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget)
{
	...
	QRect rect = QGuiApplication::primaryScreen()->geometry();
	m_screen_width = rect.width();
	m_screen_height = rect.height();
	...
}

isWindowInScreen实现如下:

//若窗体不在屏幕中央,返回false;否则返回true
bool isWindowInScreen(QPoint pos)
{
	if(pos.x() < 5){
		m_window_position = Widget::WP_Left;
		return false;
	} else if(pos.x() > m_screen_width - 5){
		m_window_position = Widget::WP_Right;
		return false;
	} else if(pos.y() < 5){
		m_window_position = Widget::WP_Up;
		return false;
	} else if(pos.y() > m_screen_height - 5){
		m_window_position = Widget::WP_Down;
		return false;
	} else {
		m_window_position = Widget::WP_None;
		return true;
	}
}

然后根据判断位置移动窗体:

void Widget::mouseMoveEvent(QMouseEvent *event)
{
	if(m_is_left_button_pressed){
		if(!isWindowInScreen(event->globalPos())){
			int x = event->globalX();
			int y = event->globalY();
			if(m_window_position == Widget::WP_Left){
				move(0, y - m_mouse_pos.y());
			} else if(m_window_position == Widget::WP_Right){
				move(m_screen_width - width(), y - m_mouse_pos.y());
			} else if(m_window_position == Widget::WP_Up){
				move(x - m_mouse_pos.x(), 0);
			} else if(m_window_position == Widget::WP_Down){
				move(x - m_mouse_pos.x(), m_screen_height - height());
			}
		} else {
			move(event->globalPos() - m_mouse_pos);
		}
	}
}

并在enterEventleaveEvent中实现鼠标进入窗体和离开窗体应该实现的功能,即窗体贴边隐藏动画:

void Widget::enterEvent(QEvent *event)
{
    Q_UNUSED(event);
    if(m_window_position != Widget::WP_None){                       //若窗体不在屏幕中央,动画显示窗体
        QPropertyAnimation *animation = new QPropertyAnimation(this, "geometry");
        int x = this->x();
        int y = this->y();
        int width = this->width();
        int height = this->height();
        animation->setStartValue(QRect(x, y, width, height));
        if(m_window_position == Widget::WP_Left){
            animation->setEndValue(QRect(0, y, width, height));
        } else if(m_window_position == Widget::WP_Right){
            animation->setEndValue(QRect(m_screen_width - width, y, width, height));
        } else if(m_window_position == Widget::WP_Up){
            animation->setEndValue(QRect(x, 0, width, height));
        } else if(m_window_position == Widget::WP_Down){
            animation->setEndValue(QRect(x, m_screen_height - height, width, height));
        }
        animation->setDuration(250);
        animation->start(QAbstractAnimation::DeleteWhenStopped);
    }
}

void Widget::leaveEvent(QEvent *event)
{
    Q_UNUSED(event);
    if(m_window_position != Widget::WP_None){                       //若窗体不在屏幕中央,动画隐藏窗体
        QPropertyAnimation *animation = new QPropertyAnimation(this, "geometry");
        int x = this->x();
        int y = this->y();
        int width = this->width();
        int height = this->height();
        animation->setStartValue(QRect(x, y, width, height));
        if(m_window_position == Widget::WP_Left){
            animation->setEndValue(QRect(0 - width + 5, y, width, height));
        } else if(m_window_position == Widget::WP_Right){
            animation->setEndValue(QRect(m_screen_width - 5, y, width, height));
        } else if(m_window_position == Widget::WP_Up){
            animation->setEndValue(QRect(x, 0 - height + 5, width, height));
        } else if(m_window_position == Widget::WP_Down){
            animation->setEndValue(QRect(x, m_screen_height - 5, width, height));
        }
        animation->setDuration(250);
        animation->start(QAbstractAnimation::DeleteWhenStopped);
    }
}

7.整体程序

https://download.csdn.net/download/alazyperson/14020019

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值