头像

张小飞

我有一壶酒,足以慰风尘

《Qt 跨平台 无边框 阴影方案的总结》

 3月前  •   Qt技巧  •   , , , ,  •   98  •   0

关于无边框跨平台的方案的一些总结,也发现了一些比较蛋疼的问题,但是也有了一些相应的解决方案,现在总结下。

一。创建一个子窗口,然后设置子窗口属性为透明,无焦点(setAttribute(Qt::WA_TranslucentBackground), setFocus(Qt::NoFocus)),子窗口installEventFilter父窗口来响应父窗口的resize的事件等等。

这种方案有个好处就是,这个子窗口模块化,任何窗口都能试用。缺点也有,就是不是完全跨平台,在某些Linux桌面环境下(比如Ubuntu),会出现多余的框,这个也没有好的办法解决掉。所以结论就是Windows平台可以用这个方法,Linux平台不太建议使用。

 

二。重写对应窗口的paintevent函数。这个方法虽说不是比较好的,而且写起来很麻烦,但是想要达到我们想要的跨平台的无边框阴影的方案,还是只能选择这个,这个上个写的小demo。

无边框窗口属性设置成这个。

c++	setWindowFlags(Qt::FramelessWindowHint);
	setAttribute(Qt::WA_TranslucentBackground);

 

重写paintevent函数,这里有两个解决方案,第一个是自己绘制,比我下边的代码;第二种就是重新绘制个图片,这样效率比较慢。但是代码比较好看

第一种:

c++	QPainterPath path;
	path.setFillRule(Qt::WindingFill);
	path.addRect(10, 10, this->width()-20, this->height()-20);

	QPainter painter(this);
	painter.setRenderHint(QPainter::Antialiasing, true);
	painter.fillPath(path, QBrush(Qt::transparent));

	QColor color(0,0,0,50);
	int arr[10] = {150,120,80,50,40,30,20,10,5,5};
	for(int i=0; i<10; i++)
	{
		QPainterPath path;
		path.setFillRule(Qt::WindingFill);
		if(i == 5)
			path.addRect(10-i-1, 10-i-1, this->width()-(10-i)*2, this->height()-(10-i)*2);
		else
			path.addRoundedRect(10-i-1, 10-i-1, this->width()-(10-i)*2, this->height()-(10-i)*2,2,2);

		color.setAlpha(arr[i]);
		painter.setPen(color);
		painter.drawPath(path);
	 }

最后别忘记,把这个窗口的layout的margin设置成10,看看我的paintevent,我addRect(10,—-)因为我只增加了10的宽度。懒得写了。

 

第二种:

c++	QPainter painter(this);
	painter.save();
	painter.setRenderHint(QPainter::Antialiasing, true);
	QPixmap pixShadow;
	//这里pixshadow可以弄个成员变量,省的每次load
	pixShadow.load(":/shadow.png");

	painter.fillRect(-6,-6,width()+12,height()+12,QColor(0, 0, 0,0));
	painter.drawPixmap(-6,-6,width()+12,height()+12,m_pixShadow);
	painter.restore();

 

图片在这里

 

 

这种方案还有一个问题,就是这个主窗口的子控件有的白色的时候,设置成这个属性

setAttribute(Qt::WA_TranslucentBackground);

有的子控件有的会变成透明。但是也没有很好的解决方案。这里是个大坑。既然是自定义的窗口,就乖乖的多照顾下子控件吧。

 

上一篇:
下一篇:

 评论


 已有0条评论

    还没有任何评论,你来说两句吧!