带有圆角的QDialog具有黑色的角,而不是半透明的

问题描述 投票:0回答:1

我需要创建一个带有圆角半透明圆角的QDialog。问题是这样做时,拐角是半透明的,但是不知何故被Window的alpha属性填充为黑色(这是我对问题原因的理解)]

enter image description here

清晰可见的是圆形边缘,但带有黑色的“背景”。为了确认,此对话框是由QThread中的QMainWindow启动的模式对话框。 不是父窗口

QDialog(根)组件的CSS是:

QDialog {
    background-color: rgba(250, 250, 250, 255);
    border-radius: 30px;
    color: #3C3C3C;
}

具有如下所示的组件布局

enter image description here

我也在QDialog上添加了阴影效果。这是QDialog的构造函数代码:

UpdateDialog::UpdateDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::UpdateDialog)
{
    ui->setupUi(this);

    setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
    QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect();
    effect->setBlurRadius(5);
    this->setGraphicsEffect(effect);
}

值得注意的是,父QMainWindow在其构造函数中设置了以下属性

ui->setupUi(this);
statusBar()->hide();
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);

// Set rounded corners style
setStyleSheet("QMainWindow {\n  background-color:rgba(240,240,240,255);\n   border-radius: 30px;\n}\n\nQDialog {\n    border-radius: 30px;\n}");

// Add shadow to main window
QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect(ui->mainWindow);
effect->setBlurRadius(5);
effect->setOffset(4, 4);
this->setGraphicsEffect(effect);

如何使此QDialog具有半透明的圆角?

qt qwidget qdialog
1个回答
1
投票

UPDATE:这是一个更好的版本。像素化的角落让我烦恼。这看起来像丝绸一样光滑,可以用CSS或C ++设置样式。它确实需要对QWidget的子类进行四舍五入(与第一个版本不同),但这是值得的。再次,为了简单起见,我在这里使用QMessageBox作为基本窗口小部件(无布局/等),但是它可以与任何QWidget一起使用(可能需要添加Qt::Dialog窗口标志)。

消息框实现:

#include <QtWidgets>

class RoundedMessageBox : public QMessageBox
{
        Q_OBJECT
    public:
        explicit RoundedMessageBox(QWidget *parent = nullptr) :
          QMessageBox(parent)
        {
            // The FramelessWindowHint flag and WA_TranslucentBackground attribute are vital.
            setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
            setAttribute(Qt::WA_TranslucentBackground);
        }

        qreal radius = 0.0;        // desired radius in absolute pixels
        qreal borderWidth = -1.0;  // -1 : use style hint frame width;  0 : no border;  > 0 : use this width.

    protected:
        void paintEvent(QPaintEvent *) override
        {
            if (!(windowFlags() & Qt::FramelessWindowHint) && !testAttribute(Qt::WA_TranslucentBackground))
                return;  // nothing to do

            QPainter p(this);
            p.setRenderHint(QPainter::Antialiasing);

            // Have style sheet?
            if (testAttribute(Qt::WA_StyleSheetTarget)) {
                // Let QStylesheetStyle have its way with us.
                QStyleOption opt;
                opt.initFrom(this);
                style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
                p.end();
                return;
            }

            // Paint thyself.
            QRectF rect(QPointF(0, 0), size());
            // Check for a border size.
            qreal penWidth = borderWidth;
            if (penWidth < 0.0) {
                QStyleOption opt;
                opt.initFrom(this);
                penWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this);
            }
            // Got pen?
            if (penWidth > 0.0) {
                p.setPen(QPen(palette().brush(foregroundRole()), penWidth));
                // Ensure border fits inside the available space.
                const qreal dlta = penWidth * 0.5;
                rect.adjust(dlta, dlta, -dlta, -dlta);
            }
            else {
                // QPainter comes with a default 1px pen when initialized on a QWidget.
                p.setPen(Qt::NoPen);
            }
            // Set the brush from palette role.
            p.setBrush(palette().brush(backgroundRole()));
            // Got radius?  Otherwise draw a quicker rect.
            if (radius >= 0.0)
                p.drawRoundedRect(rect, radius, radius, Qt::AbsoluteSize);
            else
                p.drawRect(rect);

            // C'est finí
            p.end();
        }
};

示例用法同时显示CSS和C ++样式选项:

