[英]How to make text selectable on a QListView custom widget?
TLTR:對於命令行控制台小部件,我需要能夠 select QListView
行上的文本。
以與您的瀏覽器命令行類似的方式(例如,在 Firefox 上按 F12 並轉到“控制台”,類似於 Chrome 等)。 我正在創建一個命令行控制台來與我的應用程序進行交互。
每個命令及其結果都被推送到輸入文本框上方的列表中,從而使每個項目都可以很好地繪制並且用戶友好:
其中大部分目標尚未實現,但很明顯我需要一個自定義小部件來表示每一行。
現在,我需要QListView
項目上的文本是可選擇的和可復制的。
TLTR:選擇需要進入編輯模式的文本,我不喜歡必須先雙擊才能選擇文本。
使用 QStyledItemDelegate,重寫paint
:我設法得到了我需要的外觀草稿。 但是那個appearance主要是static,沒有交互存在。 覆蓋createEditor
和setEditorData
,可以編輯內容。 我可以將 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.