QStyledItemDelegate - updateEditorGeometry 如何工作?
Posted
技术标签:
【中文标题】QStyledItemDelegate - updateEditorGeometry 如何工作?【英文标题】:QStyledItemDelegate - How does updateEditorGeometry works? 【发布时间】:2011-03-28 09:40:03 【问题描述】:我使用的是 Qt 4.7。
我有一个模型,我在 QTableView
的两列中显示,我的目标是在我的 QTableView
中提供此模型的内联编辑。
+-----------------+----------------+
| Axis position | Axis range |
+-----------------+----------------+
| Left | Fixed [0,1] |
| Left | Source: SRC1 |
| Right | Source: SRC2 |
| Left | Fixed [5,10] |
+-----------------+----------------+
第一列可以通过简单的QComboxBox
在左右切换来编辑,效果很好。问题在于我的第二列,它可以使用自定义小部件进行编辑。
这个小部件有点简单,它描述了一个范围。所以有一个 QComboBox 来选择范围的种类(“Fixed”:值由用户给出,“Source”:值根据源的最小值/最大值动态调整)。
这是我的自定义小部件的源代码:
class RangeEditor : public QWidget
Q_OBJECT
public:
RangeEditor( ... );
~RangeEditor();
public:
CurveView::ConfigAxes::Range range () const;
QVariant minimum() const;
QVariant maximum() const;
DataModel* model () const;
void range ( CurveView::ConfigAxes::Range range );
void minimum( QVariant minimum );
void maximum( QVariant maximum );
void model ( DataModel* model );
public slots:
void rangeTypeChanged( int type );
private: // --- External editors
QComboBox* editRange_;
QSpinBox* editMinimum_;
QSpinBox* editMaximum_;
QComboBox* editModel_;
;
RangeEditor::RangeEditor( ... ) : QWidget(parent)
editRange_ = new QComboBox(this);
editMinimum_ = new QSpinBox (this);
editMaximum_ = new QSpinBox (this);
editModel_ = new QComboBox(this);
QHBoxLayout* layout = new QHBoxLayout();
setLayout(layout);
layout->addWidget( editRange_ );
layout->addWidget( editMinimum_ );
layout->addWidget( editMaximum_ );
layout->addWidget( editModel_ );
editRange_->addItem( "Fixed" );
editRange_->addItem( "Source" );
editModel_->setCurrentIndex(0);
editModel_->hide();
QObject::connect( editRange_, SIGNAL(currentIndexChanged(int)),
this, SLOT (rangeTypeChanged(int)) );
void RangeEditor::rangeTypeChanged( int type )
if ( type==CurveView::ConfigAxes::FIXED )
editMinimum_->show();
editMaximum_->show();
editModel_->hide();
else if ( type==CurveView::ConfigAxes::SOURCE )
editMinimum_->hide();
editMaximum_->hide();
editModel_->show();
好的,所以现在,我创建了一个 QStyledItemDelegate 来为视图提供我的列的自定义编辑器。这是我的做法:
class ConfigAxesDelegate : public QStyledItemDelegate
public:
ConfigAxesDelegate( ... );
~ConfigAxesDelegate();
public:
virtual QWidget* createEditor ( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual void setEditorData ( QWidget* editor, const QModelIndex& index ) const;
virtual void setModelData ( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const;
virtual void updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
;
QWidget* ConfigAxesDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
if ( index.column()==0 ) // Position
PositionEditor* editor = new PositionEditor(parent);
return editor;
else if ( index.column()==1 ) // Range
RangeEditor* editor = new RangeEditor(parent);
return editor;
else
return QStyledItemDelegate::createEditor(parent,option,index);
void ConfigAxesDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const
// WHAT TO DO HERE?
editor->setGeometry( option.rect );
基本上,我得到的是一个单像素高度编辑器。
这是结果的截图:
我尝试将updateEditorGeometry
更改为以下内容:
void ConfigAxesDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index ) const
QRect r = option.rect;
r.setSize( editor->sizeHint() );
editor->setGeometry( r );
这似乎解决了大小问题,但不是位置:
我感到有点失落,因为我不知道问题是来自我的自定义小部件(没有为 Qt 提供足够的信息来正确计算其位置)还是视图(可能是一些会压坏编辑器大小的边距) ,或updateEditorGeometry()
方法。
非常感谢您的帮助,感谢阅读!
【问题讨论】:
【参考方案1】:我会说通过调用来设置编辑器的几何形状:
editor->setGeometry(rect);
应该可以正常工作;在您的情况下发生的情况是您的编辑器是使用 QHBoxLayout 构建的,它设置了默认边距和间距。您的 tableview 行的默认高度小于编辑器的高度,这会使您的编辑器调整大小;屏幕截图上的一个像素行将是:上边距 + 控件的剩余部分 + 下边距。
通过为您的表格视图启用垂直标题,您将能够调整行高以使您的编辑器控件完全可见。
你可以做什么:
1.删除\减少布局的间距和边距:
QHBoxLayout* layout = new QHBoxLayout();
layout->setSpacing(1);
layout->setMargin(1);
setLayout(layout);
在这种情况下,以这种方式更新编辑器的几何图形:
QRect rect = option.rect;
QSize sizeHint = editor->sizeHint();
if (rect.width()<sizeHint.width()) rect.setWidth(sizeHint.width());
if (rect.height()<sizeHint.height()) rect.setHeight(sizeHint.height());
editor->setGeometry(rect);
或者只是
editor->setGeometry(rect);
应该适合你
2.您也可以考虑为您的行\单元格值使用弹出编辑器
3.调整小部件的行高以适应单元格编辑器。
希望这有帮助,问候
【讨论】:
用源代码说明的清晰答案。像魅力一样工作(我使用了您的解决方案 1.)。你真的拯救了我的一天,非常感谢! 大家好,我有一个类似的代码,但如果 rect 大于前一个 rect 则不起作用。我的编辑器是一个简单的行编辑,但它只会缩小而不会水平扩展。请问有什么想法吗? @mhstnsc 将其作为新问题打开 @neuronet 好吧,该项目接受了这个问题,现在我不需要答案。更多我们尝试远离 Qt Gui。这是邪恶的国际海事组织。我们将核心逻辑保留在 Qt 中,但可能在 C# 中显示 UI 我认为重要的是要注意,如果您有布局,边距可能是问题的原因,正如我在这里发现的那样:qtcentre.org/threads/…以上是关于QStyledItemDelegate - updateEditorGeometry 如何工作?的主要内容,如果未能解决你的问题,请参考以下文章
没有为 QTableView 行调用 QStyledItemDelegate 的 sizeHint 方法
QStyledItemDelegate 部分选择默认 QLineEdit 编辑器的文本
如何使用 QStyledItemDelegate 在 QTreeWidget 中拥有不同高度的 QTreeWidgetItems?
自定义 QStyledItemDelegate - 将编辑应用到模型