QMemu 阴影实现
# 菜单阴影
Qt自带的菜单太单调了,要自己定制,所以简单修改了Qss
QString qss = "QMenu {\
background-color : rgb(255,255,255);\
padding : 5px;\
margin : 5px;\
border : 1px solid gray;\
border-radius:10px;\
}\
QMenu::item {\
font-size:10pt;\
color: rgb(0,0,0);\
background-color: transparent;\
padding: 8px 25px 6px 10px;\
margin: 4px 1px;\
}\
QMenu::item:selected {\
background-color : lightblue;\
border-radius:5px;\
}\
QMenu::icon:checked {\
background: rgb(253,253,254);\
position: absolute;\
top: 1px;\
right: 1px;\
bottom: 1px;\
left: 1px;\
}\
QMenu::icon:checked:selected {\
background-color : rgb(236,236,237);\
}\
QMenu::separator {\
height: 2px;\
background: rgb(235,235,236);\
margin-left: 5px;\
margin-right: 5px;\
}\
";
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
设置四周圆角,所以需要吧原先的背景透明
// pop menu的基本属性,不加这个menu点其他位置不消失
// framelesswindowhint 如果设置圆角需要这个,让他变成无边框, 显示圆角
// nodropshawWindowhint 不显示阴影,(在某些平台下)因为默认右侧与下侧有阴影,所以导致右下角不显示圆角
setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
// 设置背景透明,让四个角只显示圆角,不显示其他黑的部分
setAttribute(Qt::WA_TranslucentBackground);
2
3
4
5
6
# QGraphicsDropShadowEffect
上面设置了不显示自带阴影,但是还是想要菜单有阴影的,所以理所当然的,想到了无边框窗口的常用方法,使用 QGraphicsDropShadowEffect
// 注意在Qss中留出margin,给阴影显示的空间
QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this);
shadow->setOffset(0, 0);
shadow->setColor(QColor("#444444"));
shadow->setBlurRadius(10);
setGraphicsEffect(shadow);
2
3
4
5
6
7
但是一般无边框窗口我们是在widget里面嵌套一个子Widget留出margin,这个子widget才是真正的显示窗口,setGraphicsEffect作用于这个子widget。
而上面的写法是直接作用于QMenu的主Widget上了。
所以当窗体重新刷新的时候会报error
UpdateLayeredWindowIndirect failed for ptDst=(1367, 153), size=(199x219), dirty=(219x239 -10, -10) (参数错误。)
大概就是画到了QMenu窗口外面。
虽然看起来没什么大问题,因为程序不会崩溃,菜单与阴影也正常显示。
但是当你把QMenu作为类的成员变量时,选择一个QMenu的Action后,再次唤出菜单时,会发现,你上次的选择作为残影留在了上面。没有刷新。
当然,解法也很简单。
出现上面的的原因是QMenu还是同一个menu,因为error没有正常刷新,所以第二次出来时,会留有第一次操作的残影。
那我们用完就销毁好了。每次用的都是新的Menu,作为一个临时变量使用,选择完就销毁。
# QPainter
但是如果还是想要优雅一点。
那么就使用另一种阴影方式,用QPainter画出来
#define SHADOW_WIDTH 10 // 阴影边框宽度;
MyShadowWidget::MyShadowWidget(QWidget *parent)
: QWidget(parent)
{
this->setWindowFlags(Qt::FramelessWindowHint);
this->setAttribute(Qt::WA_TranslucentBackground);
}
void MyShadowWidget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.fillRect(QRect(SHADOW_WIDTH, SHADOW_WIDTH, this->width() - 2 * SHADOW_WIDTH, this->height() - 2 * SHADOW_WIDTH), QBrush(Qt::white));
QColor color(50, 50, 50, 30);
for (int i = 0; i < SHADOW_WIDTH; i++)
{
color.setAlpha(120 - qSqrt(i) * 40);
painter.setPen(color);
// 方角阴影边框;
// painter.drawRect(SHADOW_WIDTH - i, SHADOW_WIDTH - i, this->width() - (SHADOW_WIDTH - i) * 2, this->height() - (SHADOW_WIDTH - i) * 2);
// 圆角阴影边框;
painter.drawRoundedRect(SHADOW_WIDTH - i, SHADOW_WIDTH - i, this->width() - (SHADOW_WIDTH - i) * 2, this->height() - (SHADOW_WIDTH - i) * 2, 4, 4);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
但是这种方式毕竟是画出来的,效率可能不太高,效果也可能没有那么好,但是只是一个QMenu,问题不大
# 图片
据说还有用阴影图片的方法,但是我没使用过。放个连接
https://www.i4k.xyz/article/GoForwardToStep/99549750