我需要创建一个带有圆角半透明圆角的QDialog。问题是这样做时,拐角是半透明的,但是不知何故被Window的alpha属性填充为黑色(这是我对问题原因的理解)]
清晰可见的是圆形边缘,但带有黑色的“背景”。为了确认,此对话框是由QThread
中的QMainWindow
启动的模式对话框。 不是父窗口。
QDialog
(根)组件的CSS是:
QDialog {
background-color: rgba(250, 250, 250, 255);
border-radius: 30px;
color: #3C3C3C;
}
具有如下所示的组件布局
我也在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
具有半透明的圆角?
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();
}
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();
}