簡體   English   中英

如何在 QListView 自定義小部件上選擇文本?

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

語境

TLTR:對於命令行控制台小部件,我需要能夠 select QListView行上的文本。

以與您的瀏覽器命令行類似的方式(例如,在 Firefox 上按 F12 並轉到“控制台”,類似於 Chrome 等)。 我正在創建一個命令行控制台來與我的應用程序進行交互。

在此處輸入圖像描述

每個命令及其結果都被推送到輸入文本框上方的列表中,從而使每個項目都可以很好地繪制並且用戶友好:

  • 文本通過 QSyntaxHighlighter
  • 省略了長行或多行
  • 作為對象的結果可以展開或折疊
  • ETC..

其中大部分目標尚未實現,但很明顯我需要一個自定義小部件來表示每一行。

在此處輸入圖像描述

現在,我需要QListView項目上的文本是可選擇的和可復制的。

問題

TLTR:選擇需要進入編輯模式的文本,我不喜歡必須先雙擊才能選擇文本。

使用 QStyledItemDelegate,重寫paint :我設法得到了我需要的外觀草稿。 但是那個appearance主要是static,沒有交互存在。 覆蓋createEditorsetEditorData ,可以編輯內容。 我可以將 QTextEdit 設置為readOnly ,然后就可以根據需要選擇它了。

但是,列表項需要雙擊或選擇+單擊才能進入編輯模式,並且能夠 select 文本。 但是,用戶希望按原樣 select 文本,只需按下+移動+釋放鼠標即可。

文本應該可以按原樣選擇,無需雙擊該行進入編輯模式

一些代碼

#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();
}

在此處輸入圖像描述

如前所述,這種“大部分”有效,除了用戶需要雙擊該行以進入編輯模式並選擇文本,這是不可接受的。

快速解決方案:簡單,但對於大型列表視圖來說性能不是很好

一個快速的解決方案是通過為每個添加的行調用openPersistentEditor來保持所有編輯器打開。

請注意,這不是最高效的解決方案(對於非常大的列表視圖),但對於您的用例來說可能已經足夠好了。

備選方案 1:實施您自己的QStyledItemDelegate

這允許完全自定義格式,但也需要您自己實現文本選擇功能。

備選方案 2:使用 HTML

將其顯示為 HTML(這可能是 Chrome 和 Firefox 所做的)允許您完全自定義並使用內置的選擇功能。

備選方案 3:使用 QML

QML 通常更容易(快速)創建自定義用戶界面。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM