带圆角的 QDialog 有黑角而不是半透明 [英] QDialog with rounded corners have black corners instead of being translucent

查看:395
本文介绍了带圆角的 QDialog 有黑角而不是半透明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建一个带有半透明圆角的

圆形边缘清晰可见,但带有各种黑色背景".确认一下,这个 Dialog 是一个由 QMainWindow 中的 QThread 启动的模态对话框.它不是父窗口.

QDialog(根)组件的 CSS 是:

QDialog {背景颜色:rgba(250, 250, 250, 255);边框半径:30px;颜色:#3C3C3C;}

具有如下所示的组件布局

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

UpdateDialog::UpdateDialog(QWidget *parent) :QDialog(父),用户界面(新用户界面::更新对话框){ui->setupUi(this);setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect();效果-> setBlurRadius(5);this->setGraphicsEffect(effect);}

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

ui->setupUi(this);statusBar()->隐藏();setWindowFlags(Qt::FramelessWindowHint);setAttribute(Qt::WA_TranslucentBackground, true);//设置圆角样式setStyleSheet("QMainWindow {\n background-color:rgba(240,240,240,255);\n border-radius: 30px;\n}\n\nQDialog {\n border-radius: 30px;\n}");//给主窗口添加阴影QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect(ui->mainWindow);效果-> setBlurRadius(5);效果-> setOffset(4, 4);this->setGraphicsEffect(effect);

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

解决方案

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

消息框实现:

#include 类 RoundedMessageBox : 公共 QMessageBox{Q_OBJECT上市:显式 RoundedMessageBox(QWidget *parent = nullptr) :QMessageBox(父){//FramelessWindowHint 标志和 WA_TranslucentBackground 属性至关重要.setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);setAttribute(Qt::WA_TranslucentBackground);}qreal 半径 = 0.0;//以绝对像素为单位的所需半径qreal borderWidth = -1.0;//-1 : 使用样式提示框宽度;0 : 无边框;>0 : 使用这个宽度.受保护:void paintEvent(QPaintEvent *) 覆盖{if (!(windowFlags() & Qt::FramelessWindowHint) && !testAttribute(Qt::WA_TranslucentBackground))返回;//没事做QPainter p(this);p.setRenderHint(QPainter::Antialiasing);//有样式表吗?如果 (testAttribute(Qt::WA_StyleSheetTarget)) {//让 QStylesheetStyle 随我们.QStyleOption 选项;opt.initFrom(this);style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);p.end();返回;}//画你自己.QRectF rect(QPointF(0, 0), size());//检查边框大小.qreal penWidth = borderWidth;如果(笔宽 <0.0){QStyleOption 选项;opt.initFrom(this);penWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, this);}//有笔吗?如果(笔宽 > 0.0){p.setPen(QPen(palette().brush(foregroundRole()), penWidth));//确保边框适合可用空间.const qreal dlta = penWidth * 0.5;rect.adjust(dlta, dlta, -dlta, -dlta);}别的 {//QPainter 在 QWidget 上初始化时带有默认的 1px 笔.p.setPen(Qt::NoPen);}//从调色板角色设置画笔.p.setBrush(palette().brush(backgroundRole()));//有半径吗?否则绘制一个更快的矩形.如果(半径 > 0.0)p.drawRoundedRect(矩形,半径,半径,Qt::AbsoluteSize);别的p.drawRect(rect);//C'est finíp.end();}};

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

int main(int argc, char *argv[]){//QApplication::setStyle("Fusion");QApplication app(argc, argv);//对话框设置RoundedMessageBox *msgBox = new RoundedMessageBox();msgBox->setAttribute(Qt::WA_DeleteOnClose);msgBox->setMinimumSize(300, 300);msgBox->setWindowTitle("无框窗口测试");msgBox->setText("

无框圆形消息框.

");msgBox->setInformativeText("Lorem ipsum dolor sat amet, consectetur adipiscing elit. Aenean tankerum 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"在时代.整数 id tortor elementum,dictum urna sed,tincidunt metus.Proin ultrices tempus""lacinia.整数坐 amet fringilla nunc.");如果 (1) {//使用 QSS 样式app.setStyleSheet(QStringLiteral("QDialog { "边框半径:12px;"边框:3.5px 实心;"边框颜色:qlineargradient(x1:1,y1:1,x2:0,y2:0,停止:0#ffeb7f,停止:1#d09d1e);"背景:qlineargradient(x1:0,y1:0,x2:1,y2:1,停止:0#ffeb7f,停止:1#d09d1e);"颜色:#003200;"}"));}别的 {//使用原生"样式msgBox-> 半径 = 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());Q调色板朋友;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);//默认为 WindowTextmsgBox->setBackgroundRole(QPalette::Window);//这实际上已经是默认值}//阴影不起作用.//QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect();//效果->setBlurRadius(2);//msgBox->setGraphicsEffect(effect);msgBox->show();返回 app.exec();}

<小时>

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

结果我可以在新应用程序中使用一个简单的无框对话框作为关于"消息框......所以你开始吧.这是我能想到的最简单的方法,无需重新实现小部件绘制过程(就像在 Qt 时钟示例中一样).但是这种实现显然有局限性,我还没有在 Mac 上尝试过.

此外,阴影非常方便......虽然你实际上看不到它,但它在平滑角落方面做得很好.好主意,即使这不是最初的意图.:)

#include int main(int argc, char *argv[]){QApplication app(argc, argv);//对话框设置.实际上使用 QMessageBox 作为一个较短的例子.QMessageBox *msgBox = new QMessageBox();msgBox->setAttribute(Qt::WA_DeleteOnClose);msgBox->setMinimumSize(300, 300);msgBox->setWindowTitle("无框窗口测试");//可能仍然可见,例如.在任务栏中msgBox->setText("

无框圆形消息框.

");msgBox->setInformativeText("Lorem ipsum dolor sat amet, consectetur adipiscing elit. Aenean tankerum erate 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"在时代.整数 id tortor elementum,dictum urna sed,tincidunt metus.Proin ultrices tempus""lacinia.整数坐 amet fringilla nunc.");//这里是样式位...首先需要无框窗口标志提示msgBox->setWindowFlags(msgBox->windowFlags() | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);//所需的边界半径;const int 半径 = 12;//使用 CSS 设置框样式.在此处设置边框半径.//边框样式有助于混合角,但可以省略.//背景是可选的...也可以在这里添加其他样式.msgBox->setStyleSheet(QString("QDialog { "边界半径:%1px;"边框:2px 实心调色板(阴影);"背景颜色:调色板(基础);"}").arg(半径));//效果在圆角窗口之外实际上是不可见的,//但它确实有助于摆脱像素化的圆角.QGraphicsDropShadowEffect* effect = new QGraphicsDropShadowEffect();//颜色应与 CSS 中设置的边框颜色相匹配.效果-> setColor(QApplication::palette().color(QPalette::Shadow));效果-> setBlurRadius(5);msgBox->setGraphicsEffect(effect);//需要先显示盒子,然后才能获得正确的尺寸.msgBox->show();//在这里,我们绘制遮罩以覆盖切断"的角落,否则它们会显示出来.//遮罩的大小基于当前窗口的几何形状.如果窗口可调整大小(以某种方式)//然后需要在 resizeEvent() 中设置掩码.const QRect rect(QPoint(0,0), msgBox->geometry().size());QBitmap b(rect.size());b.fill(QColor(Qt::color0));QPainter 画家(&b);Painter.setRenderHint(QPainter::Antialiasing);Painter.setBrush(Qt::color1);//这个半径应该与 CSS 半径匹配Painter.drawRoundedRect(矩形,半径,半径,Qt::AbsoluteSize);画家结束();msgBox->setMask(b);返回 app.exec();}

