在QTableView中设置QPlainTextEdit Delegate的高度
Setting the Height of a QPlainTextEdit Delegate in a QTableView
我在这里工作的一个项目,目前我被困在以下问题。它是关于一个QTableView,它有一个列叫做"Description",这个列的单元格包含一个QPlainTextEditDelegate。每次输入时,我都无法设置QPlainTextEdit的高度。现在它的行为就像一个QLineEdit,直到我把QTableView的行(当时我在其中活动)拖大。
我想做的是改变QPlainTextEdit的高度,一旦我进入它。你有什么建议?我怎样才能把这件事做完呢?
提前感谢大家!
BTW抱歉我的英语不好:/
编辑:我解决了这个问题,但没有sizeHint,我使用了updateEditorGeometry:
void updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem & option, const QModelIndex & index ) const;
在这个方法中,你可以设置你想要的宽度或高度
editor->setGeometry(option.rect.x(),option.rect.y(),<your_width>,<your_height>);
不过还是谢谢你!
您应该重新实现QAbstractItemDelegate::sizeHint方法,以便在创建编辑器时返回期望的高度。我不认为有必要在创建编辑器后发出QAbstractItemDelegate::sizeHintChanged信号,但文档没有说什么。如果没有它就不能工作,您应该在返回创建的编辑器小部件后发出sizeHintChanged,以通知视图需要更改行高。
我正面临着完全相同的问题,尽管在QTableView中有一个QPlainTextEdit作为编辑器的自定义委托。最初,编辑器的增长不会超过其表单元格的大小。
什么不适合我:
-
updateEditorGeometry()
:只调用初始show()
- 自定义
sizeHint()
:从未被调用,无论是在子类还是基类中,无论任何update()
,updateGeometry()
调用或信号
在看似无穷无尽的收集关于一些未记录的QPlainTextEdit/QTextDocument '功能'和Qt怪谈的小块信息后,我通过连接到QPlainTextEdit->document()->documentLayout()的documentsizechange (QSizeF)信号得到了我想要的。
下面是扩展编辑器所需的基本要素,同时将其限制在父QTableView的viewport (m_pTableView
)中。
希望这对任何人都有意义。示例代码不能按原样编译,但应该提供足够的提示来开始。
h editor + delegate
#include <QPlainTextEdit>
// A custom QStyledItemDelegate
#include "library/tableitemdelegate.h"
/// A QPlainTextEdit to show all content lines in a scrollable view.
/// * finish editing with Return (like QLineEdit used for other metadata)
/// * add new line with Shift+Return.
/// Horizontal scrollbar is hidden as long as content is just one line.
/// Note: QTextEdit is no option here since it seems to transform content with
/// line breaks to html doc when committing data.
class MultiLineEditor : public QPlainTextEdit {
Q_OBJECT
public:
MultiLineEditor(QWidget* pParent);
bool eventFilter(QObject* obj, QEvent* event) override;
signals:
void editingFinished();
};
class MultiLineEditDelegate : public TableItemDelegate {
Q_OBJECT
public:
explicit MultiLineEditDelegate(QTableView* pTrackTable);
~MultiLineEditDelegate() override = default;
// called when the user starts editing an item
QWidget* createEditor(QWidget* parent,
const QStyleOptionViewItem& option,
const QModelIndex& index) const override;
private slots:
void commitAndCloseEditor();
private:
void adjustEditor(MultiLineEditor* pEditor, const QSizeF size) const;
mutable QRect m_editRect;
mutable int m_lineCount;
};
cpp编辑器+委托
#include "library/multilineeditdelegate.h"
#include <QAbstractTextDocumentLayout>
#include <cmath>
#include "moc_multilineeditdelegate.cpp"
MultiLineEditor::MultiLineEditor(QWidget* pParent)
: QPlainTextEdit(pParent) {
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
// Disable line wrap for a predictable view (like QLineEdit).
// Horizontal scrollbars show up automatically.
setLineWrapMode(QPlainTextEdit::NoWrap);
// Remove ugly content offset, most notable with one-liners
setContentsMargins(0, 0, 0, 0);
document()->setDocumentMargin(0);
// Add event filter to catch right-clicks and key presses
installEventFilter(this);
};
bool MultiLineEditor::eventFilter(QObject* obj, QEvent* event) {
if (event->type() == QEvent::MouseButtonPress) {
// Work around a strange quirk: right-clicks outside the rectangle of
// the underlying table index are not triggering the context menu.
// Simply returning true fixes it.
QMouseEvent* me = static_cast<QMouseEvent*>(event);
if (me->button() == Qt::RightButton &&
rect().contains(me->pos(), false)) {
return true;
}
} else if (event->type() == QEvent::KeyPress) {
// Finish editing with Return key like in QLineEdit
QKeyEvent* ke = static_cast<QKeyEvent*>(event);
if ((ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter) &&
ke->modifiers().testFlag(Qt::NoModifier)) {
emit editingFinished();
return false;
}
}
return QPlainTextEdit::eventFilter(obj, event);
}
MultiLineEditDelegate::MultiLineEditDelegate(QTableView* pTableView)
: TableItemDelegate(pTableView),
m_lineCount(0) {
}
QWidget* MultiLineEditDelegate::createEditor(QWidget* pParent,
const QStyleOptionViewItem& option,
const QModelIndex& index) const {
Q_UNUSED(index);
auto* pEditor = new MultiLineEditor(pParent);
auto* pDocLayout = pEditor->document()->documentLayout();
// Adjust height to fit content and maybe shift vertically to fit into the
// library view. documentSizeChanged() is emitted when text changed, incl.
// initial fill.
// We could also connect to QPlainTextEdit::blockCountChanged(), though
// for some reason, that only works for documents with 2+ lines
// appending line breaks to single-line docs won't fire that signal :|
connect(pDocLayout,
&QAbstractTextDocumentLayout::documentSizeChanged,
this,
[this, pEditor](const QSizeF size) {
adjustEditor(pEditor, size);
});
// emitted when pressing Return key to act like QLineEdit
connect(pEditor,
&MultiLineEditor::editingFinished,
this,
&MultiLineEditDelegate::commitAndCloseEditor);
// Store the initial rectangle so we can read the x/y origin and in adjustEditor()
m_editRect = option.rect;
return pEditor;
}
void MultiLineEditDelegate::adjustEditor(MultiLineEditor* pEditor, const QSizeF size) const {
// Compared to QTextEdit, size.height() is the line count (Qt speak: blocks)
int newLineCount = static_cast<int>(round(size.height()));
// Only act if line count changed
if (newLineCount == m_lineCount) {
return;
} else {
m_lineCount = newLineCount;
}
// Remove the scrollbars if content is just one line to emulate QLineEdit
// appearace, else enable auto mode.
Qt::ScrollBarPolicy pol(m_lineCount > 1 ? Qt::ScrollBarAsNeeded : Qt::ScrollBarAlwaysOff);
pEditor->setVerticalScrollBarPolicy(pol);
pEditor->setHorizontalScrollBarPolicy(pol);
// Calculate the content height
int lines = m_lineCount;
// Add extra margin so the horizontal scrollbar doesn't obstruct the last
// line (which also avoids the vertical scrollbar as long as possible)
lines += lines > 1 ? 1 : 0;
QFontMetrics fm(pEditor->document()->defaultFont());
int newH = fm.lineSpacing() * lines;
// Limit editor to visible table height
int tableH = m_pTableView->viewport()->rect().height();
newH = std::min(newH, tableH);
// If the editor overflows the table view, move it up so it's not clipped.
// No need to care about y < 0 or y > (table height - line height) since the
// table already ensures visibility when the index is selected.
int newY = m_editRect.y();
if ((newY + newH) > tableH) {
newY = tableH - newH;
}
// Also limit width so scrollbars are visible and table is not scrolled if
// cursor is moved horizontally.
int newW = std::min(pEditor->width(), m_pTableView->viewport()->rect().width());
pEditor->setGeometry(QRect(m_editRect.x(), newY, newW, newH));
}
void MultiLineEditDelegate::commitAndCloseEditor() {
MultiLineEditor* pEditor = qobject_cast<MultiLineEditor*>(sender());
emit commitData(pEditor);
emit closeEditor(pEditor);
}
- C++:如何根据地形高度更新玩家身高?
- 如何更改QComboBox项目的高度大小?
- 更改高度贴图,使其在 4x4 网格上显示 16 个 hieghtmap
- 我试图用这段代码找到二叉树的高度,但它一直返回 0,有人可以告诉我为什么吗?
- C++:如何计算二叉树中其值模块高度小于 2 的节点数?
- 如何使用 C++ gdal 库将栅格地理从 EGM96 转换为 WGS84 椭球体高度基准面
- 从具有父指针和左子树和右子树高度的树中删除
- 程序输入名称和高度并显示它。我不知道如何显示列表中最高人的姓名和身高
- 我正在尝试创建一个 C++ 贪吃蛇游戏,但我似乎无法绘制第二个高度边框,我该如何解决这个问题?
- 计算树高度的函数
- 尝试创建一个程序来查找非二叉树的高度.最终得到一个很长的循环,没有答案
- 计算BST返回-1的高度混淆
- 使用递归计算一个函数中的高度和大小
- 如何从2D数组为QHeightMapSurfaceDataProxy创建高度图以显示2D傅立叶变换结果
- 接受来自键盘的树节点以确定其高度
- 在 C++ 中使用平展数组语法,崩溃取决于宽度/高度
- 在一行中初始化指针(新uint8_t[高度*宽度*3])
- 在高度模板化的库中进行代码混淆
- ID3DXFont :文本被拉伸,如何获取字体的宽度和高度?
- 在QTableView中设置QPlainTextEdit Delegate的高度