int main(int argc, char *argv[])
{
    //QApplication::setStyle("Fusion");
    QApplication app(argc, argv);

    // Dialog setup
    RoundedMessageBox *msgBox = new RoundedMessageBox();
    msgBox->setAttribute(Qt::WA_DeleteOnClose);
    msgBox->setMinimumSize(300, 300);
    msgBox->setWindowTitle("Frameless window test");

    msgBox->setText("<h3>Frameless rounded message box.</h3>");
    msgBox->setInformativeText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean fermentum erat rhoncus, "
                               "scelerisque eros ac, hendrerit metus. Nunc ac lorem id tortor porttitor mollis. Nunc "
                               "tristique orci vel risus convallis, non hendrerit sapien condimentum. Phasellus lorem tortor, "
                               "mollis luctus efficitur id, consequat eget nulla. Nam ac magna quis elit tristique hendrerit id "
                               "at erat. Integer id tortor elementum, dictum urna sed, tincidunt metus. Proin ultrices tempus "
                               "lacinia. Integer sit amet fringilla nunc.");

    if (1) {
        // Use QSS style
        app.setStyleSheet(QStringLiteral(
            "QDialog { "
                "border-radius: 12px; "
                "border: 3.5px solid; "
                "border-color: qlineargradient(x1: 1, y1: 1, x2: 0, y2: 0, stop: 0 #ffeb7f, stop: 1 #d09d1e); "
                "background: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #ffeb7f, stop: 1 #d09d1e); "
                "color: #003200; "
            "}"
        ));
    }
    else {
        // Use "native" styling
        msgBox->radius = 12.0;
        msgBox->borderWidth = 3.5;

        QLinearGradient bgGrad(0, 0, 1, 1);
        bgGrad.setCoordinateMode(QGradient::ObjectMode);
        bgGrad.setColorAt(0.0, QColor("gold").lighter());
        bgGrad.setColorAt(1.0, QColor("goldenrod").darker(105));
        QLinearGradient fgGrad(bgGrad);
        fgGrad.setStart(bgGrad.finalStop());
        fgGrad.setFinalStop(bgGrad.start());

        QPalette pal;
        pal.setBrush(QPalette::Window, QBrush(bgGrad));
        pal.setBrush(QPalette::Mid, QBrush(fgGrad));
        pal.setBrush(QPalette::WindowText, QColor("darkgreen").darker());
        msgBox->setPalette(pal);

        msgBox->setForegroundRole(QPalette::Mid);     // default is WindowText
        msgBox->setBackgroundRole(QPalette::Window);  // this is actually the default already
    }

    // Drop shadow doesn't work.
    //  QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect();
    //  effect->setBlurRadius(2);
    //  msgBox->setGraphicsEffect(effect);

    msgBox->show();
    return app.exec();
}

enter image description here


ORIGINAL:使用通用QMessageBox并在其上设置掩码。

事实证明,我可以在新应用中为“关于”消息框使用简单的无框架对话框,所以您就可以开始了。这是我可以想到的最简单的方法,完全不需要重新实现小部件绘制过程(就像Qt时钟示例中一样)。但是这种实现显然有局限性,我还没有在Mac上尝试过。

而且,阴影非常方便...尽管您实际上看不到它,但是它在平滑角落方面做得很好。好主意,即使那不是初衷。 :)

#include <QtWidgets>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    // Dialog setup. Actually use a QMessageBox for a shorter example.
    QMessageBox *msgBox = new QMessageBox();
    msgBox->setAttribute(Qt::WA_DeleteOnClose);
    msgBox->setMinimumSize(300, 300);
    msgBox->setWindowTitle("Frameless window test");  // might still be visible eg. in a taskbar
    msgBox->setText("<h3>Frameless rounded message box.</h3>");
    msgBox->setInformativeText("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean fermentum erat rhoncus, "
                               "scelerisque eros ac, hendrerit metus. Nunc ac lorem id tortor porttitor mollis. Nunc "
                               "tristique orci vel risus convallis, non hendrerit sapien condimentum. Phasellus lorem tortor, "
                               "mollis luctus efficitur id, consequat eget nulla. Nam ac magna quis elit tristique hendrerit id "
                               "at erat. Integer id tortor elementum, dictum urna sed, tincidunt metus. Proin ultrices tempus "
                               "lacinia. Integer sit amet fringilla nunc.");

    // Here come the styling bits... First need the frameless window flag hint
    msgBox->setWindowFlags(msgBox->windowFlags() | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
    // The desired border radius;
    const int radius = 12;
    // Style the box with CSS. Set the border radius here. 
    // The border style helps blend the corners, but could be omitted.
    // The background is optional... could add other styling here too.
    msgBox->setStyleSheet(QString(
        "QDialog { "
            "border-radius: %1px; "
            "border: 2px solid palette(shadow); "
            "background-color: palette(base); "
        "}"
    ).arg(radius));

    // The effect will not be actually visible outside the rounded window,
    // but it does help get rid of the pixelated rounded corners.
    QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect();
    // The color should match the border color set in CSS.
    effect->setColor(QApplication::palette().color(QPalette::Shadow));
    effect->setBlurRadius(5);
    msgBox->setGraphicsEffect(effect);

    // Need to show the box before we can get its proper dimensions.
    msgBox->show();

    // Here we draw the mask to cover the "cut off" corners, otherwise they show through.
    // The mask is sized based on the current window geometry. If the window were resizable (somehow)
    // then the mask would need to be set in resizeEvent().
    const QRect rect(QPoint(0,0), msgBox->geometry().size());
    QBitmap b(rect.size());
    b.fill(QColor(Qt::color0));
    QPainter painter(&b);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setBrush(Qt::color1);
    // this radius should match the CSS radius
    painter.drawRoundedRect(rect, radius, radius, Qt::AbsoluteSize);
    painter.end();
    msgBox->setMask(b);

    return app.exec();
}

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.