我正在尝试实现一个类似于Qt Jupyter Notebook中基于单元的小部件,其中多个单元垂直堆叠。每个单元格由QTextEdit
和多个按钮组成,通过在文本编辑器中输入更多文本(例如,文本编辑器中没有垂直滚动条),该单元格的垂直尺寸会增大。
但是,我不确定在Qt中实现这种小部件的最佳方法是什么。我已经尝试过为QListWidget
和每个项目使用自定义小部件(由QTextEdit
和几个按钮组成),但是自定义小部件不会通过输入更多文本而垂直增长,而是使用{ {1}}滚动条将出现。我还使用QTextEdit
和QListView
实现了第二个版本,但是遇到了多个问题,包括无法(通过委托)与绘制的按钮进行交互。
关于如何实现这种基于单元的窗口小部件的任何建议/示例?
答案 0 :(得分:1)
您可以继承QTextEdit
的子类,并使用document()->size()
来监听文档大小的变化(请注意,不是QTextEdit的大小)。然后,您可以调整QTextEdit
的父级大小以反映新的大小。要用小部件填充父级,请使用布局。为此,我在下面多次使用QVBoxLayout
。 (一个用于在垂直列中容纳多个QTextEdit
小部件;第二个用于容纳一个TextEdit)。
#include <QtCore>
#include <QtWidgets>
class DyTextEdit : public QTextEdit
{
Q_OBJECT
public:
DyTextEdit(QWidget *parent = nullptr) :
QTextEdit(parent)
{
QTextDocument *doc = document();
currentSize = doc->size();
qDebug() << "[Init] Size:" << currentSize;
// listen to text/content changes
connect(this, &QTextEdit::textChanged, this, &DyTextEdit::on_textChanged);
// connect <>
connect(this, &DyTextEdit::sizeChanged, this, &DyTextEdit::resizeParent);
doc->setTextWidth(-1);
emit sizeChanged(currentSize); // init
}
signals:
// emitted when document size changes
void sizeChanged(QSizeF size);
public slots:
void on_textChanged()
{
QSizeF newSize = document()->size();
qDebug() << "[TextChanged] Size:" << newSize;
// detect changes in the document size
if (newSize != currentSize)
emit sizeChanged(newSize); // emit signal
// update size
currentSize = newSize;
}
void resizeParent(QSizeF size)
{
// resize the parent's height, don't bother with the width
parentWidget()->setFixedHeight(size.height());
}
private:
QSizeF currentSize; // keeps track of current document size
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// holds all dytextedits
QWidget aggregateWidget;
QVBoxLayout aggregateLayout(&aggregateWidget);
// note: for scalability, use a QList (or QLists)
// first textbox
QWidget widget;
QVBoxLayout vbLayout(&widget);
vbLayout.setMargin(0);
DyTextEdit dytext(&widget);
vbLayout.addWidget(&dytext);
// first button row
QHBoxLayout hbLayout(&widget);
hbLayout.setMargin(0);
QPushButton pb1a("Push this.", &widget);
hbLayout.addWidget(&pb1a);
QPushButton pb1b("Push this.", &widget);
hbLayout.addWidget(&pb1b);
// second textbox
QWidget widget2;
QVBoxLayout vbLayout2(&widget2);
vbLayout2.setMargin(0);
DyTextEdit dytext2(&widget2);
vbLayout2.addWidget(&dytext2);
// second button row
QHBoxLayout hbLayout2(&widget2);
hbLayout2.setMargin(0);
QPushButton pb2a("Push this.", &widget2);
hbLayout2.addWidget(&pb2a);
QPushButton pb2b("Push this.", &widget2);
hbLayout2.addWidget(&pb2b);
// add widgets to layout
aggregateLayout.addWidget(&widget); // cell 1
aggregateLayout.addLayout(&hbLayout); // |
aggregateLayout.addWidget(&widget2); // cell 2
aggregateLayout.addLayout(&hbLayout2); // |
aggregateLayout.setSizeConstraint(QLayout::SetMinAndMaxSize);
aggregateWidget.show();
return a.exec();
}
#include "main.moc" // include if there are QObject classes in main.cpp
请注意,在上面,我使用了QHBoxLayout
的按钮行,并将它们添加到与文本框小部件分离的整体聚合布局中。如果您希望将按钮设置为其他格式,则仍然可以使用QGridLayout
这样的说法。您还可以将textedits和按钮布局作为子项组合在另一个覆盖了两者的小部件(用作伞)下。这将更清楚地形成小部件的单元格,并且可能更容易移动。 (我已经在Github上上传了一个可行的示例。)
这是键入内容并粘贴内容后的屏幕截图。
请注意,聚合小部件将在删除文本行时收缩。