简体   繁体   English

如何在 QListView 自定义小部件上选择文本?

[英]How to make text selectable on a QListView custom widget?

Context语境

TLTR: For a command-line console widget, I need to be able to select the texts on a QListView row. TLTR:对于命令行控制台小部件,我需要能够 select QListView行上的文本。

In a similar way that your browser command-line (eg pressing F12 on Firefox and going to "Console", similar for Chrome, others).以与您的浏览器命令行类似的方式(例如,在 Firefox 上按 F12 并转到“控制台”,类似于 Chrome 等)。 I am creating a command-line console for interacting with my application.我正在创建一个命令行控制台来与我的应用程序进行交互。

在此处输入图像描述

Each command and it result is pushed into a list above the input text-box, allowing each item to be drawn nicely and user-friendly:每个命令及其结果都被推送到输入文本框上方的列表中,从而使每个项目都可以很好地绘制并且用户友好:

  • The text goes through a QSyntaxHighlighter文本通过 QSyntaxHighlighter
  • Long lines, or multiple lines are elided省略了长行或多行
  • Results which are objects can be expanded or collapsed作为对象的结果可以展开或折叠
  • etc.. ETC..

Most of those goals are not yet implemented, but it's clear that I need a custom-widget to represent each row.其中大部分目标尚未实现,但很明显我需要一个自定义小部件来表示每一行。

在此处输入图像描述

Now, I need the text on that QListView item to be selectable , and copiable.现在,我需要QListView项目上的文本是可选择的和可复制的。

The problem问题

TLTR: Selecting the texts requiers to enter edit-mode, I don't like having to double-click first for selecting text. TLTR:选择需要进入编辑模式的文本,我不喜欢必须先双击才能选择文本。

Using a QStyledItemDelegate, Overriding paint : I managed to have a draft of the apparence I need.使用 QStyledItemDelegate,重写paint :我设法得到了我需要的外观草稿。 But that apparence is mostly static, no interaction exists.但是那个appearance主要是static,没有交互存在。 Overriding createEditor and setEditorData , the content can be edited.覆盖createEditorsetEditorData ,可以编辑内容。 I can set the QTextEdit as readOnly and then, it is just selectable as required.我可以将 QTextEdit 设置为readOnly ,然后就可以根据需要选择它了。

However, the list items needs to be double-clicked, or selected+clicked in order to get into edit-mode, and being able to select the text.但是,列表项需要双击或选择+单击才能进入编辑模式,并且能够 select 文本。 But, the user expects to select the text as it is, just by pressing+moving+relasing the mouse.但是,用户希望按原样 select 文本,只需按下+移动+释放鼠标即可。

The text should be selectable as it is, without double-clicking the row for getting into edit-mode文本应该可以按原样选择,无需双击该行进入编辑模式

Some code一些代码

#include <QApplication>
#include <QListView>
#include <QStyledItemDelegate>
#include <QLabel>
#include <QPainter>
#include <QPaintEvent>
#include <QStandardItemModel>
#include <QTextEdit>

class CommandLineItemDelegate: public QStyledItemDelegate
{
    Q_OBJECT
    mutable QTextEdit m_editor;
public:
    void paint(QPainter *p, const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        QRect rect(QPoint(0, 0), option.rect.size());

        m_editor.setPlainText( index.data().toString());
        m_editor.resize(option.rect.size());

        p->save();
        p->translate(option.rect.topLeft());

        m_editor.render(p, QPoint(), QRegion());
        p->restore();
    }

    QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const override
    {
        return QSize(200,50);
    }

    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override
    {
        auto* edit = new QTextEdit(parent);
        edit->setGeometry(option.rect);
        edit->setReadOnly(true);

        return edit;
    }

    void setEditorData(QWidget *editor, const QModelIndex &index) const override
    {
        auto* textEditor = dynamic_cast<QTextEdit*>(editor);
        if (textEditor != nullptr)
        {
            textEditor->setPlainText(index.data().toString());
        }
    }

    void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
    {
        auto* textEditor = dynamic_cast<QTextEdit*>(editor);
        if (textEditor != nullptr)
        {
            model->setData(index, textEditor->toPlainText());
        }
    }
};

class CommandLineListView: public QListView
{
    Q_OBJECT
    CommandLineItemDelegate m_delegate;
    QStandardItemModel m_model;
public:
    explicit CommandLineListView( QWidget* parent=nullptr)
        : QListView(parent)
        , m_delegate()
    {
        setModel(&m_model);
        m_model.insertColumn(0);
        m_model.insertRows(0,3);
        m_model.setData(m_model.index(0,0),"var adri = function(a,b){return a+b; }; // function to sum");
        m_model.setData(m_model.index(1,0),"Math.PI");
        m_model.setData(m_model.index(2,0),"2+2");
        setSelectionMode(QAbstractItemView::SelectionMode::NoSelection); //Text selection, but no row selection.

        setItemDelegate(&m_delegate);
    }
};

#include "main.moc"

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

    CommandLineListView list;
    list.show();

    app.exec();
}

在此处输入图像描述

As explained before, this "mostly" works, except that the user needs to double-click the row to enter edit-mode and selecting the text, which is not acceptable.如前所述,这种“大部分”有效,除了用户需要双击该行以进入编辑模式并选择文本,这是不可接受的。

Quick solution: easy, but not very performant for large list views快速解决方案:简单,但对于大型列表视图来说性能不是很好

A quick solution is to keep all the editors open, by calling openPersistentEditor for each added row.一个快速的解决方案是通过为每个添加的行调用openPersistentEditor来保持所有编辑器打开。

Note that this is not the most performant solution (for very large list view), but may be good enough for your use case.请注意,这不是最高效的解决方案(对于非常大的列表视图),但对于您的用例来说可能已经足够好了。

Alternative 1: Implement your own QStyledItemDelegate备选方案 1:实施您自己的QStyledItemDelegate

This allows full customisation of the formatting, but also requires that you implement the text selection feature yourself.这允许完全自定义格式,但也需要您自己实现文本选择功能。

Alternative 2: Use HTML备选方案 2:使用 HTML

Displaying it as HTML (which is probably what Chrome and Firefox do) allows you full customisation and using the built-in selection feature.将其显示为 HTML(这可能是 Chrome 和 Firefox 所做的)允许您完全自定义并使用内置的选择功能。

Alternative 3: Use QML备选方案 3:使用 QML

QML is often easier to (rapidly) create a custom user interface. QML 通常更容易(快速)创建自定义用户界面。

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

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