自定义控件和事件过滤器两种方式实现鼠标按下、移动、释放事件

Qt中处理鼠标事件的两种方法

 

                                                 

这是最终要实现的效果,当鼠标在红色,绿色方块上按下并拖动时,这两会随之移动

红色采用事件过滤器;

绿色采用重写自定义控件。

目录

 方法一:事件过滤器

        先创建lbl_2并设计其颜色大小:

        为lbl_2安装事件过滤器:

        事件过滤器

插入:鼠标跟踪

 方法二:自定义控件

鼠标跟踪: 

globalpos与pos

而在这里globalpos和pos却有不同 


 方法一:事件过滤器

        先创建lbl_2并设计其颜色大小:

    lbl_2=new QLabel(widget);
    lbl_2->setFrameShape(QFrame::Box);
    lbl_2->setFixedSize(100,100);
    lbl_2->setStyleSheet("background-color:red");

        为lbl_2安装事件过滤器:

 lbl_2->installEventFilter(this);

        事件过滤器

需要注意的是,在这里需要将QEvent类型的event转化为QMouseEvent

因为Qt中的事件对象QEvent是一个通用的事件对象,包含了许多类型的事件,但它并不提供事件的具体细节。

而QMouseEvent获取有关鼠标事件的信息;

例如在这里我们可以访问

  • globalPos():鼠标事件的全局位置,即鼠标在屏幕上的坐标。
  • pos():鼠标事件的位置,即鼠标在目标对象(lbl_2)内的相对坐标。
bool press_move_release::eventFilter(QObject *watch, QEvent *event)
{
    if(watch==lbl_2)//当监督对象为lbl_2时
    {
        //如果事件为鼠标按下
        if(event->type()==QEvent::MouseButtonPress)
        {
            
              QMouseEvent* mouseevent=static_cast<QMouseEvent*>(event);
            presspos=mouseevent->globalPos();
            wndpos=lbl_2->pos();
        }
        //如果事件是鼠标移动
        else if(event->type()==QEvent::MouseMove)
        {
            qDebug()<<"mousemove";
            QMouseEvent* mouseevent=static_cast<QMouseEvent*>(event);
            QPoint now=wndpos+(mouseevent->globalPos()-presspos);
            lbl_2->move(now);

        }
        //如果事件是鼠标释放
        else if(event->type()==QEvent::MouseButtonRelease)
        {
            qDebug()<<"1";

        }
    }

}

插入:鼠标跟踪

以上的事件过滤器默认状态下需要鼠标保持按下的状态下,系统才会调用mousemoveEvent事件

鼠标跟踪它允许应用程序捕获和响应鼠标指针的移动,即使没有鼠标按钮按下。默认情况下,鼠标跟踪通常是禁用的,这意味着只有在鼠标按钮按下时才会触发鼠标事件。启用鼠标跟踪后,应用程序将在鼠标移动时收到相应的事件,而无需按下鼠标按钮。

this->setMouseTracking(true);

在这里我们无需调用鼠标跟踪就可以达到我们想要的效果,而鼠标跟踪的使用我们稍后会在自定义控件里讲到。

 方法二:自定义控件

        自定义控件直接应用程序中创建用户界面元素,允许完全控制事件处理

 在这里我们创建了一个名为mc的控件,并让他继承QLabel类

用了鼠标按下,移动,释放三个事件

mc::mc(QWidget *parent): QLabel {parent}
{
    //鼠标跟踪
    this->setMouseTracking(true);
}
//鼠标按下
void mc::mousePressEvent(QMouseEvent *event)
{
    qDebug()<<"mousepress";
    //记录按下时鼠标坐标
    mousepos=event->globalPos();
    //记录按下时方块坐标
    wndpos=this->pos();
    qDebug()<<wndpos;
    qDebug()<<mousepos;
}
//鼠标移动
void mc::mouseMoveEvent(QMouseEvent *event)
{
    qDebug()<<"mousemove";
    //方块原来坐标+(现在鼠标坐标与原来鼠标坐标的差)
    this->move(wndpos+event->globalPos()-mousepos);
}

//鼠标释放
void mc::mouseReleaseEvent(QMouseEvent *event)
{

}

