我想在QDialog上设置圆角。由于它是顶级窗口,border-radius不起作用,所以我要这样做:
QRegion EnterPinDialog::roundedRect(const QRect& rect, int r)
{
QRegion region;
// middle and borders
region += rect.adjusted(r, 0, -r, 0);
region += rect.adjusted(0, r, 0, -r);
// top left
QRect corner(rect.topLeft(), QSize(r*2, r*2));
region += QRegion(corner, QRegion::Ellipse);
// top right
corner.moveTopRight(rect.topRight());
region += QRegion(corner, QRegion::Ellipse);
// bottom left
corner.moveBottomLeft(rect.bottomLeft());
region += QRegion(corner, QRegion::Ellipse);
// bottom right
corner.moveBottomRight(rect.bottomRight());
region += QRegion(corner, QRegion::Ellipse);
return region;
}
我这样叫:
this->setMask(roundedRect(this->rect(), 8));
它有效,但问题是角落是像素化的。
有没有办法在没有这些像素化角落的情况下获得它?如果是,怎么样?
答案 0 :(得分:1)
显示 here 的 setAttribute(Qt.WA_TranslucentBackground,True)方法也有效...只需在顶级窗口设置此属性,使用 paintEvent()方法覆盖中的QPainterPath绘制窗口的形状。
以下是一些 (python) 代码,可帮助您为具有圆角的矩形构造或绘制QPainterPath。
def drawPartiallyRoundedRect(painter,x,y,w,h,
radiusTR, radiusBR, radiusBL, radiusTL,
doFill,fillColor,
doLine=False,lineColor=None,lineWidth=1,
antiAlias=True):
w2 = int(w/2.0)
h2 = int(h/2.0)
if (doLine):
x += lineWidth/2.0
y += lineWidth/2.0
w -= lineWidth
h -= lineWidth
T = y
L = x
R = x + w
B = y + h
# clamp values to fit within rect
if (radiusTR > w2):
radiusTR = w2
if (radiusTR > h2):
radiusTR = h2
if (radiusTL > w2):
radiusTL = w2
if (radiusTL > h2):
radiusTL = h2
if (radiusBL > w2):
radiusBL = w2
if (radiusBL > h2):
radiusBL = h2
if (radiusBR > w2):
radiusBR = w2
if (radiusBR > h2):
radiusBR = h2
diamTR = radiusTR + radiusTR
diamBR = radiusBR + radiusBR
diamBL = radiusBL + radiusBL
diamTL = radiusTL + radiusTL
p = QPainterPath()
if (radiusTR > 0.0):
p.moveTo(R, T + radiusTR);
p.arcTo(R-diamTR, T, diamTR, diamTR, 0.0, 90.0) # TR
else:
p.moveTo(R,T)
if (radiusTL > 0.0):
p.arcTo(L, T, diamTL, diamTL, 90.0, 90.0) # TL
else:
p.lineTo(L,T)
if (radiusBL > 0.0):
p.arcTo(L, B-diamBL, diamBL, diamBL, 180.0, 90.0); # BL
else:
p.lineTo(L,B)
if (radiusBR > 0.0):
p.arcTo(R-diamBR, B-diamBR, diamBR, diamBR, 270.0, 90.0); # BR
else:
p.lineTo(R,B)
p.closeSubpath();
if (antiAlias):
painter.setRenderHint(QPainter.Antialiasing,True)
else:
painter.setRenderHint(QPainter.Antialiasing,False)
if (doFill and fillColor):
painter.setBrush( fillColor )
elif ( doFill ): # pass doFill and None for fillColor to use current brush
pass
else:
painter.setBrush( Qt.NoBrush )
if ((lineWidth != 0.0) and doLine and lineColor):
pen = QPen( lineColor, lineWidth,
Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin )
painter.setPen( pen )
else:
painter.setPen( Qt.NoPen )
painter.drawPath( p )
答案 1 :(得分:1)
有点迟到这个派对,但也许它会帮助别人。这显示了如何通过在新的QBitmap上绘制来创建一个像素化较少的蒙版(它仍然没有真正抗锯齿,因为位图只有2种颜色,但曲线比直接使用QPainterPath要平滑得多)。
在我的情况下,我想掩盖放置在主窗口内的窗口小部件形状(作为中央窗口小部件)。 4个边缘周围有4个工具栏,我希望中心视图有圆角边框,让主窗口背景显示出来。正如Harald建议的那样,这不是通过CSS可行的,因为小部件的内容实际上没有剪切到圆形边框。
// MainView is simply a QWidget subclass.
void MainView::resizeEvent(QResizeEvent *event)
{
QBitmap bmp(size());
bmp.clear();
QPainter painter(&bmp);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setPen(QColor(Qt::black));
painter.setBrush(QColor(Qt::black));
painter.drawRoundedRect(geometry(), 20.0f, 20.0f, Qt::AbsoluteSize);
setMask(bmp);
}
它位于resizeEvent中,因为它需要知道当前的窗口小部件大小(使用size()
和geometry()
)。这是原始帖子的一个较短的替代品(我认为),但圆角边缘确实像素化。
void MainView::resizeEvent(QResizeEvent *event)
{
QPainterPath path;
path.addRoundedRect(geometry(), 20.0f, 20.0f, Qt::AbsoluteSize);
QRegion region = QRegion(path.toFillPolygon().toPolygon());
setMask(region);
}
答案 2 :(得分:-1)
根据您希望对话框看起来如何,您可以通过css完全重新设置窗口,它们遵循框模型,请参阅整个stylesheet文档。
border: 2px; border-radius 2px;
将为您提供2px宽的边框,半径为2px。
我一般你应该能够通过样式表来处理你的大部分ui定制需求