4

我想在 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));

它有效,但问题是角落被像素化了。

有没有办法在没有这些像素化角落的情况下获得它?如果是,如何?

4

3 回答 3

2

这个聚会有点晚了,但也许它会帮助别人。这显示了如何通过在新的 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);
}
于 2014-03-26T04:55:20.523 回答
1

此处显示的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 )
于 2012-01-04T09:21:07.783 回答
0

根据您希望对话框看起来像什么,您甚至可以通过 css 完全重新设置顶层窗口的样式,它们遵循盒子模型,请参阅整个样式表文档。

border: 2px; border-radius 2px;

会给你一个 2px 宽的边框,半径为 2px。

我一般来说,您应该能够通过样式表处理您的大部分 ui 自定义需求

于 2010-09-30T09:48:06.153 回答