I need to create a QDialog with rounded translucent corners. The problem is when doing so, the corners are translucent, but are somehow filled in by the Window's alpha property making it black (which is my understanding of the cause of the problem)

Clearly visible is the rounded edges, but with a black 'background' of sorts. To confirm, this Dialog is a modal dialog launched by a QThread from QMainWindow. It is not the parent window.

The CSS for the QDialog (root) component is:

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

with a Component Layout as shown below

I added a drop shadow effect on the QDialog too. This is the constructor code for the 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);
}

Notably, the parent QMainWindow has the following attributes set in its constructor

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

How do I make this QDialog to have rounded translucent corners?

解决方案

UPDATE: Here is a much better version. The pixelated corners were bugging me, among other things. This one looks smooth as silk and can be styled with either CSS or C++. It does require subclassing the QWidget to be rounded (unlike the first version), but it's worth it. Again I'm using a QMessageBox as the base widget here for simplicity (no layouts/etc), but it would work with any QWidget (may need a Qt::Dialog window flag added).

The message box implementation:

#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();
        }
};

Example usage showing both CSS and C++ styling options:

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


ORIGINAL: using a generic QMessageBox and setting a mask on it.

Turned out I could use a simple frameless dialog for an "about" message box in a new app... so here you go. This is the simplest method I can think of w/out re-implementing the widget painting process altogether (like in the Qt clock example). But there's clearly limits to this implementation, and I haven't tried it on a Mac yet.

Also, the drop shadow came in very handy... although you can't actually see it, it does a great job smoothing out the corners. Great idea, even if that wasn't the original intention. :)

#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();
}

这篇关于带圆角的 QDialog 有黑角而不是半透明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