zoukankan      html  css  js  c++  java
  • GUI 编程 —— QT 的 QSlider 鼠标点击定位问题

    这几天打算封装 libvlc 实现一个简单的播放器操作类,用 QT 写 UI 测试程序的时候,发现播放进度的显示控件 QSlider 在处理鼠标点击时,并不能直接定位到鼠标按下的位置。为解决这一问题,我在网上看了几篇博文提供的解决办法,但实现的效果并不理想,主要的问题是:鼠标点击定位时,出现位置偏差。鉴于这,我提供了如下的解决办法。

    1. 为 QSlider 控件设置事件过滤

    在 QSlider 控件父窗口初始化的时候设置(比如我的代码中就在 Widget 构造函数中设置):

    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        ......
        ui->hSlider_duration->installEventFilter(this);
        ......
        ui->hSlider_volume->installEventFilter(this);
        ......
    }
    

    2. 重载 eventFilter() 接口

    对 QSlider 控件的父级窗口重载 eventFilter() 接口,然后针对 鼠标左键的按下事件 进行过滤判断操作:

    bool Widget::eventFilter(QObject * watched, QEvent * event)
    {
        if ((event->type() == QEvent::MouseButtonPress) &&
            ((watched == ui->hSlider_duration) || (watched == ui->hSlider_volume)))
        {
            on_slider_mouseLButtonPress(watched, event);
        }
    
        return QWidget::eventFilter(watched, event);
    }
    

    3. 计算点击定位的 value

    void Widget::on_slider_mouseLButtonPress(QObject * slider, QEvent * event)
    {
        do
        {
            //======================================
            // 只处理 鼠标左键 的按下事件
    
            QSlider     * sliderCtrl = static_cast< QSlider     * >(slider);
            QMouseEvent * mouseEvent = static_cast< QMouseEvent * >(event );
            if (Qt::LeftButton != mouseEvent->button())
            {
                break;
            }
    
            //======================================
            // 确定控件操作的基本参数
    
            int cxctl = 0;  // 滑块宽度
            int cxwnd = 0;  // 滑槽长度
            int mxpos = 0;  // 鼠标按下的位置
    
            if (Qt::Horizontal == sliderCtrl->orientation())
            {
                // 水平样式的 slider
                cxctl = sliderCtrl->minimumSizeHint().width();
                cxwnd = sliderCtrl->width();
                if (sliderCtrl->invertedAppearance())
                    mxpos = cxwnd - mouseEvent->x();
                else
                    mxpos = mouseEvent->x();
            }
            else
            {
                // 垂直样式的 slider
                cxctl = sliderCtrl->minimumSizeHint().height();
                cxwnd = sliderCtrl->height();
                if (sliderCtrl->invertedAppearance())
                    mxpos = mouseEvent->y();
                else
                    mxpos = cxwnd - mouseEvent->y();
            }
    
            if (cxwnd <= cxctl)
            {
                break;
            }
    
            //======================================
            // 计算结果,并设置新计算得到的 position 值
    
            int scpos = sliderCtrl->minimum() +
                        (int)((sliderCtrl->maximum() - sliderCtrl->minimum()) *
                              ((mxpos - cxctl / 2.0) / (cxwnd - cxctl)));
    
            if (sliderCtrl->sliderPosition() == scpos)
            {
                break;
            }
    
            sliderCtrl->setSliderPosition(scpos);
    
            //======================================
    
        } while (0);
    }
    

    4. 头文件中 Widget 类的接口声明如下:

    class Widget : public QWidget
    {
        ......
    
        // overrides
    protected:
        virtual bool eventFilter(QObject * watched, QEvent * event);
    
        // inner invoking
    protected:
        void on_slider_mouseLButtonPress(QObject * slider, QEvent * event);
    
        ......
    };
    

    另外,我的 libvlc 播放器封装类也完成了,在另外一篇文章中 libvlc —— 攫取 RGB图像 和 PCM音频 数据[C++代码实现]

  • 相关阅读:
    任务二 发布作业信息(已完成)
    查看作业信息(任务一 已完成)
    项目冲刺任务之任务场景分析(四)
    项目冲刺之任务场景分析(三)
    解析XML文件的两种方式 SAX和DOM
    解析XML文件的两种方式 SAX和DOM
    iOS开发代码规范(通用)
    随机创建点击对象
    自定义加载等待框(MBProgressHUD)
    KVO、KVC
  • 原文地址:https://www.cnblogs.com/VxGaaagaa/p/11213398.html
Copyright © 2011-2022 走看看