发生鼠标事件,当在 Widget 内按下 (或释放) 鼠标按钮 (或移动鼠标光标) 时。
才发生鼠标移动事件当按下鼠标按钮时,除非启用鼠标跟踪采用?QWidget::setMouseTracking?().
Qt 自动抓取鼠标当在 Widget 内按下鼠标按钮时;Widget 将继续接收鼠标事件,直到最后释放鼠标按钮。
鼠标事件包含特殊接受标志 (指示接收者是否想要事件)。应该调用?ignore?() 若鼠标事件未被 Widget 所处理。鼠标事件会沿父级 Widget 链向上传播,直到小部件接受它采用?accept?(),或由事件过滤器消耗掉它。
注意?: 若鼠标事件被传播给?widget?其中?Qt::WA_NoMousePropagation?有设置,该鼠标事件将不会沿父级 Widget 链向上进一步传播。
可以找到键盘修饰符键的状态通过调用?modifiers()?函数,继承自?QInputEvent?.
函数?pos?(),?x?(),和?y?() 给出光标相对于接收鼠标事件的小部件的位置.如果由于鼠标事件而移动小部件,请使用?globalPos?() 返回的全局位置以避免晃动。
QWidget::setEnabled?() 函数可用于启用 (或禁用) 小部件的鼠标事件和键盘事件。
重实现?QWidget?事件处理程序, QWidget::mousePressEvent (), QWidget::mouseReleaseEvent (), QWidget::mouseDoubleClickEvent (),和?QWidget:?:mouseMoveEvent?() 以在自己的 Widget 中接收鼠标事件。
实现以下功能
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include<QMouseEvent>
#include<QMessageBox>
#include<QLabel>
#include<QStatusBar>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QLabel *statusLabel;
QLabel *mouseLabel;
void dispPicture();
protected:
void mouseMoveEvent(QMouseEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
// MainWindow构造函数
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) // 继承了QWidget类,创建一个主窗口
, ui(new Ui::MainWindow) // 初始化用户界面
{
ui->setupUi(this); // 配置用户界面
// 创建两个标签,用于显示鼠标的坐标
statusLabel=new QLabel("鼠标在当前窗口坐标为:"); // 鼠标当前位置的标签
statusLabel->setFixedWidth(200); // 设置标签宽度为200像素
mouseLabel=new QLabel(); // 鼠标位置的显示标签
mouseLabel->setFixedWidth(200); // 设置标签宽度为200像素
// 将这两个标签添加到状态栏
statusBar()->addPermanentWidget(statusLabel);
statusBar()->addPermanentWidget(mouseLabel);
// 开启鼠标追踪,即可以获取鼠标的移动事件
this->setMouseTracking(true);
resize(800,600); // 设置窗口大小为800x600像素
// 加载并显示图片
dispPicture();
}
// MainWindow析构函数
MainWindow::~MainWindow()
{
delete ui; // 删除用户界面对象,释放内存
}
// 鼠标移动事件处理函数
void MainWindow::mouseMoveEvent(QMouseEvent *e)
{
// 更新鼠标位置的显示标签内容
mouseLabel->setText("("+QString::number(e->x())+","+QString::number(e->y())+")");
}
// 鼠标按下事件处理函数
void MainWindow::mousePressEvent(QMouseEvent *e)
{
QString str="("+QString::number(e->x())+","+QString::number(e->y())+")"; // 鼠标坐标字符串
if(e->button()==Qt::LeftButton) // 如果按下的是左键
{
statusBar()->showMessage("按下左键"+str); // 在状态栏显示消息
}
else if(e->button()==Qt::RightButton) // 如果按下的是右键
{
statusBar()->showMessage("按下右键"+str); // 在状态栏显示消息
}
else if(e->button()==Qt::MidButton) // 如果按下的是中键
{
statusBar()->showMessage("按下中键"+str); // 在状态栏显示消息
}
}
// 鼠标释放事件处理函数
void MainWindow::mouseReleaseEvent(QMouseEvent *e)
{
QString str="("+QString::number(e->x())+","+QString::number(e->y())+")"; // 鼠标坐标字符串
statusBar()->showMessage("用户已经释放鼠标坐标"+str); // 在状态栏显示消息
}
// 显示图片函数
void MainWindow::dispPicture()
{
QString str("D:/wallhaven-9d5x5k.png"); // 图片路径字符串
QImage *image=new QImage; // 创建QImage对象用于加载图片
QLabel *imageLabel=new QLabel(this); // 创建QLabel对象用于显示图片
imageLabel->move(20,20); // 设置图片标签的位置,距离窗口左上角20,20像素的位置开始显示图片
imageLabel->setFixedSize(700,400); // 设置图片标签的大小为700x400像素,即图片的大小为700x400像素
if(!(image->load(str))) // 如果图片加载失败(例如文件不存在、文件格式不正确等)
{
QMessageBox::information(this,"失败","图片加载失败"); // 弹出信息框提示用户图片加载失败
delete image; // 删除QImage对象,释放内存
return; // 结束函数执行,不再继续执行后续代码,因为已经无法加载图片了。
}
imageLabel->setPixmap(QPixmap::fromImage(*image)); // 将加载的图片转换为QPixmap对象,然后设置到QLabel对象上,显示图片。这里使用*image是因为QImage是const的,不能直接赋值给非const对象。需要先解引用一下。
}
代码提供了一个名为MainWindow
的类,它是QMainWindow
的子类。这个类主要处理了鼠标的移动、点击事件,以及显示图片的功能。
构造函数:
MainWindow
的构造函数中,首先初始化了用户界面,然后设置了鼠标追踪,并设置了窗口的大小。鼠标移动事件处理函数:
鼠标按下事件处理函数:
鼠标释放事件处理函数:
显示图片函数:
从代码中可以看出,这个MainWindow
类主要实现了鼠标事件的响应和图片的加载与显示功能。这些功能都是通过重写QMainWindow
中的事件处理函数来实现的。同时,代码中也使用了Qt的一些常用组件,如QLabel
、QImage
等来进行界面和图片的操作。
将给定的小部件永久地添加到这个状态栏,如果小部件还不是这个QStatusBar对象的子部件,则重新定位它。随着状态栏的增长和收缩,stretch参数用于计算给定小部件的合适大小。默认的拉伸因子是0,即给小部件一个最小的空间。
永久意味着小部件可能不会被临时消息所掩盖。它位于状态栏的最右边。
此属性保存是否为小部件启用鼠标跟踪
如果禁用了鼠标跟踪(默认值),则当移动鼠标时至少按下一个鼠标按钮时,小部件仅接收鼠标移动事件。
如果启用了鼠标跟踪,即使没有按下按钮,小部件也会接收鼠标移动事件。
隐藏正常状态指示,并在指定的毫秒数(超时)内显示给定消息。如果timeout为0(默认值),则消息保持显示,直到clearMessage()槽被调用,或者直到showMessage()槽被再次调用以更改消息。
请注意,调用showMessage()是为了显示工具提示文本的临时解释,因此传递超时0不足以显示永久消息。
从具有给定文件名的文件中加载图像。如果图像已成功加载,则返回true;否则将使图像无效并返回false。
加载程序尝试使用指定的格式读取图像,例如PNG或JPG。如果没有指定格式(这是默认的),它会根据文件的后缀和头自动检测。具体操作请参见QImageReader::setAutoDetectImageFormat()。
当按下或释放按键时,按键事件将发送到具有键盘输入焦点的小部件。
密钥事件包含一个特殊的接受标志,该标志指示接收方是否将处理密钥事件。默认情况下,QEvent::KeyPress?和?QEvent::KeyRelease?设置了此标志,因此在对键事件执行操作时无需调用?accept?()。对于?QEvent::ShortcutOverride,接收方需要显式接受事件以触发覆盖。对关键事件调用?ignore?() 会将其传播到父小部件。该事件在父小部件链上向上传播,直到小部件接受它或事件过滤器使用它。
QWidget::setEnabled?() 函数可用于启用 (或禁用) 小部件的鼠标事件和键盘事件。
事件处理程序?QWidget::keyPressEvent?(),?QWidget?::keyReleaseEvent (), QGraphicsItem::?keyPressEvent () 和 QGraphicsItem?:?:keyReleaseEvent?() 接收键事件。
实现以下功能,可以上下左右移动
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QKeyEvent>
#include<QPaintEvent>
#include<QPainter>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void drawPixFunc();
void paintEvent(QPaintEvent *);
void keyPressEvent(QKeyEvent *);
private:
Ui::Widget *ui;
QPixmap *pix;
QImage image;
int startX;
int startY;
int width;
int height;
int step;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
// Widget类的构造函数
Widget::Widget(QWidget *parent)
: QWidget(parent) // 调用基类QWidget的构造函数
, ui(new Ui::Widget) // 初始化用户界面
{
ui->setupUi(this); // 设置用户界面
// 自动填充背景色为白色
setAutoFillBackground(true);
// 设置窗口的背景颜色为白色
QPalette p=this->palette();
p.setColor(QPalette::Window,Qt::white);
setPalette(p);
// 设置窗口的最小和最大尺寸为800x600
setMinimumSize(800,600);
setMaximumSize(800,600);
// 获取窗口的宽度和高度
width=size().width();
height=size().height();
// 创建一个与窗口大小相同的白色位图
pix=new QPixmap(width,height);
pix->fill(Qt::white);
// 从指定路径加载一张图片
image.load("D:/file.jpg");
// 初始化图片显示位置的起始点为(30,30)
startX=30;
startY=30;
step=30;
// 调用drawPixFunc函数,开始在位图上绘制图片的边框和对角线网格
drawPixFunc();
}
// Widget类的析构函数,负责释放创建的资源
Widget::~Widget()
{
delete ui; // 删除用户界面对象,释放内存
}
// drawPixFunc函数,绘制位图上的网格和图片
void Widget::drawPixFunc()
{
pix->fill(Qt::green); // 将位图填充为绿色,作为背景色
QPainter *painter=new QPainter; // 创建一个QPainter对象,用于绘图
QPen pen(Qt::DashDotLine); // 创建一个画笔,用于绘制网格线
// 绘制水平网格线,间距为step像素,从左到右绘制,直到达到窗口宽度为止
for(int i=step;i<width;i=i+step)
{
painter->begin(pix); // 开始绘图到指定的位图上
painter->setPen(pen); // 设置画笔颜色为网格线颜色
painter->drawLine(QPoint(i,0),QPoint(i,height)); // 绘制一条从顶部到底部的水平线
painter->end(); // 结束绘图操作
}
// 绘制垂直网格线,间距为step像素,从上到下绘制,直到达到窗口高度为止
for(int i=step;i<height;i=i+step)
{
painter->begin(pix); // 开始绘图到指定的位图上
painter->setPen(pen); // 设置画笔颜色为网格线颜色
painter->drawLine(QPoint(0,i),QPoint(width,i)); // 绘制一条从左到右的垂直线
painter->end(); // 结束绘图操作
}
// 在网格中心位置绘制图片,起始点为(startX, startY)位置,大小为图片的实际大小(width和height已定义为窗口大小)
painter->begin(pix); // 开始绘图到指定的位图上
painter->drawImage(QPoint(startX,startY),image); // 绘制图片到指定位置和大小
painter->end(); // 结束绘图操作
}
// Widget 类的 paintEvent 函数,用于在画布上绘制图片
void Widget::paintEvent(QPaintEvent *)
{
// 创建一个 QPainter 对象,用于在画布上绘制
QPainter pt;
// 在当前对象上开始绘制
pt.begin(this);
// 在画布上绘制 pixmap 图片,起始位置为 (0,0)
pt.drawPixmap(QPoint(0,0),*pix);
// 结束绘制
pt.end();
}
// Widget 类的 keyPressEvent 函数,用于处理键盘按键事件
void Widget::keyPressEvent(QKeyEvent *e)
{
// 检查按键是否为左键、右键、上键或下键
if(e->key() == Qt::Key_Left) {
// 处理左键事件
startX = (startX - step < 0) ? startX : startX - step;
} else if(e->key() == Qt::Key_Right) {
// 处理右键事件
startX = (startX + step > width) ? startX : startX + step;
} else if(e->key() == Qt::Key_Up) {
// 处理上键事件
startY = (startY - step < 0) ? startY : startY - step;
} else if(e->key() == Qt::Key_Down) {
// 处理下键事件
startY = (startY + step > height) ? startY : startY + step;
}
// 调用 drawPixFunc 函数进行绘制操作
drawPixFunc();
// 更新界面,使更改可见
update();
}
代码分析: