Windows high DPI series controls (1) - pie chart


Original link: Windos high DPI series controls (1) - pie chart

1. Get drunk

In the blink of an eye, half of 2020 has passed. Looking back on my work and life in the recent period, I always feel that I should write something!

So, I have been thinking about it recently when I have free time, thinking about what useful things I can write! I just wrote a few articles about high DPI before. I don’t know why, and the reading volume is not very high, so I plan to introduce a series of control use cases with high DPI as the index, including Qt’s own controls, simple charts and some Complicated diagrams.

  1. Not to mention the controls that come with Qt, the high DPI framework can almost perfectly adapt
  2. Simple charts mainly include histograms, line charts, pie charts, etc.
  3. Complex charts are mainly to customize some stock-related charts, such as time-sharing charts, k-line charts, etc.

For popular software, friendly support for 4k displays is really necessary. A good popular desktop software needs to adapt to various operating systems, from XP that is about to be forgotten by people to Win10, which has a relatively high market share. If you want to have a good user experience, high DPI must be well adapted. , here the author has prepared a series of high-DPI control adaptation articles to share with you, mainly sorting out various controls encountered in my work, adapting them to the developed high-DPI framework, and making a demonstration demo, which is provided to Students in need, in addition to sorting out existing controls, will develop some more meaningful new controls, such as time-sharing charts and k-lines in stocks.

Purpose:

  1. Promote my own solution to adapt to high DPI, for everyone to discuss, whether there is better room for optimization
  2. Organize stock-related controls, adapt them to my high DPI framework, and provide references for students in need
  3. Organize my own knowledge base in stages, so that scattered knowledge points can be brought together

2. Effect display

As shown in the figure below, adapt to high DPI interaction effects.

The physical size of the display on the left and right sides is the same, that is, the floor area is the same, the difference is that the left side is a 1080p display, and the right side is a 4k display

Because of the video recording, there may be visual errors. In reality, the left and right windows give people the same visual perception.

"Switching Displays Back and forth"


"Pie Chart Support Operation"

3. High DPI adaptation

The idea of ​​high DPI adaptation has been systematically analyzed before. For details, please refer to the two articles of Qt High DPI Display (1) - Solution Organization and Qt High DPI Display (2) - Adaptive Solution Analysis .

In addition to the above two articles, there was another article to be written in the previous plan. Later, I was too busy to finish writing. The third article mainly wants to talk about how to optimize the existing framework and make DPI adapt to the efficiency If it becomes higher, there will be a chance to make up for it later.

The promissory note article is the beginning of a series of articles on adapting to high DPI practice. The pie chart control has been shared a long time ago. For details, refer to Qt’s self-drawing pie chart . How to draw a pie chart will not be described here. The core of this article is mainly to adapt the high DPI display of the pie chart. The details of the adaptation will be described later, and more and richer components will be connected in succession later.

Let's first take you to review what we have done to adapt to high DPI, and finally look at how the pie chart is adapted to high DPI.

1. High DPI frame operation

Students who have read the previous two articles should know that we adapt to high DPI mainly from two aspects, namely the physical size of the form and the font

physical size

The physical size is literally the size of the software, but the physical size here also includes the size of the sub-window, which means that the gap between the sub-windows is also adapted to the physical size.

In order to let the development students use it without perception, we added the same number of interface classes that may be used as our own basic classes, and rewritten the size-related functions in the interface class, so that everyone can use the interface class Sometimes only the class name is changed, and the interface usage is still the same as before.

The size function is rewritten. If we also know the DPI of the current display, the zoom interface is very simple! The size of the current development settings multiplied by the factor to be zoomed is the final size to be displayed. The framework only needs to set the final size to be displayed to the Qt interface, which is the parent class interface of the current class, so that our software interface is realized. enlarge. Is this the end? Think about it carefully, when developers use these interfaces, they set the size under 96DPI. If the window is moved to another monitor with a different DPI, do we have to call all the set interfaces again? If the number is small, it’s okay, but a complex software such as set interface will make you outrageous. If you let the development classmates call it once, I guess they will kill you. In addition to the need to call, the order of calling is also very important. Imagine such a scenario, if there are many forms that need to be scaled, do you want the form to suddenly become larger locally without the jump of the exchange rate? The answer is of course no.

In order to make the form scale regularly, we need to control the order of scaling. Here we need to continue to rewrite some key methods. We rewritten the size-related functions when we rewrote the class before. This time we also need The layout-related functions are also rewritten, so that we record their relationship when the interface is laid out, and when there is a DPI change, we call each interface that needs to be scaled layer by layer according to the previously maintained layout relationship .

interface layout

Here is a popular knowledge point. The software interface we usually see is flat, which is a two-dimensional concept. However, during the development process of the software interface, the layout relationship of the interface is actually a tree, such as the following figure. Interface, interface A includes interface B and interface C, and interface B includes two interfaces D, so when we construct two interfaces A, in fact, all interfaces are constructed twice, and interface D is constructed Four.

font size

The high DPI framework we adapt, except for self-emoji, other situations do not need to pay attention to how the font changes. These font adaptations are all completed in our high DPI adaptation framework. Here is a brief description of the font adaptation High DPI way.

During the running of the high DPI framework, the qss files under 1x, 2x and 3x are actively maintained. If it is detected that the Qss file required by the program is not in these three configurations, the framework will dynamically use the qss file closest to the current zoom ratio. The file generates a temporary qss file. For example, the current zoom ratio is 1.8x, then the program will generate a qss file suitable for the 1.8x zoom ratio according to the 2xqss file. First, the image is compressed and displayed, and the font size will be multiplied by 1.8 and then divided by 2 Converting to a font size with a zoom ratio of 1.8x may cause rounding, but there is basically no problem with the commonly used integer multiple zoom ratio of 0.5, because the font size is generally an integer multiple of 2.

2. Adapt to high DPI

At the beginning of the design of the high-DPI framework, we wanted to let developers worry as little as possible about DPI, but the actual situation is that there are still a few situations that need to be adapted by ourselves, such as the self-destruct interface. At this time, we need to do it ourselves. Obtain high DPI related information and draw reasonably

draw text

When drawing text, we need to obtain the current zoom factor, and scale the drawing parameters appropriately. For example, when we draw a 12px font, if it is under a 4k display, our dpi may be 192, then the zoom factor is 2x, when drawing text, you need to draw a 24px font

scaling factor = current monitor DPI / 96.0

Sometimes when drawing text, there may be restrictions on the area where the text is located. Under 96DPI, we don’t need to worry about whether there will be problems in the area, but if the display DPI is greater than 96, we need to adapt the area where the text is drawn, otherwise it may be damaged. results that you do not expect. For example, we need to draw a piece of text in a square box with a border of 100px at the coordinates of 10 and 10. At 96DPI, we may just be able to draw the text. If it is at 192DPI, we double the font size. If we draw The area is still a 100px square, so the text may not even be drawn in half. What's the problem? Obviously, the font becomes larger, and our drawing area must also be enlarged accordingly. Let's try a 200px square, is it possible? The answer is yes.

draw pictures

It is often necessary to draw pictures when self-painting the interface. Let's analyze in detail how to draw pictures under any DPI!

The first is to obtain the image path under the 1x zoom ratio, and then we convert it into the image path we need under the current display through a conversion function, and scale the image to achieve the best display effect.

As shown in the following code, it is a packaged function, which mainly completes the acquisition of the picture we are going to draw according to the 1x picture path, and returns us the memory address. It needs to be added here that the QPixmap in Qt has a caching mechanism. When we get the same picture for the second time, Qt will directly get the memory of the last picture from the memory and return it to us directly, so there is no need here worry about efficiency.

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. Adapt pie chart

We need to adapt to the high DPI when drawing the interface, mainly because the geometric size required for drawing needs to be adjusted. To put it bluntly, look at the picture below, the left 1080P monitor, the right 4K monitor, and two monitors The size is the same size. Look at the coordinates of the rectangular areas on the left and right sides are clearly displayed, the one on the right that looks the same size is twice as large as the one on the left, and the coordinates of the upper left corner are also twice as large.

The geometric size of the left rectangle is (83, 104, 168, 211), and the geometric size of the right rectangle is (166, 208, 336, 422). According to our high DPI adaptation, the scaling ratio of the left display is 1x. Right side is 2X

《1080P vs 4K》

As mentioned in the previous section, the adaptation to high DPI in the self-drawing interface is mainly for the geometric size of the drawing, and the pie chart is no exception. Here I post a function for calculating the geometric size of each module in the pie chart, which has been adapted to a high DPI. The method also very simple

The adaptation process is mainly done with macros, which are defined as follows: #define SCALE_NUMBER(n) ((n) * dpi_scale), dpi_scale is a member variable of each high DPI frame class, which is maintained by the frame, indicating the current The factor by which the window needs to be scaled

Not much nonsense, the following code is a function after adapting to a high DPI, mainly to scale some parameters that affect the geometric position calculation.

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

So far, the content to be shared in this article is basically completed. The other code logic of the pie chart control, including the way of drawing logic to adapt to high DPI, is similar to the above function, and you can make up your own brain. Interested friends can go to Pie Chart-High DPI to download. The resources in the CSDN link only contain the pie chart drawing code adapted to the high DPI, which is for your reference only and cannot be compiled.

4. Related Articles

  1. Qt's high DPI display (1) - solution arrangement
  2. Qt's High DPI Display (2) - Adaptive Solution Analysis
  3. Qt's self-drawing pie chart

Excellent articles worth a look:

  1. Financial Associated Press-Products
  2. Glodon-Products
  3. Qt custom control list
  4. Awesome Qt library

If you think the article is good, you may wish to give a reward, writing is not easy, thank you for your support. Your support is my greatest motivation, thank you! ! !




It's Important – Reprint Statement

  1. The articles on this site have no special instructions, all are original and copyrighted, please use the link when reprinting, and give the source of the original text. At the same time, write the original author: morning ten night eight or Twowords

  2. If you want to reprint, please reprint the original text. If you modify this article when reprinting, please inform in advance. It is forbidden to modify this article to benefit the reprinter when reprinting.


Guess you like

Origin blog.csdn.net/qq_30392343/article/details/107109787