【笔记1-8】Qt bug记录:QListWidget窗口的浏览模式切换为ListMode后,滚轮滚动速度变慢

  • 问题现象是,在QListWidget的一个窗口中有一些item,可以用IconMode和ListMode两种模式显示,一开始在IconMode用滚轮滑动速度是正常的,切换到ListMode后滚动速度也正常,但是再切换回来,滚动速度明显变慢,只要不切换ListMode速度就不会变化

最后调查发现是Qt自身的限制,这里先做一个简单的demo,可以再现这个问题

  • idiombrowser.cpp
c 复制代码
#include "idiombrowser.h"

#include <QApplication>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QListWidget>
#include <QPushButton>
#include <QListWidgetItem>

IdiomBrowser::IdiomBrowser(QWidget *parent) : QWidget(parent)
{
    setupUI();
    populateList();
    connectSignals();
}

void IdiomBrowser::switchToListMode()
{
    listWidget->setViewMode(QListView::ListMode);
    listWidget->setDragDropMode(QAbstractItemView::NoDragDrop);
    adjustListSize();
}

void IdiomBrowser::switchToIconMode()
{
    listWidget->setViewMode(QListView::IconMode);
    listWidget->setDragDropMode(QAbstractItemView::NoDragDrop);
    listWidget->setIconSize(QSize(64, 64));
    adjustListSize();
}

void IdiomBrowser::setupUI()
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);

    // 创建按钮布局
    QHBoxLayout *buttonLayout = new QHBoxLayout();
    listModeButton = new QPushButton("list mode", this);
    iconModeButton = new QPushButton("icon mode", this);

    buttonLayout->addWidget(listModeButton);
    buttonLayout->addWidget(iconModeButton);

    // 创建列表控件
    listWidget = new QListWidget(this);
    listWidget->setSelectionMode(QAbstractItemView::SingleSelection);

    // 初始设置为列表模式
    switchToIconMode();

    mainLayout->addLayout(buttonLayout);
    mainLayout->addWidget(listWidget);

    setWindowTitle("scroll test");
    resize(600, 400);
    // listWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
}

void IdiomBrowser::populateList()
{

    QStringList idioms = {
        "aaaa", "bbbb", "cccc", "dddd",
        "eeee", "ffff", "gggg", "hhhh",
        "iiii", "jjjj", "kkkk", "llll",
        "mmmm", "nnnn", "oooo", "pppp",
        "qqqq", "rrrr", "ssss", "tttt",
        "uuuu", "vvvv", "wwww", "xxxx",
        "vvvv", "wwww",

    };

    for (const QString &idiom : idioms) {
        QListWidgetItem *item = new QListWidgetItem(idiom);
        listWidget->addItem(item);
    }
}

void IdiomBrowser::connectSignals()
{
    connect(listModeButton, &QPushButton::clicked, this, &IdiomBrowser::switchToListMode);
    connect(iconModeButton, &QPushButton::clicked, this, &IdiomBrowser::switchToIconMode);
}

void IdiomBrowser::adjustListSize()
{
    if (listWidget->viewMode() == QListView::IconMode) {
        listWidget->setGridSize(QSize(100, 100));
        listWidget->setSpacing(10);
        listWidget->setWordWrap(true);
    } else {
        listWidget->setGridSize(QSize());
        listWidget->setSpacing(2);
    }
}
  • idiombrowser.h
c 复制代码
#ifndef IDIOMBROWSER_H
#define IDIOMBROWSER_H

#include <QWidget>

class QListWidget;
class QPushButton;

class IdiomBrowser : public QWidget
{
    Q_OBJECT

public:
    IdiomBrowser(QWidget *parent = nullptr);

private slots:
    void switchToListMode();
    void switchToIconMode();

private:
    void setupUI();
    void populateList();
    void connectSignals();
    void adjustListSize();

    QListWidget *listWidget;
    QPushButton *listModeButton;
    QPushButton *iconModeButton;
};

#endif // IDIOMBROWSER_H
  • main.cpp
c 复制代码
#include <QApplication>
#include "idiombrowser.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    IdiomBrowser browser;
    browser.show();

    return app.exec();
}

通过对Qt6源码进行debug发现了问题原因

首先是在void QListModeViewBase::updateVerticalScrollBar(const QSize &step)这个函数中

如果切换到ListMode就会走进第一个if,然后setSingleStep(1)

设置为1后,这里的viewMayChangeSingleStep就会变成false

viewMayChangeSingleStep是false的情况下,后续切换模式时,就无法切换step,也就是滚动单步步长singleStep永远是1

这里源码的注释也说明了,如果将setSingleStep设置为一个reasonable值,就无法切换了,需要再设为-1才能恢复

singleStep用于滑动时计算步长

解决方案是将滚动模式设为按像素滚动,这样不会走setSingleStep(1);

setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);

相关推荐
flying robot14 分钟前
centos7系统配置
笔记
木千31 分钟前
Qt中关于eventFilter函数无法过滤QTableWidget鼠标事件的处理方式
qt
zhdy567893 小时前
最简单方法 设置matlab坐标轴刻度标签的字号,设置坐标轴标题和图形标题,并指定字号。画出的图片背景设置为白色,
笔记
崇山峻岭之间3 小时前
Matlab学习笔记02
笔记·学习·matlab
木木em哈哈3 小时前
C语言多线程
笔记
hssfscv5 小时前
Javaweb 学习笔记——html+css
前端·笔记·学习
Dream Algorithm7 小时前
自古英雄多寂寥
笔记
yuhaiqun19897 小时前
Typora 技能进阶:从会写 Markdown 到玩转配置 + 插件高效学习笔记
经验分享·笔记·python·学习·学习方法·ai编程·markdown
apcipot_rain7 小时前
汇编语言与逆向分析 一轮复习笔记
汇编·笔记·逆向
奇树谦8 小时前
【Qt实战】实现图片缩放、平移与像素级查看功能
开发语言·qt