Circle user avatar issue



  • Hi! I want to make QLabel with the image circle:

    Code:

    QLabel *label = new QLabel(this);
    QPixmap avatarPixmap(":/Icon/default_avatar.png");
    label->setPixmap(avatarPixmap);
    label->setStyleSheet("border: 0.5px solid red; border-radius: 50%; background-clip: padding;");
    

    0_1517048799005_2018-01-27_122604.png

    It only rounds the QLabel, not the image. How to fix it? Thanks.



  • The easiest Way would be to make the Image rounded with Gimp or Photoshop.

    But if you want to do that with Code you need to override the paintEvent of the QLabel. With something like this.

    void CoverWidget::paintEvent(QPaintEvent *e)
    {
        Q_UNUSED(e)
     
        QImage image("image.jpg");
        QBrush brush(image);
     
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setBrush(brush);
        painter.drawRoundedRect(0, 0, width(), height(), 5, 5);
    }
    


  • @Fuel

    Yes, the only way is to override the paintEvent for QLabel

    Code:

    void AccountImage::paintEvent(QPaintEvent *event)
    {
        QPixmap pixmap(":/Icon/default_avatar.png");
        QBrush brush(pixmap);
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setBrush(brush);
        painter.drawRoundedRect(0, 0, width(), height(), 100, 100);
        QLabel::paintEvent(event);
    }
    

    0_1517054607704_2018-01-27_140145.png

    The image is rounded but not properly scaled. Any ideas?


  • Qt Champions 2017

    @Cobra91151

    Hi, did you have scaleContent on the QLabel ?
    since its now much bigger than before.
    you can use pixmap::scaled to scale it before drawing it.
    (notice it returns the scaled copy, not modify the original pixmap)

    Also note, its possible to draw on image with painter before setting it on QLabel
    so overriding paintEvent is not the only way. (strictly speaking)

    QPixmap pixmap(":/Icon/default_avatar.png");
    QBrush brush(pixmap);
    QPainter painter(&pixmap);
     painter.setRenderHint(QPainter::Antialiasing);
     painter.setBrush(brush);
     painter.drawRoundedRect(0, 0, pixmap.width(), pixmap.height(), 100, 100);
    label->setPixmap(pixmap);
    
    


  • @mrjj

    I have tried your solution.

    QPixmap pixmap(":/Icon/default_avatar.png");
    QBrush brush(pixmap);
    QPainter painter(&pixmap);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(brush);
    painter.drawRoundedRect(0, 0, pixmap.width(), pixmap.height(), 100, 100);
    ui->label->setScaledContents(true);
    ui->label->setFixedSize(100, 100);
    ui->label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    ui->label->setPixmap(pixmap);
    

    But it displays:
    0_1517056457575_2018-01-27_143334.png


  • Qt Champions 2017

    Hi
    You control the circle with
    painter.drawRoundedRect(0, 0, pixmap.width(), pixmap.height(), 100, 100);
    Currently it uses the width/height of the pixmap and will give that result.

    Maybe the
    http://doc.qt.io/qt-5/qpainter.html#drawEllipse
    will work better ?


  • Qt Champions 2017

    Hi
    What about

    painter.drawEllipse( QPoint(pixmap.width()/2, pixmap.height()/2), 80, 80);
    

    alt text



  • @mrjj

    Ok. I have used painter.drawEllipse(0, 0, pixmap.width(), pixmap.height());

    Result:
    0_1517057064275_2018-01-27_144334.png

    I think to override QLabel paintEvent method is better choice because I also need to click on that image.

    alt text

    But I should scale it properly.


  • Qt Champions 2017

    @Cobra91151
    Hi
    Yeah if you need click on label
    https://wiki.qt.io/Clickable_QLabel
    Then subclass is better.

    Just used the scaled function from pixmap to scale it.

    QPixmap scaled =pixmap.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
    painter->drawPixmap(0,0, scaled);



  • @mrjj

    I have override the paint event method:

    void AccountImage::paintEvent(QPaintEvent *event)
    {
        QPixmap pixmap(":/Icon/default_avatar.png");
        QPixmap scaled = pixmap.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
        QBrush brush(scaled);
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setBrush(brush);
        painter.drawPixmap(0, 0, scaled);
        QLabel::paintEvent(event);
    }
    

    The result is:

    0_1517058912493_2018-01-27_144334.png


  • Qt Champions 2017

    @Cobra91151
    Ok , that looks right ?



  • @mrjj

    No, it's just the image without circle borders.

    I have found another solution. To use setMask method:

    QPixmap pixmap(":/Icon/default_avatar.png");
    label->setPixmap(pixmap);
    label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    label->setFixedSize(100, 100);
    QRegion *region = new QRegion(0, 0, label->width(), label->height(), QRegion::Ellipse);
    label->setScaledContents(true);
    label->setMask(*region);
    

    The result:

    0_1517059803364_2018-01-27_152656.png

    It's looks good but the image edges is sharpen. Any ideas how to smooth it?


  • Qt Champions 2017

    @Cobra91151
    Hi
    But the code you shown did NOT draw circle so i thought you were aware of that ?
    The image looked rightly scaled.

    As far as i know its not possible to smooth a mask.


  • Qt Champions 2017

    Hi
    Do you need to do this dynamically since using 2 images would be much easier.
    But i assume you need multiple avatar images and hence having a "circled" version is
    not optimal ?



  • @mrjj

    What do you mean to use 2 images? The concept is to display user avatar when he signed in. So it will change dynamically.


  • Qt Champions 2017

    @Cobra91151
    One that is normal
    and one where you have drawn the highlight/circle on.
    and when you select/click QLabel you switch to that image.


  • Qt Champions 2017

    Ah so user will bring his own avatar image ?



  • @mrjj

    Yes.


  • Qt Champions 2017

    @Cobra91151
    Ok, then painting yourself seems better :)
    What was wrong with the paintEvent + scaled + drawEllipse ?
    since you are now looking into masks



  • @mrjj

    I draws the image but not rounds it.

    void AccountImage::paintEvent(QPaintEvent *event)
    {
        QPixmap pixmap(":/Icon/default_avatar.png");
        QPixmap scaled = pixmap.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
        QBrush brush(scaled);
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setBrush(brush);
        painter.drawPixmap(0, 0, scaled);
        QLabel::paintEvent(event);
    }
    

    alt text


  • Qt Champions 2017

    Why not ?
    just need the
    painter.drawEllipse(0, 0, scaled.width(), scaled.height());
    after
    painter.drawPixmap(0, 0, scaled);



  • @mrjj

    drawPixmap is draws the pixmap, not circle. What method I should use to get image circle?


  • Qt Champions 2017

    @Cobra91151
    as before. drawEllipse



  • @mrjj

    Code:

    void AccountImage::paintEvent(QPaintEvent *event)
    {
        QPixmap pixmap(":/Icon/default_avatar.png");
        QPixmap scaled = pixmap.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
        QBrush brush(scaled);
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setBrush(brush);
        painter.drawPixmap(0, 0, scaled);
        painter.drawEllipse(0, 0, scaled.width(), scaled.height());
        QLabel::paintEvent(event);
    }
    

    0_1517062687531_2018-01-27_161733.png

    Still image is not fully in a circle.

    Update:
    It looks better here:

    0_1517062937546_2018-01-27_162205.png

    void AccountImage::paintEvent(QPaintEvent *event)
    {
        QPixmap pixmap(":/Icon/default_avatar.png");
        QBrush brush(pixmap);
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setBrush(brush);
        painter.drawRoundedRect(0, 0, width(), height(), 100, 100);
        QLabel::paintEvent(event);
    }
    

    But I can't scale it properly.


  • Qt Champions 2017

    Hi
    well can scale the image to less that the size of the
    QLabel so there are room to draw a circle around the image.
    Since the image is the size of the Label , you cant draw outside the image.

    so either make image smaller to it can be inside circle or
    make image smaller so it fits in circle.



  • @mrjj

    So now it looks much better:

    0_1517064100797_2018-01-27_164133.png

    void AccountImage::paintEvent(QPaintEvent *event)
    {
        QPixmap pixmap(":/Icon/default_avatar.png");
        QPixmap scaled = pixmap.scaled(width(), height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
        QBrush brush(scaled);
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setBrush(brush);
        painter.drawRoundedRect(0, 0, width(), height(), 100, 100);
        QLabel::paintEvent(event);
    }
    

  • Qt Champions 2017

    @Cobra91151
    Ah yes. Like brush.
    So you want image to be inside the circle and let it clip anything else.
    I thought you wanted to paint a circle on it. :)



  • @mrjj

    So finally I have set it properly and it works great!

    void AccountImage::paintEvent(QPaintEvent *event)
    {
        QPixmap pixmap(":/Icon/my_avatar.png");
        QPixmap scaled = pixmap.scaled(width(), height(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
        QBrush brush(scaled);
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setBrush(brush);
        painter.drawRoundedRect(0, 0, width(), height(), 100, 100);
        QLabel::paintEvent(event);
    }
    

    Result:

    0_1517065826536_2018-01-27_171006.png

    Thank you for the help.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.