鼠标跟踪: 

自定义不像事件过滤器,这三个函数是独立的,也就是说当鼠标移动至方块上时就会触发mouseMoveEvent事件,导致方块抖动。

而这时候关掉鼠标跟踪,也就意味着只有在鼠标按钮按下时才会触发鼠标事件。

从而达到我们需要的按下拖动效果。

globalpos与pos

        在处理方块拖动后的位置,我们用到了鼠标按下时的坐标,鼠标按下时方块的坐标,鼠标拖动后的坐标。

        在这里我们用到了鼠标按下时的坐标与鼠标拖动后的坐标的差,这即为方块应该移动的方向距离。

而在这里globalpos和pos却有不同 

        如果我们用globalpos来表示二者之差:

//鼠标按下
void mc::mousePressEvent(QMouseEvent *event)
{
    qDebug()<<2;
    //记录按下时鼠标坐标
    mousepos=event->globalPos();
    //记录按下时方块坐标
    wndpos=this->pos();
    qDebug()<<wndpos;
    qDebug()<<mousepos;

}
//鼠标移动
void mc::mouseMoveEvent(QMouseEvent *event)
{
    qDebug()<<"mousemove";
    //方块原来坐标+(现在鼠标坐标与原来鼠标坐标的差)
    this->move(wndpos+event->globalPos()-mousepos);
}

 代码正常运行,也达到了想要的效果

        而用pos来表示却:

//鼠标按下
void mc::mousePressEvent(QMouseEvent *event)
{
    qDebug()<<2;
    //记录按下时鼠标坐标
    mousepos=event->pos();
    //记录按下时方块坐标
    wndpos=this->pos();
    qDebug()<<wndpos;
    qDebug()<<mousepos;

}
//鼠标移动
void mc::mouseMoveEvent(QMouseEvent *event)
{
    qDebug()<<"mousemove";
    //方块原来坐标+(现在鼠标坐标与原来鼠标坐标的差)
    this->move(wndpos+event->pos()-mousepos);
}

方块会抖动

pos造成抖动

        当使用pos()获取鼠标事件的坐标时,会将鼠标事件的坐标转换为相对于mc控件的局部坐标。这意味着鼠标事件的坐标是相对于mc控件内部的,而不是全局坐标。

        如果使用相对坐标来计算新的控件位置,相对坐标受到控件父级或布局的影响,可能会引起计算错误。

        而全局坐标表示鼠标事件的位置在整个屏幕上的坐标,而不受控件的影响。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在Qt中,可以通过自定义件的鼠标事件实现鼠标操作的响应。下面是一般的步骤: 1. 继承QWidget或QAbstractButton等基类,创建自定义件类。 2. 重写自定义件类的鼠标事件处理函数,如mousePressEvent、mouseReleaseEvent、mouseMoveEvent等。 3. 在重写的鼠标事件处理函数中,根据需要实现相应的功能逻辑。 例如,如果你想在自定义件上实现鼠标点击事件的响应,可以按照以下步骤进行: 1. 创建一个继承自QWidget的自定义件类,例如MyWidget。 2. 在MyWidget类中重写mousePressEvent函数,该函数会在鼠标按下时被调用。 3. 在mousePressEvent函数中实现你想要的功能,比如显示一个提示框或改变件的状态等。 下面是一个简单的示例代码: ```cpp #include <QWidget> #include <QMouseEvent> class MyWidget : public QWidget { Q_OBJECT public: MyWidget(QWidget *parent = nullptr) : QWidget(parent) {} protected: void mousePressEvent(QMouseEvent *event) override { if (event->button() == Qt::LeftButton) { // 左键点击事件处理逻辑 // 例如显示一个提示框 qDebug() << "Left button pressed!"; } // 调用父类的事件处理函数,保证其他事件正常处理 QWidget::mousePressEvent(event); } }; ``` 在上述示例中,我们重写了MyWidget类的mousePressEvent函数,并在函数中判断鼠标按下的按钮是否为左键,如果是则输出一条调试信息。同时,我们还调用了父类的mousePressEvent函数,以确保其他事件的正常处理。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值