本文主要梳理总结了我自己在项目开发过程中经常遇到的一个问题,就是用QPainter
进行图形绘制时,边角显示不完整的现象。这个问题虽然比较简单,但是很容易忘记,每次绘图时都要调试一下,故总结于此,方便以后查阅,也方便同行伙伴参考。
Painter
绘制我们知道,QPainter
简直是王者,任何图形都可以由它绘制出来。
如上图所示,项目中在制作这个页面时,我们会将每个部分制作成一个单独的控件,这个控件继承于QPushButton
类,并重写void resizeEvent(QResizeEvent *event)
和void paintEvent(QPaintEvent *event)
两个函数,其中前者主要获取并设定这个控件中图标
和文字
的相对位置,后者要主负责对控件重新绘制。
在类的初始化时,要设定可选中属性:setFocusPolicy(Qt::StrongFocus)
。
下面将其主要代码放在下面:
void QToolItem::resizeEvent(QResizeEvent *event)
{
//获取相关的矩形区域、边框圆角和线宽等
......
//初始化路径
m_btnPath = QPainterPath();
m_btnPath.setFillRule(Qt::WindingFill);
m_btnPath.addRoundedRect(rect(), m_corner, m_corner);
//最后调用父类的resizeEvent
QPushButton::resizeEvent(event);
}
void QToolItem::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.save();
painter.setRenderHints(QPainter::Antialiasing, true); //打开防锯齿
//若选中状态时,绘制边框
if(hasFocus())
{
painter.fillPath(m_btnPath, m_clrSelectedBk); //先填充路径
painter.setPen(QPen(m_clrBorder, m_borderWidth));
painter.drawRoundedRect(rect().adjusted(1,1,-1,-1), m_corner, m_corner); //再画边框
}
else
{
painter.fillPath(m_btnPath, m_clrResetBk);
}
painter.setRenderHints(QPainter::Antialiasing, false); //关闭反走样
//画图标
QString tempPicture = m_strPixPath;
if(!tempPicture.isEmpty())
{
if(!m_isRunning)
tempPicture += "_1.png";
else
tempPicture += "_2.png";
painter.drawImage(m_rectMap, QImage(tempPicture));
}
//画标题文字
painter.setFont(m_ftTitle);
if(!m_isRunning)
painter.setPen(m_clrTitleReset);
else
painter.setPen(m_clrTitleStart);
painter.drawText(m_rectTitle, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextWordWrap, m_strTitle);
//画描述文字
painter.setFont(m_ftDesc);
painter.setPen(m_clrDesc);
painter.drawText(m_rectDesc, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, m_strDesc);
painter.restore();
这里在绘制圆角矩形区域时,一定要注意,要先填充区域后,再绘制边框。若先绘制边框,再填充区域,会导致边框线看不到,只能显示四个圆角处的点线。
另一个比较重要的点是,在绘制边框时,若直接使用这句:
painter.drawRoundedRect(rect(), m_corner, m_corner);
则会导致线很细,即使你加粗了线宽,也不是很明显。为什么会这样呢?这是因为painter
在绘制时都是从0
像素开始的,例如,若要绘制100
的长度,它实际绘制的是从0
到99
像素。因此,我们设置边框线宽为2
时,其可见的也只有一个像素。我们可以修改一下,用下面这句:
painter.drawRoundedRect(rect().adjusted(1,1,-1,-1), m_corner, m_corner);
这相当于是将画边框的位置略微向内移动了一个像素,即可得到完美的效果。
另外,对于绘制图形时,反走样特性,不能随便开,绘制完成后要记得随手关闭。在绘制直线时,不要打开反走样特性,否则,直线绘制显示会很模糊。
Layout
布局 对于上面项目中的控件,若不绘制的话,也可以通过布局实现,你可根据自己的开发场景选择。其示例代码如下:
QLabel* label = new QLabel();
QLabel* label2 = new QLabel();
label2->setStyleSheet(QString("border:1px solid red;"));
label->setStyleSheet(QString("border:1px solid red;"));
label2->setPixmap(QPixmap("E:/QtCode/QPushbuttonPaintIcon/upgrade.png"));
label->setText("升级工具");
label->setFixedWidth(80);
QHBoxLayout* myLayout = new QHBoxLayout();
myLayout->addSpacing(10);
myLayout->addWidget(label2);
myLayout->addSpacing(30);
myLayout->addWidget(label);
myLayout->addStretch();
ui->pushButton->setLayout(myLayout);
本文到此结束!
如果对你有帮助,请随手 点赞 或 点喜欢!
=======================================================
欢迎【关注、私信 @武三郎】。我们一起交流一起进步。