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 —— 播放器示例程序[C++代码实现攫取 RGB图像 和 PCM音频 数据功能]

原文地址:https://www.cnblogs.com/Gaaagaa/p/12130799.html

时间: 2024-10-25 19:20:32

GUI 编程 —— QT 的 QSlider 鼠标点击定位问题的相关文章

C/C++ -- Gui编程 -- Qt库的使用 -- 使用自定义类

1.新建空Qt工程 2.新建C++类HelloQt 3.新建ui文件,添加部件,重命名主窗体(对话框)类名HelloQt,构建生成ui头文件 4.修改头文件helloqt.h 1 #ifndef HELLOQT_H 2 #define HELLOQT_H 3 4 #include <QDialog> 5 6 namespace Ui{ 7 class HelloQt; 8 } 9 class HelloQt : public QDialog 10 { 11 Q_OBJECT 12 public

QT中模拟鼠标点击事件

传入座标,模拟鼠标点击QWebView中网页上的某一点 qDebug()<<"mouse clicked"; QPoint pos(403,34); QMouseEvent event0(QEvent::MouseButtonPress, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QApplication::sendEvent(view->page(), &event0); QMouseEven

java语言gui编程之内部类和鼠标事件经典1

/*  时间:2015年3月21日09:53:44  程序目的:理解内部类的作用和鼠标事件的处理  源文件的名称:TestInner.java  要点:   1, 内部类的性质和用法   2, 将内部类定义为普通内部类的好处-----内部类可以直接访问外层类的属性和方法   3, 可以更清楚的组织逻辑,防止不应该被其他类访问的类进行访问      何时使用:    该类不允许或不需要其他类进行访问.       鼠标事件     鼠标事件的两个监听器接口为MouseListener, Mouse

C/C++ -- Gui编程 -- Qt库的使用 -- 使用.ui文件

1.创建Qt空工程 2.添加Qt设计师界面,无按钮对话框helloqt.ui 3.编辑界面,添加部件,修改对话框对象名为HelloQt 1 <?xml version="1.0" encoding="UTF-8"?> 2 <ui version="4.0"> 3 <class>HelloQt</class> 4 <widget class="QDialog" name=&q

C/C++ -- Gui编程 -- Qt库的使用 -- HelloWorld

1.纯代码写对话框HelloWorld 创建空Qt工程,添加C++源文件main.cpp 需要设置编码以支持中文 -----源代码main.cpp----- 1 #include <QApplication> 2 #include <QDialog> 3 #include <QLabel> 4 #include <QtextCodec> 5 6 int main(int argc, char * argv[]) 7 { 8 QApplication app(

C/C++ -- Gui编程 -- Qt库的使用 -- 标准对话框

-----mywidget.cpp----- 1 #include "mywidget.h" 2 #include "ui_mywidget.h" 3 #include <QFileDialog> 4 #include <QColorDialog> 5 #include <QFontDialog> 6 #include <QInputDialog> 7 #include <QMessageBox> 8 #i

C/C++ -- Gui编程 -- Qt库的使用 -- 信号与槽 -- 欢迎界面

程序运行先显示一个对话框,确定进入主程序 1.新建Qt工程,类MyWidget,基类QWidget 2.新建设计师界面类MyDialog,基类QDialog 3.-----main.cpp----- 1 #include "mywidget.h" 2 #include "mydialog.h" 3 #include <QApplication> 4 5 int main(int argc, char *argv[]) 6 { 7 QApplication

C/C++ -- Gui编程 -- Qt库的使用 -- 理解主窗体构造函数

MyWidget做父窗体 MyWidget的构造函数中可以手动添加组件 Ui::MyWidget存放子部件 Ui::MyWidget执行setupUi()函数为子部件开辟空间,指定父窗体 MyWidget只能调用构造函数中添加的组件 Ui::MyWidget只能调用UI文件中的子部件 Ui::MyWidget不是Wiget类,只是一个普通类,不能拿他做父窗体 测试:1.新建GUI工程,主类MyWidget,UI上拖放一个Frame 以后都用Qt5了,省得汉字转码 2.-----mywidget.

C/C++ -- Gui编程 -- Qt库的使用 -- QtWidget

1 #include<QtGui> 2 int main(int argc, char * argv[]) 3 { 4 QApplication app(argc, argv); 5 QTextCodec::setCodecForCStrings(QTextCodec::codecForName("utf-8")); 6 QWidget wgt; 7 wgt.setWindowTitle(QString::QString("我也有依靠")); 8 wgt