【发布时间】:2021-08-19 23:27:24
【问题描述】:
我想制作一个在每个平台上看起来都一样的自定义按钮,而不是继承 QPushButton 或 QAbstractButton 而是 QWidget。这个按钮应该包含一个像素图作为图标和一个文本加上一个可选的字幕。到目前为止,我已经完成了这项工作,但问题是小部件的宽度。小部件本身被剪裁了一些宽度。
我的问题是,当我用画家画了很多东西时,父小部件如何知道小部件的新尺寸是多少?新大小可以是任何内容,具体取决于文本或像素图。
编辑 1
尺寸提示给出了所需尺寸的估计值
QSize Button::sizeHint() const {
QFont nameFont(font());
QFont descriptionFont(font());
QFontMetrics nameFontMetric(nameFont);
QFontMetrics descriptionFontMetric(descriptionFont);
nameFont.setBold(true);
QSize result(0, 0);
result.setWidth(getPixmap().width() + 5
+ nameFontMetric.horizontalAdvance(' ')
+ qMax(descriptionFontMetric.boundingRect(m_ptr->description).width(), nameFontMetric.boundingRect(m_ptr->name).width()));
result.setHeight(qMax(getPixmap().height(),
nameFontMetric.boundingRect(m_ptr->name).height() + descriptionFontMetric.boundingRect(m_ptr->description).height()));
return result;
}
paint方法是从paintEvent方法中调用的,在该方法中使用QPainter(this)创建一个painter
void Button::paint(QPainter *painter)
{
QRect drawingRect;
QFont nameFont(painter->font());
QFont descriptionFont(painter->font());
nameFont.setBold(true);
descriptionFont.setPointSize(nameFont.pointSize() / 1.5);
QFontMetrics nameFontMetric(nameFont, painter->device());
QFontMetrics descriptionFontMetric(descriptionFont, painter->device());
auto nameFontRectInitial = nameFontMetric.boundingRect(m_ptr->name + " ");
auto nameFontRect = nameFontMetric.boundingRect(nameFontRectInitial, 0, m_ptr->name + " ");
auto descriptionFontRectInitial = descriptionFontMetric.boundingRect(m_ptr->description + " ");
auto descriptionFontRect = descriptionFontMetric.boundingRect(descriptionFontRectInitial, 0, m_ptr->description + " ");
// Get rect of widget so far
auto r = rect();
auto labelRect = r;
auto descriptionRect = r;
labelRect = labelRect.translated(getPixmap().width() + 5, 0);
descriptionRect = descriptionRect.translated(getPixmap().width() + 5, 0);
labelRect.setSize(nameFontRect.size());
descriptionRect.setSize(descriptionFontRect.size());
descriptionRect.translate(0, labelRect.height());
//setFixedSize((labelRect | descriptionRect).size());
drawingRect = labelRect | descriptionRect | getPixmap().rect();
drawingRect.adjust(0,0,5,0);
resize(drawingRect.size());
// Draw background
painter->fillRect(drawingRect, palette().color(QPalette::Button));
// Draw name
painter->setFont(nameFont);
painter->setPen(palette().color(QPalette::Text));
painter->drawText(labelRect, Qt::AlignTop | Qt::TextSingleLine, m_ptr->name);
// Draw description
painter->setFont(descriptionFont);
painter->setPen(palette().color(QPalette::Text));
painter->drawText(descriptionRect, Qt::AlignTop, m_ptr->description);
// Draw border
painter->setPen(palette().color(QPalette::Midlight));
painter->drawRect(drawingRect.adjusted(0, 0, -1, -1));
painter->drawPixmap(m_ptr->pixmapOrigin, m_ptr->pixmap);
到目前为止,我使用这种方法可以正常工作,但另一个问题是在我想要拉伸该小部件的布局中调整大小,以便一行中的所有小部件具有相同的宽度。好像不是这样,我不知道该怎么做。
编辑 2:
我通过使用 updateGeometry() 来告诉布局系统尺寸提示发生了变化(这就是我理解文档的方式)。这样做的缺点是我必须在内部保持大小并检查它是否在paintEvent内部发生了变化。
void Button::paint(QPainter *painter)
{
QRect drawingRect;
QFont nameFont(painter->font());
QFont descriptionFont(painter->font());
nameFont.setBold(true);
descriptionFont.setPointSize(nameFont.pointSize() / 1.5);
QFontMetrics nameFontMetric(nameFont, painter->device());
QFontMetrics descriptionFontMetric(descriptionFont, painter->device());
auto nameFontRectInitial = nameFontMetric.boundingRect(m_ptr->name + " ");
auto nameFontRect = nameFontMetric.boundingRect(nameFontRectInitial, 0, m_ptr->name + " ");
auto descriptionFontRectInitial = descriptionFontMetric.boundingRect(m_ptr->description + " ");
auto descriptionFontRect = descriptionFontMetric.boundingRect(descriptionFontRectInitial, 0, m_ptr->description + " ");
// Get rect of widget so far
auto r = rect();
auto labelRect = r;
auto descriptionRect = r;
labelRect = labelRect.translated(getPixmap().width() + 5, 0);
descriptionRect = descriptionRect.translated(getPixmap().width() + 5, 0);
labelRect.setSize(nameFontRect.size());
descriptionRect.setSize(descriptionFontRect.size());
descriptionRect.translate(0, labelRect.height());
drawingRect = labelRect | descriptionRect | getPixmap().rect();
drawingRect.adjust(0,0,5,0);
if(drawingRect.width() != m_ptr->w || drawingRect.height() != m_ptr->h) {
m_ptr->w = drawingRect.width();
m_ptr->h = drawingRect.height();
updateGeometry();
}
// Draw background
painter->fillRect(r, palette().color(QPalette::Button));
// Draw name
painter->setFont(nameFont);
painter->setPen(palette().color(QPalette::Text));
painter->drawText(labelRect, Qt::AlignTop | Qt::TextSingleLine, m_ptr->name);
// Draw description
painter->setFont(descriptionFont);
painter->setPen(palette().color(QPalette::Text));
painter->drawText(descriptionRect, Qt::AlignTop, m_ptr->description);
}
【问题讨论】:
-
请显示您迄今为止尝试过的代码(最好是minimal reproducible example)并查看
QWidget::sizeHint和QWidget::sizePolicy。
标签: c++ qt user-interface qt5