欧博会员开户:Windows高DPI系列控件(一) - 饼图

admin 3个月前 (07-04) 科技 43 0

目录
  • 一、醉一醉
  • 二、效果展示
  • 三、高DPI适配
    • 1、高DPI框架运作
    • 2、适配高DPI
    • 3、适配饼图
  • 四、相关文章

原文链接:Windos高DPI系列控件(一) - 饼图

一、醉一醉

眨眼功夫,2020年已往一半了。回忆最近一段时间的工作和生涯,总以为应该写点儿什么!

于是,最近有空就在想啊想,想想可以写点儿什么有用的器械好呢!恰好之前写过几篇关于高DPI的文章,不知道什么缘故原由,阅读量不是很高,因此设计以高DPI为索引最先引入一系列的控件使用案例,包罗Qt自带的控件、简朴图表和一些庞大的图表。

  1. Qt自带的控件就不说了,高DPI框架险些可以完善适配
  2. 简朴的图表这里主要会引入柱状图、折线图、饼图等
  3. 庞大图表主要是定制一些股票看盘相关图表,例如分时图、k线图等

对于民众软件来说,友好的支持4k显示器真的很有需要呢。一款好的民众桌面端软件需要适配种种操作系统,从快要被人们遗忘的Xp到现在占有率较高的Win10,若是想拥有一个好的用户体验,高DPI是必须要好好适配滴,这里作者准备了一个系列的高DPI控件适配文章分享给人人,主要整理我工作中遇到的种种控件,适配到已经开发好的高DPI框架中,并做出演示demo,提供给有需要的同砚,除过整理已有的控件,更多的是会开发一些更有意义的新控件,好比股票中的分时图、k线等。

目的:

  1. 推广我自己适配高DPI的方案,供人人讨论,是否有更好的优化空间
  2. 整理股票相关的控件,适配到我的高DPI框架中,提供给有需要的同砚参考
  3. 阶段性整理我自己的知识库,让零星的知识点汇聚起来

二、效果展示

如下图所示,适配高DPI交互效果。

左右两侧的显示物理尺寸一致,也就是占地面积一样大,差别的是左侧是1080p显示器,右侧是4k显示器

由于是视频录制缘故原由,可能会有视觉误差,现实看的话,左右两个窗体给人的视觉感受巨细是一样的。

《往返切换显示器》


《饼图支持操作》

三、高DPI适配

高DPI的适配思绪之前已经系统的剖析过,详情参看Qt之高DPI显示器(一) - 解决方案整理和Qt之高DPI显示器(二) - 自适配解决方案剖析两篇文章。

除过上述两篇文章外,之前设计中另有一篇文章要写,厥后实在是太忙了,一直没有写完,第三篇文章主要是想讲下怎么优化现有框架,让DPI适配效率变的更高,后边有机遇补上。

本票文章最先算是适配高DPI实践系列文章的开篇之作,饼图控件很早之前就分享过,详情参考Qt之自绘制饼图,怎么绘制饼图这里就不再形貌。本篇文章的焦点主要是举行了饼图高DPI的显示适配,后边会主要形貌下适配的细节,后期还会陆续接入更多更厚实的组件。

下面先带人人回首下适配高DPI我们都干了哪些事情,最后在看看饼图是怎么适配高DPI的。

1、高DPI框架运作

看过前两篇文章的同砚应该知道,我们适配高DPI主要从两个方面举行的,分别是窗体的物理尺寸和字体

物理尺寸

物理尺寸从字面上看就是软件巨细,不外我们这里的物理尺寸也包罗子窗口的巨细,那也就是说子窗口之间的间隙也在物理尺寸这里举行适配。

为了让开发同砚无感知的使用,我们新增了同样数目的可能会使用到的界面类,作为我们自己的基础类,而且重写了界面类中跟尺寸相关的函数,让人人使用界面类的时刻只换类名称,接口用法照样跟以前一样。

重写了尺寸函数,若是我们也知道当前显示器的DPI,缩放界面是不是就很简朴了!当前开发设置的尺寸乘以需要缩放的系数就是最终需要显示的尺寸,框架只需要把最后需要显示的尺寸设置给Qt的接口,也就是当前类的父类接口,这样我们的软件界面就实现了放大。做到这里算不算完呢?仔细想一想,开发同砚使用这些接口的时刻都是设置了96DPI下的尺寸,若是窗口移动到另一台差别DPI的显示器上,岂非我们要把所有set接口重新挪用一遍?若是数目少了还行,但一个庞大的软件这样的set接口会多的令你发指,若是你让开发同砚都挪用一遍,我估量他们会打死你。除过需要挪用以外,挪用顺序也至关主要,试想这样一种场景,若是需要缩放的窗体许多,你会希望窗体局部突然变大,没有汇率的跳动吗?谜底固然是否。

为了让窗体有纪律的缩放,那我们就需要控制缩放的顺序了,这里就需要分外的继续重写一些要害方式,之前我们重写类的时刻重写了尺寸相关函数,这一次我们还需要把结构相关的函数也举行重写,为的就是在界面结构的时刻我们把他们的关系记录下来,后续在泛起DPI变化时,我们凭据之前维护的结构关系,按层挪用每一个需要缩放的界面。

界面结构

这里普及一个知识点,平时我们所看到的软件界面是平面的,是一个二维的观点,然则软件界面在开发的历程中,界面的结构关系实在是一棵树,好比像下图这样的界面,界面A包罗了界面B和界面C,而界面B又包罗了两个界面D,这样当我们组织两个界面A时,实在所有的界面都被组织了两份,而且界面D被组织了四份。

字体巨细

我们适配的高DPI框架,除过自绘文字以外,其他情形是不需要关注字体怎么更改的,这些字体适配都在我们的高DPI适配框架中完成了,这里简朴形貌下字体适配高DPI的方式。

高DPI框架运行历程中,自动维护了1x、2x和3x下的qss文件,若是检测到程序所需要的Qss文件不在这三个设置中,那么框架会动态的凭据一个最接近当前缩放比的qss文件天生一个暂且qss文件,好比当前缩放比是1.8x,那么程序将会凭据2xqss文件,天生一个适合1.8x缩放比的qss文件,首先就是图片举行压缩显示,字号会乘以1.8然后除以2转换成1.8x缩放比下的字号,可能会有舍入,然则对于人人常用的0.5整数倍缩放比基本都是没有问题的,由于字号一样平常都是2的整数倍。

2、适配高DPI

高DPI框架设计之初就是想让开发同砚只管少的去费心DPI的事情,然则现实情形是另有少部分情形是需要自己去适配的,比方说自毁界面,这个时刻我们就需要自己去获取高DPI相关信息合理绘制

绘制文字

绘制文字时,我们需要获取当前的缩放系数,在合适的现实去缩放绘制相关参数,比方说,当我们绘制12px字体时,若是是在4k显示器下,我们的dpi可能为192,那么缩放系数就是2x,绘制文字时就需要绘制24px字体

缩放系数 = 当前显示器DPI / 96.0

有时刻绘制文字时可能会附带限制文字所在区域,96DPI下我们不需要费心区域是否会泛起问题,然则若是显示器DPI大于96时,文字绘制的区域我们也就需要响应的适配下,否则可能会泛起你不希望的效果。比方说,我们需要在坐标为10,10这个位置,以边框100px正方形框内绘制一段文本,96DPI下可能刚恰好能绘制完这段文字,若是192DPI下,我们把字号放大了一倍,若是绘制区域照样100px的正方形,那么文字很可能连一半都绘制不完。问题出在那里呢?很显然,字体变大了,我们的绘制区域一定也需要举行响应的放大,不妨试试200px的正方形是不是可以呢!谜底是Yes。

绘制图片

自绘界面时往往少不了绘制图片,下面具体剖析下怎么在随便DPI下绘制图片!

首先是获取1x缩放比下的图片路径,然后我们通过一个转换函数转换成我们当前显示器下需要的图片路径,并缩放图片,以到达最好的显示效果。

如下代码所示,是一个封装好的函数,主要完成了凭据1x图片路径获取我们将要绘制的图片,而且给我们返回的是内存地址。这里需要分外弥补下,Qt中的QPixmap是有做缓存机制的,当我们第二次获取统一张图片时,Qt会直接从内存中获取到上一次图片的内存直接返回给我们,因此这里不需要忧郁效率问题。

QPixmap TIGERQTCOMM_EXPORT ImagePath::GetStretchPixmap(const std::string & path, float scale)
{
	std::string tpath = ImagePath::GetPixmapPath(path, (int)(scale + 0.5001));
	float factor = ImagePath::GetStretchFactor(scale);

	QPixmap pixmap(tpath.c_str());
	if (factor != 1.0)
	{
		pixmap = pixmap.scaled(pixmap.size() * factor);
	}

	return pixmap;
}

3、适配饼图

自绘界面时需要我们自己去适配高DPI,主要是绘制所需要的的几何巨细需要调整,说的直白一点儿就是看下图,左侧1080P显示器,右侧4K显示器,而且两个显示器尺寸是一样大的。看左右两侧的矩形区域坐标很清晰的展示出来了,右侧看着一样大的举行是左侧举行的两倍大,而且左上角的坐标也是两倍。

左侧矩形几何巨细是(83, 104, 168, 211),右侧矩形几何巨细是(166, 208, 336, 422) ,根据我们高DPI适配的叫法左侧显示器的缩放比就是1x,右侧是2X

《1080P vs 4K》

前边小节说过了,自绘界面时适配高DPI主要是针对绘制的几何巨细,饼图也不破例,这里我贴一个饼图各模块几何巨细盘算的函数,已经适配过高DPI,方式也很简朴

适配历程主要是用宏来完成的,宏界说如下:#define SCALE_NUMBER(n) ((n) * dpi_scale),dpi_scale为每个高DPI框架下类的成员变量,该变量由框架维护,示意当前窗口需要缩放的系数

空话不多说,如下代码是适配过高DPI后的函数,主要是对一些影响几何位置盘算的参数举行了缩放。

