用户登录
用户注册

分享至

Qt项目中,用QPainter进行绘制图形时,边角显示不完整问题的梳理

  • 作者: 老实人n064
  • 来源: 51数据库
  • 2021-08-17

总第42篇

本文主要梳理总结了我自己在项目开发过程中经常遇到的一个问题,就是用QPainter进行图形绘制时,边角显示不完整的现象。这个问题虽然比较简单,但是很容易忘记,每次绘图时都要调试一下,故总结于此,方便以后查阅,也方便同行伙伴参考。

1.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的长度,它实际绘制的是从099像素。因此,我们设置边框线宽为2时,其可见的也只有一个像素。我们可以修改一下,用下面这句:

        painter.drawRoundedRect(rect().adjusted(1,1,-1,-1), m_corner, m_corner);

      

这相当于是将画边框的位置略微向内移动了一个像素,即可得到完美的效果。

另外,对于绘制图形时,反走样特性,不能随便开,绘制完成后要记得随手关闭。在绘制直线时,不要打开反走样特性,否则,直线绘制显示会很模糊。

2.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);

      

本文到此结束!

如果对你有帮助,请随手 点赞点喜欢

=======================================================

欢迎【关注、私信 @武三郎。我们一起交流一起进步。

软件
前端设计
程序设计
Java相关