1

I want to achieve something like this using QPainter

I tried using 2 rounded rectangles in QPainter side by side but I was unable to achieve the image above.

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    QRectF leftRect= QRectF(0, 0, 300, 150);
    QRectF rightRect= QRectF(300, 0, 300, 150);
    painter.fillRect(leftRect, QColor("black");
    painter.drawRoundedRect(leftRect,15,35);
    painter.setPen(QPen("white"));
    painter.setPen(QPen("black"));
    painter.fillRect(rightRect, QColor("white");
    painter.drawRoundedRect(rightRect,15,35);    

This is what I tried and got this enter image description here

I tried this with QPainterPath

QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QRectF leftRect= QRectF(0, 0, 300, 150);
QRectF rightRect= QRectF(300, 0, 300, 150);
QPainterPath path;
path.setFillRule(Qt::WindingFill);
path.addRoundedRect(leftRect, 15, 35);
QPen pen(Qt::white, 1);
painter.setPen(pen);
painter.fillPath(path, Qt::black);
painter.drawPath(path);

QPainterPath path2;
path2.setFillRule(Qt::WindingFill);
QPen pen1(Qt::black, 1);
painter.setPen(pen1);
path2.addRoundedRect(rightRect, 15, 35);

painter.fillPath(path2, Qt::white);
painter.drawPath(path2);  

And got this : enter image description here

Rubina
  • 123
  • 1
  • 17

2 Answers2

3

The best Qt has to offer in this regard is separate x and y rounding radii. So nothing that will do it for you out the box.

It seems like the way to go to get that geometry is to use QPainterPath to compose the shape out of several sub-components, in your case an arc for the radius and 3 lines for the rest.

You should be able to translate and mirror the painter to draw the other side. So you fill and outline the left side, then flip the painter and outline the right side.

Also, in case you are drawing something like say a progress bar, there is another course of action. You will draw a regular rounded rectangle and use it as a mask, and then you can fill the amount you want by drawing a regular rectangle, that will be clipped in the desired shape by the mask.

OK, seems like you will need some extra help, here is some working code you can tweak:

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    QPainterPath path;

    // compose the "half"
    path.moveTo(20, 0);
    path.lineTo(100, 0);
    path.lineTo(100, 40);
    path.lineTo(20, 40);
    path.arcTo(0, 0, 40, 40, -90, -180);

    // draw black half
    painter.setBrush(Qt::black);
    painter.setPen(QPen(Qt::black, 1));
    painter.drawPath(path);

    // mirror and reposition the painter
    QTransform mirror(-1, 0, 0, 0, 1, 0, 0, 0, 1);
    painter.setTransform(mirror);
    painter.translate(-200, 0);

    // draw white half
    painter.setBrush(Qt::white);
    painter.drawPath(path);
dtech
  • 47,916
  • 17
  • 112
  • 190
  • Could you show sample working code in do so . Because I tried using QPainterPath. It did not render properly – Rubina Jun 28 '18 at 16:41
  • Post your code and the result in the question to see what's going wrong. – dtech Jun 28 '18 at 16:44
0

Similar result can be achieved using QPainter.setClipPath

progress bar with round borders

    percent = 30
    border_radius = 10

    bar_color = Qt.gray
    bar_progress_color = Qt.black

    painter = QPainter(self)

    painter.setRenderHint(QPainter.Antialiasing)

    path = QPainterPath()

    path.addRoundedRect(QRectF(self.rect()), border_radius, border_radius)
    painter.setClipPath(path)

    painter.setPen(Qt.NoPen)
    painter.setBrush(QColor(bar_color))

    painter.drawRect(self.rect())

    if percent > 0:
        painter.setBrush(bar_progress_color)

        percent = percent / 100
        percent_rect = QRect(0, 0, self.width() * percent, self.height())

        painter.drawRect(percent_rect)

If you also want to get the black border then add

    painter.setPen(Qt.black)
    painter.setBrush(Qt.NoBrush)
    painter.drawRoundedRect(QRectF(self.rect()), border_radius, border_radius)
vzhd1701
  • 91
  • 1
  • 3