在 QTableView 单元格的中心绘制 QPixmap
Painting QPixmap in the center of QTableView cell
我有一个运行良好的 QTableView,第一列包含一些缩略图,在此列的每个单元格中,缩略图都垂直居中,但不是水平居中。
我真的需要使用委托吗?
如果是,如何使用 QStyledItemDelegate 将它们水平居中?
您自己绘制不是必需的,但自定义代理是必需的。带样式的项目委托使用样式的控制元素绘制代码来绘制 CE_ItemViewItem
- 请参阅 the source code for Qt 5.5.0。绘图代码考虑了样式选项的 decorationAlignment
成员。不幸的是,没有数据角色可以将该对齐方式传递给样式的实现。相反,您必须覆盖委托中的对齐方式:
class DecorationAligningDelegate : public QStyledItemDelegate {
Q_OBJECT
Qt::Alignment const m_alignment;
public:
explicit DecorationAligningDelegate(Qt::Alignment alignment, QObject * parent = 0) :
QStyledItemDelegate(parent), m_alignment(alignment) {}
Qt::Alignment alignment() const { return m_alignment; }
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const {
auto opt = option;
opt.decorationAlignment = m_alignment;
QStyledItemDelegate::paint(painter, opt, index);
}
};
然后,将缩略图居中:
view.setItemDelegateForColumn(0,
new DecorationAligningDelegate(Qt::AlignHCenter, &view));
//or
view->setItemDelegateForColumn(0,
new DecorationAligningDelegate(Qt::AlignHCenter, view));
如果你真的想自己画,即使没有必要,样式选项中给出了要画的项目的矩形(option.rect
)。要绘制以项目矩形为中心的像素图,您可以执行以下操作:
QStyleOption option;
QPixmap pix;
QPainter painter;
...
painter.save();
auto loc = option.rect.center() - pix.rect().center()
painter.drawPixmap(loc, pix);
painter.restore();
构建自己的委托并继承QStyledItemDelegate。重写绘画方法。
然后做这样的事情:
void
MyDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
QPixmap pixmap;
pixmap.load("Your pixmap file path");
pixmap = pixmap.scaled(option.rect.width(), option.rect.height(), Qt::KeepAspectRatio);
// Position our pixmap
const int x = option.rect.center().x() - pixmap.rect().width() / 2;
const int y = option.rect.center().y() - pixmap.rect().height() / 2;
if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, option.palette.highlight());
}
painter->drawPixmap(QRect(x, y, pixmap.rect().width(), pixmap.rect().height()), pixmap);
}
我只保留我的版本,即文学是两个答案的结合。
class DecorationAligningDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit DecorationAligningDelegate(Qt::Alignment alignment, QObject *parent = nullptr)
: QStyledItemDelegate(parent), m_alignment(alignment) {}
Qt::Alignment alignment() const { return m_alignment; }
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QIcon icon = QIcon(qvariant_cast<QIcon>(index.data(Qt::DecorationRole)));
if (option.state & QStyle::State_Selected)
{
painter->fillRect(option.rect, option.palette.highlight());
}
icon.paint(painter, option.rect, m_alignment);
}
private:
Q_DISABLE_COPY(VDecorationAligningDelegate)
Qt::Alignment const m_alignment;
};
我假设您是这样定义项目的:
auto *item = new QTableWidgetItem();
item->setIcon(QIcon("Your pixmap file path"));
不要忘记设置委托。
我有一个运行良好的 QTableView,第一列包含一些缩略图,在此列的每个单元格中,缩略图都垂直居中,但不是水平居中。
我真的需要使用委托吗? 如果是,如何使用 QStyledItemDelegate 将它们水平居中?
您自己绘制不是必需的,但自定义代理是必需的。带样式的项目委托使用样式的控制元素绘制代码来绘制 CE_ItemViewItem
- 请参阅 the source code for Qt 5.5.0。绘图代码考虑了样式选项的 decorationAlignment
成员。不幸的是,没有数据角色可以将该对齐方式传递给样式的实现。相反,您必须覆盖委托中的对齐方式:
class DecorationAligningDelegate : public QStyledItemDelegate {
Q_OBJECT
Qt::Alignment const m_alignment;
public:
explicit DecorationAligningDelegate(Qt::Alignment alignment, QObject * parent = 0) :
QStyledItemDelegate(parent), m_alignment(alignment) {}
Qt::Alignment alignment() const { return m_alignment; }
void paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const {
auto opt = option;
opt.decorationAlignment = m_alignment;
QStyledItemDelegate::paint(painter, opt, index);
}
};
然后,将缩略图居中:
view.setItemDelegateForColumn(0,
new DecorationAligningDelegate(Qt::AlignHCenter, &view));
//or
view->setItemDelegateForColumn(0,
new DecorationAligningDelegate(Qt::AlignHCenter, view));
如果你真的想自己画,即使没有必要,样式选项中给出了要画的项目的矩形(option.rect
)。要绘制以项目矩形为中心的像素图,您可以执行以下操作:
QStyleOption option;
QPixmap pix;
QPainter painter;
...
painter.save();
auto loc = option.rect.center() - pix.rect().center()
painter.drawPixmap(loc, pix);
painter.restore();
构建自己的委托并继承QStyledItemDelegate。重写绘画方法。
然后做这样的事情:
void
MyDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
const QModelIndex& index) const
{
QPixmap pixmap;
pixmap.load("Your pixmap file path");
pixmap = pixmap.scaled(option.rect.width(), option.rect.height(), Qt::KeepAspectRatio);
// Position our pixmap
const int x = option.rect.center().x() - pixmap.rect().width() / 2;
const int y = option.rect.center().y() - pixmap.rect().height() / 2;
if (option.state & QStyle::State_Selected) {
painter->fillRect(option.rect, option.palette.highlight());
}
painter->drawPixmap(QRect(x, y, pixmap.rect().width(), pixmap.rect().height()), pixmap);
}
我只保留我的版本,即文学是两个答案的结合。
class DecorationAligningDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit DecorationAligningDelegate(Qt::Alignment alignment, QObject *parent = nullptr)
: QStyledItemDelegate(parent), m_alignment(alignment) {}
Qt::Alignment alignment() const { return m_alignment; }
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QIcon icon = QIcon(qvariant_cast<QIcon>(index.data(Qt::DecorationRole)));
if (option.state & QStyle::State_Selected)
{
painter->fillRect(option.rect, option.palette.highlight());
}
icon.paint(painter, option.rect, m_alignment);
}
private:
Q_DISABLE_COPY(VDecorationAligningDelegate)
Qt::Alignment const m_alignment;
};
我假设您是这样定义项目的:
auto *item = new QTableWidgetItem();
item->setIcon(QIcon("Your pixmap file path"));
不要忘记设置委托。