analogClock程序解析 part04
窗体设置无边框
前面,我们实现了时钟。这个时钟的显示是带有标题栏,时钟显示在窗体的中央。
现在,我们去掉标题栏。可以在构造函数中,增加下面代码来实现。
analogClock::analogClock(QWidget *parent)
: QWidget(parent,Qt::FramelessWindowHint| Qt::WindowSystemMenuHint)
这种在构造函数中,直接用
Qt::FramelessWindowHit属性,
窗口设置了无边框Qt::FramelessWindowHint,窗口界面不会自动刷新,也不能移动,也不能关闭,也不能缩放。
鼠标移动窗体
由于现在设置了无边框窗体,程序不能响应鼠标操作。因此,必须添加鼠标响应函数。
首先,在analogClock.h程序中,重载两个鼠标事件函数,代码为:
protected:
void mouseMoveEvent(QMouseEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
其次,我们必须在analogClock.h中,增加一个QPoint类的成员变量,代码为:
private:
QPoint m_dragPosition;
我们定义成员变量的类型是QPoint,private表示私有成员。
然后,鼠标按下操作,在analogClock.cpp程序中,添加如下实现代码:
void analogClock::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton) {
m_dragPosition = event->globalPos() -
frameGeometry().topLeft();
event->accept();
}
}
这个代码是实现鼠标按下操作。通过event->button()的值等于鼠标左键按下时,记下当前鼠标在屏幕上的像素值,并保存到成员变量中。
event->button() : 返回产生事件的按钮
event->globalPos()获取的鼠标位置是鼠标偏离电脑屏幕左上角(x=0,y=0)的位置(像素值)。
frameGeometry().topLeft()是不含边框的窗口矩形的左上角像素值。
event->accept()函数是默认处理过程。
综上所述,鼠标左键按下时,成员变量m_dragPosotion记录了鼠标当前在屏幕上距离无边框时钟窗口左上角的相对坐标(像素值)。
然后,鼠标移动时,在analogClock.cpp程序中,添加如下代码:
void analogClock::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons() & Qt::LeftButton){
move(event->globalPos() - m_dragPosition);
event->accept();
}
}
这段程序,采用了event->buttons() 函数。
这里要注意event->buttons() 函数与event->button() 函数的区别。
event->button() 返回产生事件的按钮;
event->buttons() 返回产生事件的按钮状态,函数返回当前按下的所有按钮,按钮状态可以是
Qt::LeftButton,Qt::RightButton,Qt::MidButton或运算组合
例如:
鼠标左键已经处在按下的状态,
此时如果移动鼠标,会产生鼠标的move事件,button()返回Qt::NoButton,buttons()返回LeftButton。
再按下鼠标右键,会触发鼠标的press事件,button返回RightButton,buttons返回LeftButton | RightButton
再移动鼠标,会发生move事件,button返回Qt::NoButton,buttons返回LeftButton | RightButton
再松开左键,会发生Release事件,button返回LeftButton,buttons返回RightButton
简而言之,button返回“发生了此事件的按钮”,buttons返回"发生事件时还处于按下状态的按钮"
event->buttons() & Qt::LeftButton就是判断鼠标移动过程中,如果鼠标左键是按下状态,则用移动函数move()移动窗口。
程序运行结果为:
透明背景
在analogClock.cpp的构造函数中,增加一个函数,可以设置背景为透明颜色,代码为:
setAttribute(Qt::WA_TranslucentBackground);
添加这行代码后,程序运行的结果为:
此时,鼠标左键在透明区域,将选择不到任何对象移动时钟。鼠标左键必须选择黑线或其他有颜色的对象或者字体,才能移动时钟。
添加关闭时钟
由于目前的时钟,关闭了标题栏,因此,不能关闭程序。
为此,在构造函数中,我们添加一个退出操作。
这里采用右键菜单的形式,代码为:
QAction *quitAction = new QAction(tr("E&xit"),this);
quitAction->setShortcut(tr("Ctrl+Q"));
connect(quitAction,
&QAction::triggered,
qApp,
&QCoreApplication::quit);
addAction(quitAction);
第1句,是新建一个QAction的指针变量quitAction,构造时,初始化菜单的显示。
第2句,是增加菜单的快捷键,即Ctrl+Q,键盘上的ctrl键和Q键同时按,通过setShortcut()函数,加上快捷键。
第3句,建立信号与槽函数的关系。用connect()函数来实现,qApp是指向Application的全局变量。QCoreApplication::quit是退出函数。
第4句,将quitAction添加到程序中来。
编译,运行,发现可以用Ctrl+Q退出时钟程序了。
添加鼠标右键弹出菜单
现在,我们希望按鼠标右键,弹出退出菜单。可以添加1行代码,就可完成,代码为:
setContextMenuPolicy(Qt::ActionsContextMenu);
这里采用setContextMenuPolicy()函数来完成这个鼠标右键弹出菜单功能。
QWidget及其子类都可有右键菜单,首先设置QWidget与右键菜单有关的函数setContextMenuPolicy(),属性对应项为contextmenuPolicy。
Qt::ContextMenuPolicy枚举类型包括:Qt::DefaultContextMenu,
Qt::NoContextMenu
Qt::PreventContextMenu
Qt::ActionsContextMenu
Qt::CustomContextMenu
默认是 Qt::DefaultContextMenu。
它是利用右键菜单事件contextMenuEvent()来处理。
鼠标所在位置自动显示提示字符串
当鼠标移动到程序所在位置时,只要鼠标停留一会,可以自动显示提示字符串tooltip,可采用下面代码,
setToolTip(tr("按下鼠标左键移动时钟.\n"
"鼠标右键可以关闭时钟."));
即采用setToolTip()函数来完成。tr()函数里面是字符串,如果分行显示,如上面代码所示。
鼠标右键弹出菜单,鼠标所在位置显示提示字符串如下图所示。