2010-09-30 18 views
4

Je souhaite définir des coins arrondis sur un QDialog. Comme il est une fenêtre de niveau supérieur, rayon de frontière ne fonctionne pas, donc je l'ai à faire:Coin arrondi non pixélisé pour la fenêtre de niveau supérieur

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; 
} 

et je l'appelle ainsi:

this->setMask(roundedRect(this->rect(), 8)); 

Il fonctionne, mais le problème est que les coins sont pixellisés.

Y at-il un moyen de l'obtenir sans avoir ces coins pixellisés? Si oui, comment?

Répondre

-1

En fonction de ce que vous voulez que la boîte de dialogue ressemble, vous pouvez complètement relooker même les fenêtres de niveau supérieur via css, elles adhèrent au modèle de boîte voir la documentation entière stylesheet.

border: 2px; border-radius 2px; 

Vous obtiendrez une bordure large de 2 pixels avec un rayon de 2 pixels.

Je général, vous devriez être en mesure de traiter la plupart de votre personnalisation ui a besoin à travers les feuilles de style

+0

Je ne suis pas d'accord avec Harald Scherirch. Voir [Qt Bug 3499] (https://bugreports.qt.nokia.com/browse/QTBUG-3499?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel) sur le système de suivi des bogues Qt –

+0

https://bugreports.qt-project.org/browse/QTBUG-3499 – Trilarion

1

Le setAttribute (Qt.WA_TranslucentBackground, True) Méthode montré here fonctionne aussi ... Il suffit de définir cet attribut dans votre fenêtre de niveau supérieur et peignez la forme de votre fenêtre à l'aide d'un QPainterPath dans une méthode paintEvent().

Voici quelques (python) Code qui pourrait vous aider à construire, ou de la peinture, le QPainterPath pour un rectangle avec des coins arrondis.

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

Un peu tard à cette fête, mais peut-être que cela aidera quelqu'un d'autre. Cela montre comment créer un masque moins pixélisé en dessinant au sommet d'un nouveau QBitmap (ce n'est pas vraiment anti-aliasé car un bitmap n'a que 2 couleurs, mais la courbe est beaucoup plus fluide que l'utilisation directe de QPainterPath).

Dans mon cas, je voulais masquer une forme de widget qui est placé dans une fenêtre principale (en tant que widget central). Il y a 4 barres d'outils autour des 4 bords, et je voulais que la vue du centre ait des bordures arrondies et que l'arrière-plan de la fenêtre principale soit visible. Ce n'était pas faisable via CSS, comme le suggère Harald puisque le contenu du widget ne s'est pas réellement découpé sur la bordure arrondie.

// 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); 
} 

Il est en resizeEvent parce qu'il a besoin de connaître la taille widget en cours (en utilisant size() et geometry()). Voici une alternative plus courte du post original (je pense), mais les bords arrondis deviennent pixélisés.

void MainView::resizeEvent(QResizeEvent *event) 
{ 
    QPainterPath path; 
    path.addRoundedRect(geometry(), 20.0f, 20.0f, Qt::AbsoluteSize); 
    QRegion region = QRegion(path.toFillPolygon().toPolygon()); 
    setMask(region); 
}