繁体   English   中英

QTableView 的奇怪行为与包含斜杠的文本

[英]Strange behavior of QTableView with text containing slashes

我们最近将一个项目从 Qt 4.8 移植到 Qt 5.15(由于依赖关系,我们还不能选择 Qt 6)。

我们发现当一个项目的文本包含斜线时,我们所有的 QTableView 都会表现得很奇怪。 这是一个演示 2 个问题的小程序:

#include <QTableWidget>
#include <QAbstractItemModel>
#include <QApplication>
#include <QDebug>


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

    QTableWidget tbl;
    tbl.setTextElideMode(Qt::ElideLeft);
    tbl.setColumnCount(2);
    tbl.setRowCount(argc-1);
    for (int i = 1; i < argc; ++i)
    {
        tbl.setItem( i-1, 0, new QTableWidgetItem(QString::number(i)) );
        tbl.setItem( i-1, 1, new QTableWidgetItem(argv[i]) );
    }
    tbl.show();
    
    auto* pModel = tbl.model();
    QString qstrMatch = "*single*file*";
    QModelIndexList lst = pModel->match(pModel->index(0,1), Qt::DisplayRole, qstrMatch, -1, Qt::MatchWildcard);
    qDebug() << lst.size() << "results";
    for (const QModelIndex& idx : lst)
    {
        qDebug() << argv[1+idx.row()];
    }

    return app.exec();
}

假设我们使用以下 4 个字符串运行该程序:

/path/to/design/patterns/singleton_file.txt
/path/to/design/patterns/observer_file.txt
just_single_name_file_no_path.txt
drill a single 1/4 inch hole then file here

1) 文本省略

在 Qt 4 中, Qt::ElideLeft在所有情况下都受到尊重:

在此处输入图像描述

但是在 Qt 5 中,每当文本包含斜杠时似乎就有问题:

在此处输入图像描述

一位同事注意到一个表仍在按预期工作,并发现它的不同之处在于使用了自定义委托。 果然,只需在其他表上执行tbl.setItemDelegate(new QItemDelegate)也可以解决问题。 但这似乎没有任何意义。

2)文本匹配

在 Qt 4 中,对match function 的调用确实按预期返回 3 个结果。 在 Qt 5 中,它只返回 1 个结果 - 对于不包含斜杠的字符串。

不过,通过使用带有Wildcard语法的QRegExp来使用我们自己的循环来实现搜索可以按预期工作。


https://doc.qt.io/qt-5.15/sourcebreaks.html没有提供任何可能发生变化的指针。

在对 Qt 5 的源代码进行了一些挖掘之后,我们能够找到这些问题背后的原因和解决方案。

这两个问题无关。

1) 文本省略

在研究了 Qt 源代码一段时间后,我偶然发现了QTableView::setWordWrap的这个文档注释:

请注意,即使启用了换行,单元格也不会扩展以适合所有文本。 省略号将根据当前的 textElideMode 插入。

自动换行是默认开启的,只有当你手动调整行大小时它的效果才会变得清晰:

在此处输入图像描述

所以“...”不是用于“水平”文本宽度省略,而是用于“垂直”换行截断。 解决方案是在QTableView上简单地使用: setWordWrap(false)

使用QItemDelegate的原因似乎是它的实现在自动换行之前进行了简单的省略,而QStyledItemDelegate (默认)首先换行,然后仅省略了无法换行的很长单词的行。 (尚不清楚 Qt 4 中哪一部分的处理方式不同:可能斜杠不被视为换行的有效字边界。)

2)文本匹配

根本区别在于QAbstractItemModel::match QRegExp :之前使用带有Wildcard语法的 QRegExp 与现在使用QRegularExpression::wildcardToRegularExpression 正如后者 function 的文档所述:

转换的目标是文件路径通配,这尤其意味着路径分隔符接受特殊处理。

这意味着每个项目的文本都被视为文件路径,其中每个*只能在一个路径组件内匹配 - 它不能跨越斜线(它转换为类似[^/]*而不仅仅是.* )。 因此,通配符模式需要有特定数量的斜杠和星号才能匹配文本。

所以唯一的解决方案(如果我们选择使用QAbstractItemModel::match而不是滚动我们自己的循环)似乎是编写我们自己的wildcardToRegularExpression实现,它不假设通配符用于文件路径,因此不处理路径分隔符,然后使用Qt::RegularExpression匹配标志。 在其他地方也需要这样的QRegExp使用现在已弃用的带有Wildcard语法的 QRegExp 需要替换为QRegularExpression

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM