Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Qt drawing a filled rounded rectangle with border

I want to draw a rectangle with rounded corners (border radius same for all 4 corners) with a specific color filling the entire rectangle, and a separate border color (say border is 1 px wide).

From my observation, Qt provides three methods - fillRect and drawRect and drawRoundedRect. I have tried them, they don't work like I want to. There is no method like fillRoundedRect. Which means that I can draw a rounded rectangle but it won't be filled with the color I want.

How do I do it? And also, I read that due to some aliasing problems, the corners are often rendered as unequal. How do I set it as equal for all four? Will painter.setRenderHint(QPainter::Antialiasing) suffice? Or do I have to do anything else?

like image 485
SexyBeast Avatar asked Mar 22 '15 16:03

SexyBeast


People also ask

What is a rounded edge rectangle called?

Download Notebook. A rounded rectangle is the shape obtained by taking the convex hull of four equal circles of radius and placing their centers at the four corners of a rectangle with side lengths and . A filled rounded rectangle with (or. ) is called a stadium.


2 Answers

You can create a QPainterPath, add the rounded rect to it, and then fill and stroke it:

QPainter p(this); p.setRenderHint(QPainter::Antialiasing); QPainterPath path; path.addRoundedRect(QRectF(10, 10, 100, 50), 10, 10); QPen pen(Qt::black, 10); p.setPen(pen); p.fillPath(path, Qt::red); p.drawPath(path); 

Note that even with antialiasing, 1 px border will probably never really look good, especially on a low DPI desktop monitor, on a high DPI mobile device it will be almost invisible.

enter image description here

If you create the rectangle as QRectF(9.5, 9.5, 100, 50) it will look better with 1 px antialiased border, because it will "snap" on the right pixel:

enter image description here

like image 85
dtech Avatar answered Sep 18 '22 15:09

dtech


The answer above (from @dtech) works great, but can sometimes end up with an uneven border around the roundedRect. Using QPainter.strokePath() instead of QPainter.drawPath() can fix this issue.

Here is a python implementation of QPushButton, with paintEvent reimplemented:

# I use PySide6, but whatever library should work. from PySide6.QtWidgets import QPushButton from PySide6.QtGui import QPainter, QPainterPath, QBrush, QPen from PySide6.QtCore import Qt, QRectF  class RoundedButton(QPushButton):     def __init__(self, text, bordersize, outlineColor, fillColor):         super(RoundedButton, self).__init__()         self.bordersize = bordersize         self.outlineColor = outlineColor         self.fillColor = fillColor         self.setText(text)      def paintEvent(self, event):         # Create the painter         painter = QPainter(self)         painter.setRenderHint(QPainter.Antialiasing)         # Create the path         path = QPainterPath()         # Set painter colors to given values.         pen = QPen(self.outlineColor, self.bordersize)         painter.setPen(pen)         brush = QBrush(self.fillColor)         painter.setBrush(brush)          rect = QRectF(event.rect())         # Slighly shrink dimensions to account for bordersize.         rect.adjust(self.bordersize/2, self.bordersize/2, -self.bordersize/2, -self.bordersize/2)          # Add the rect to path.         path.addRoundedRect(rect, 10, 10)         painter.setClipPath(path)          # Fill shape, draw the border and center the text.         painter.fillPath(path, painter.brush())         painter.strokePath(path, painter.pen())         painter.drawText(rect, Qt.AlignCenter, self.text()) 
like image 35
Umbral Reaper Avatar answered Sep 20 '22 15:09

Umbral Reaper