[英]How to make text selectable on a QListView custom widget?
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:每个命令及其结果都被推送到输入文本框上方的列表中,从而使每个项目都可以很好地绘制并且用户友好:
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
项目上的文本是可选择的和可复制的。
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.覆盖
createEditor
和setEditorData
,可以编辑内容。 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文本应该可以按原样选择,无需双击该行进入编辑模式
#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.