C++ 如何利用QStyledItemDelegate在QTreeWidget中拥有不同高度的QTreeWidgetItems?
注意:原来问题不是由于实现了C++ 如何利用QStyledItemDelegate在QTreeWidget中拥有不同高度的QTreeWidgetItems?,c++,qt,qwidget,qtreewidget,qtreewidgetitem,C++,Qt,Qwidget,Qtreewidget,Qtreewidgetitem,注意:原来问题不是由于实现了QStyledItemDelegate,而是因为在MyTreeWidget的构造函数中我调用了。以下代码和@scopchanov发布的解决方案有效且有效 QTreeWidget有一个受保护的方法,名为itemFromIndex(),这就是我如何使其可访问的方法: class MyTreeWidget : public QTreeWidget { Q_OBJECT public: MyTreeWidget(QWidget *parent) : QTree
QStyledItemDelegate
,而是因为在MyTreeWidget
的构造函数中我调用了。以下代码和@scopchanov发布的解决方案有效且有效
QTreeWidget
有一个受保护的方法,名为itemFromIndex()
,这就是我如何使其可访问的方法:
class MyTreeWidget : public QTreeWidget {
Q_OBJECT
public:
MyTreeWidget(QWidget *parent) : QTreeWidget(parent) {
setItemDelegate(new MyItemDelegate(this));
}
QTreeWidgetItem treeWidgetItemFromIndex(const QModelIndex& index) {
return itemFromIndex(index);
}
}
在我的QStyledItemDelegate
中,我存储一个指向MyTreeWidget
的指针,然后重写其虚拟sizeHint()
方法,并根据QTreeWidgetItem
的类型添加填充
class MyItemDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
MyItemDelegate(QObject *parent) : QStyledItemDelegate(parent) {
_myTreeWidget = dynamic_cast<MyTreeWidget*>(parent);
}
QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const {
auto treeWidgetItem = _myTreeWidget->treeWidgetItemFromIndex(index);
QSize padding;
if (dynamic_cast<MyCustomTreeWidgetItem1*>(treeWidgetItem) {
padding = {0, 5};
} else if (dynamic_cast<MyCustomTreeWidgetItem2*>(treeWidgetItem) {
padding = {0, 10};
}
return QStyledItemDelegate::sizeHint(option, index) + padding;
}
}
类MyItemDelegate:公共QStyledItemDelegate
{
Q_对象
公众:
MyItemDelegate(QObject*父级):QStyledItemDelegate(父级){
_myTreeWidget=动态投影(父级);
}
QSize sizeHint(常数QStyleOptionViewItem&option、常数QModelIndex&index)常数{
auto treeWidgetItem=\u myTreeWidget->treeWidgetItemFromIndex(索引);
量化填充;
if(动态_铸造(树状边缘){
填充={0,5};
}else if(动态施法(树状边缘){
填充={0,10};
}
返回QStyledItemDelegate::sizeHint(选项,索引)+填充;
}
}
这不起作用,因为不会为每个QTreeWidgetItem
调用委托的sizeHint()
因此,我的文本选项在MyCustomTreeWidgetItem1
的构造函数中调用setSizeHint()
,这似乎也没有任何效果。是否因为存在委托而忽略它
另一个选项是设置QWidget
中包含的MyCustomTreeWidgetItem
的最小高度,这可以通过QTreeWidget::setItemWidget()
实现
所以,从我使用代理的那一刻起,我似乎只限于大小。是我可以选择摆脱代理,还是我可以尝试其他方法
我知道很多人会说从QTreeWidget
切换到QTreeView
,但目前这是不可能的。解决方案
我将以不同(更简单)的方式处理此问题:
enum ItemType : int {
IT_ItemWithRegularPadding,
IT_ItemWithBigPadding
};
switch (type) {
case IT_ItemWithRegularPadding:
item->setData(0, Qt::UserRole, QSize(0, 5));
break;
case IT_ItemWithBigPadding:
item->setData(0, Qt::UserRole, QSize(0, 10));
break;
}
sizeHint
时,从索引的数据中检索所需的大小,例如:
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const override {
return QStyledItemDelegate::sizeHint(option, index)
+ index.data(Qt::UserRole).toSize();
}
#include <QApplication>
#include <QStyledItemDelegate>
#include <QTreeWidget>
#include <QBoxLayout>
class Delegate : public QStyledItemDelegate
{
public:
explicit Delegate(QObject *parent = nullptr) :
QStyledItemDelegate(parent){
}
QSize sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const override {
return QStyledItemDelegate::sizeHint(option, index)
+ index.data(Qt::UserRole).toSize();
}
};
class MainWindow : public QWidget
{
public:
enum ItemType : int {
IT_ItemWithRegularPadding,
IT_ItemWithBigPadding
};
MainWindow(QWidget *parent = nullptr) :
QWidget(parent) {
auto *l = new QVBoxLayout(this);
auto *treeWidget = new QTreeWidget(this);
QList<QTreeWidgetItem *> items;
for (int i = 0; i < 10; ++i)
items.append(createItem(QString("item: %1").arg(i),
0.5*i == i/2 ? IT_ItemWithRegularPadding
: IT_ItemWithBigPadding));
treeWidget->setColumnCount(1);
treeWidget->setItemDelegate(new Delegate(this));
treeWidget->insertTopLevelItems(0, items);
l->addWidget(treeWidget);
resize(300, 400);
setWindowTitle(tr("Different Sizes"));
}
private:
QTreeWidgetItem *createItem(const QString &text, int type) {
auto *item = new QTreeWidgetItem(QStringList(text));
switch (type) {
case IT_ItemWithRegularPadding:
item->setData(0, Qt::UserRole, QSize(0, 5));
break;
case IT_ItemWithBigPadding:
item->setData(0, Qt::UserRole, QSize(0, 10));
break;
}
return item;
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#包括
#包括
#包括
#包括
类委托:公共QStyledItemDelegate
{
公众:
显式委托(QObject*parent=nullptr):
QStyledItemDelegate(父级){
}
QSize sizeHint(常量QStyleOptionViewItem和option,
常量QModelIndex和索引)常量覆盖{
返回QStyledItemDelegate::sizeHint(选项,索引)
+data(Qt::UserRole).toSize();
}
};
类主窗口:公共QWidget
{
公众:
枚举项类型:int{
它是一个有规则填充的项目,
它有很大的填充物
};
主窗口(QWidget*parent=nullptr):
QWidget(父级){
auto*l=新的QVBoxLayout(此);
auto*treeWidget=新的QTreeWidget(此);
QList项目;
对于(int i=0;i<10;++i)
items.append(createItem(QString(“项:%1”).arg(i),
0.5*i==i/2?具有规则填充的IT_项
:IT_items with big padding));
treeWidget->setColumnCount(1);
treeWidget->setItemDelegate(新委托(此));
treeWidget->insertTopLevelItems(0,items);
l->addWidget(树边条);
调整大小(300400);
setWindowTitle(tr(“不同尺寸”);
}
私人:
QTreeWidgetItem*createItem(常量QString&text,int类型){
auto*item=新的QTreeWidgetItem(QStringList(text));
开关(类型){
使用规则填充的大小写IT_项:
item->setData(0,Qt::UserRole,QSize(0,5));
打破
使用大填充的大小写IT_项:
item->setData(0,Qt::UserRole,QSize(0,10));
打破
}
退货项目;
}
};
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
主窗口w;
w、 show();
返回a.exec();
}
注意:此示例根据索引设置项目的大小-奇数或偶数。通过实现区分项目所需的逻辑,您可以随意更改此设置
结果
给定的示例产生以下结果:
偶数项和奇数项的高度不同。我能够找到问题的根源,问题是我的
QTreeWidget
将uniformRowHeights
属性设置为true。将其取下解决了问题。但是,您的解决方案消除了对动态施法的需要,因此我将其升级。@ArmaniStyles,my解决方案不仅更简单,而且它是通过使用代理来获得不同项目高度的正确方法。如果您让代理知道使用它的视图和使用它的方法,就像您所做的那样,这称为紧耦合,会在项目的后期给您带来麻烦。因此,我建议您使用我描述的方法。哟你最好接受这个答案,因为它为关于达到不同高度的问题提供了一个有效的解决方案。我同意你的解决方案更简单,但我不同意紧耦合部分,因为它只适用于你的样本。事实上,我可能有3种不同类型的qtreewigetitem
和ac通过对它们进行子分类,我可以得到这样的逻辑:m的子类