void CPieChart::ConstructCornerLayout(const QSize & size)
{
	int currentR = SCALE_NUMBER(d_ptr->m_MinDiameter);
	int diameter;
	int horiWidth = size.width();
	if (d_ptr->m_bLegendVisible)
	{
		horiWidth -= SCALE_NUMBER(d_ptr->m_LegendWidth * 2);
	}
	int PieHeight;
	if (d_ptr->m_MutiDay.size() >= 1)
	{
		PieHeight = size.height() - SCALE_NUMBER(d_ptr->m_BarHeight) * d_ptr->m_MutiDay.size()
			- SCALE_NUMBER(d_ptr->m_BottomMargin + d_ptr->m_Space + d_ptr->m_BarSpace * (d_ptr->m_MutiDay.size() - 1))
			- SCALE_NUMBER(d_ptr->m_LabelHeight * 2);
	}
	else
	{
		PieHeight = size.height();
	}
	if (horiWidth > PieHeight)
	{
		diameter = PieHeight;
	}
	else
	{
		diameter = horiWidth;
	}

	int x, y;
	int r = diameter - SCALE_NUMBER(d_ptr->m_Minx * 2);
	currentR = r > currentR ? r : currentR;
	if (d_ptr->m_bLegendVisible)
	{
		d_ptr->m_Items.resize(4);

		x = width() / 2 - currentR / 2;
		y = (PieHeight - currentR) / 2;

		d_ptr->m_Items[1].m_LegendRect = QRect(SCALE_NUMBER(d_ptr->m_Minx), SCALE_NUMBER(d_ptr->m_Miny)
			, SCALE_NUMBER(d_ptr->m_LegendWidth), SCALE_NUMBER(30));

		d_ptr->m_Items[0].m_LegendRect = QRect(size.width() - Margin - SCALE_NUMBER(d_ptr->m_LegendWidth)
			, SCALE_NUMBER(d_ptr->m_Miny)
			, SCALE_NUMBER(d_ptr->m_LegendWidth), SCALE_NUMBER(30));

		d_ptr->m_Items[3].m_LegendRect = QRect(size.width() - Margin - SCALE_NUMBER(d_ptr->m_LegendWidth)
			, PieHeight - SCALE_NUMBER(d_ptr->m_Miny + 30)
			, SCALE_NUMBER(d_ptr->m_LegendWidth), SCALE_NUMBER(30));

		d_ptr->m_Items[2].m_LegendRect = QRect(SCALE_NUMBER(d_ptr->m_Minx)
			, PieHeight - SCALE_NUMBER(d_ptr->m_Miny + 30)
			, SCALE_NUMBER(d_ptr->m_LegendWidth), SCALE_NUMBER(30));

		d_ptr->m_Items[0].m_bAlign = false;
		d_ptr->m_Items[3].m_bAlign = false;
	}
	else
	{
		x = SCALE_NUMBER(d_ptr->m_Minx);
		y = SCALE_NUMBER(d_ptr->m_Miny);
	}

	d_ptr->m_PieRect = QRect(x, y, currentR, currentR);
	d_ptr->m_BarsRect = QRect(SCALE_NUMBER(20), 2 * y + currentR + SCALE_NUMBER(d_ptr->m_Space)
		, width() - SCALE_NUMBER(50)
		, size.height() - PieHeight);
}

到目前为止,本篇文章要分享的内容算基本完成了。饼图控件的其他的代码逻辑,包罗绘制逻辑适配高DPI方式都合上述函数类似,人人自行脑补即可。感兴趣的同伙可以到饼图-高DPI下载,CSDN链接中的资源只包罗适配过高DPI的饼图绘制代码,仅供人人参考,并不能通过编译。

四、相关文章

  1. Qt之高DPI显示器(一) - 解决方案整理
  2. Qt之高DPI显示器(二) - 自适配解决方案剖析
  3. Qt之自绘制饼图

值得一看的优异文章:

  1. 财联社-产物展示
  2. 广联达-产物展示
  3. Qt定制控件列表
  4. 牛逼哄哄的Qt库

若是您以为文章不错,不妨给个 打赏,写作不易,谢谢列位的支持。您的支持是我最大的动力,谢谢!!!
欧博会员开户:Windows高DPI系列控件(一) - 饼图 第1张 欧博会员开户:Windows高DPI系列控件(一) - 饼图 第2张



很主要--转载声明

  1. 本站文章无稀奇说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords

  2. 如要转载,请原文转载,如在转载时修改本文,请事先见告,谢绝在转载时通过修改本文到达有利于转载者的目的。

,

平心在线官网

欢迎进入平心在线官网(原诚信在线、阳光在线)。平心在线官网www.px111.net开放平心在线会员登录网址、平心在线代理后台网址、平心在线APP下载、平心在线电脑客户端下载、平心在线企业邮局等业务。

Allbet欧博官网声明:该文看法仅代表作者自己,与本平台无关。转载请注明:欧博会员开户:Windows高DPI系列控件(一) - 饼图

网友评论

  • (*)

最新评论

站点信息

  • 文章总数:716
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1286
  • 评论总数:350
  • 浏览总数:21364