How does Qt custom Widget achieve mutual exclusion effect

cutting edge

What is a custom Widget to achieve mutual exclusion?

When using Qt to make a function with a more beautiful interface, you may encounter this kind of problem: multiple controls are mutually exclusive, similar to QRadiButton controls, but not pure QRadioButton controls. Mutually exclusive may be a window, or It could be several buttons, etc.

Here I just listed a simple example of mutual exclusion. Although it is simple, it contains various pitfalls. If necessary, you can take small notes, especially for Qt novices, it is still very necessary.

It can be seen from the effect diagram that 3 custom widgets have been created. When one of them is clicked, the background color and text color of the other two will change and be in the selected state.

Next, the functions displayed in the renderings will be explained one by one, including knowledge points and pitfall records.

The benefits of this article, free to receive Qt development learning materials package, technical video, including (C++ language foundation, C++ design pattern, introduction to Qt programming, QT signal and slot mechanism, QT interface development-image drawing, QT network, QT database programming, QT project actual combat, QSS, OpenCV, Quick module, interview questions, etc.) ↓↓↓↓↓↓See below↓↓Click on the bottom of the article to receive the fee↓↓

function realization

In the process of implementing a custom mutual exclusion widget, I encountered the following knowledge points and problems. Let’s see if there are any functions you have encountered or just needed!

knowledge points

1: The four-state function of the Widget analog button, including: normal, pressed, focused, disabled

2: Background color setting and text content style setting of Widget custom class

3: How to make multiple widgets achieve mutual exclusion effect

question

1: Why doesn't the custom Widget background color take effect?

Let’s talk about this simple function based on the above knowledge points and problems!

Explain knowledge point 1

Using the four-state function of the Widget to simulate the button requires the use of the Widget's own messages: mouse down, mouse in, and mouse out.

virtual void mousePressEvent(QMouseEvent *event); //鼠标按下响应消息
virtual void enterEvent(QEvent *event); //鼠标进入响应消息
virtual void leaveEvent(QEvent *event); //鼠标离开响应消息

Does anyone ask why there is no mouseMoveEvent message?

Answer: The mouse cannot be triggered by directly using the mouseMoveEvent message in Qt. SetMouseTracking(true) must be set to make the mouse tracking event valid in the current window.

Whether this function needs to be set according to the specific situation of use. In the current small demo, only image conversion is done, there is no need to consume resources in mouseMove all the time.

(Digression: The mousemove event under the MFC framework is directly available without special settings)

After the mouse enters the widget, it can be marked as the mouse is always active in the widget, unless a leaveEvent message is triggered.

Mouse down response message

void QCustomWidget::mousePressEvent(QMouseEvent *event)
{
	this->SetWidgetStyle(Style_Down);
	QWidget::mousePressEvent(event);
}

The currently adopted enumeration type: mouse press response.

The mouse enters the widget response message

void QCustomWidget::enterEvent(QEvent *event)
{
	this->SetWidgetStyle(Style_Focus);
	QWidget::enterEvent(event);
}

The currently adopted enumeration type: mouse focus state, use enter message instead of mousemove message.

If you log, you will find that the trigger function will only go once when the mouse enters, and it will not be triggered when the mouse continues to move inside the widget, which greatly reduces message processing.

The mouse leaves the widget response message

void QCustomWidget::leaveEvent(QEvent *event)
{
	this->SetWidgetStyle(Style_Normal);
	QWidget::leaveEvent(event);
}

The currently adopted enumeration type: mouse leave state.

I just showed the simplest leave setting. One thing to consider is that if the current widget is in the pressed state and the mouse leaves at this moment, how should it be displayed?

Do you still want to show the normal style?

The answer is definitely NO!

Although the mouse has been moved away, the selected state has changed from normal to pressed state. In the program, we need to use a bool value variable to record whether the current widget has been selected. If it has been selected, it needs to be changed to the selected state when the mouse leaves

The modification looks like this:

if (m_bClickedState == true)
{
	this->SetWidgetStyle(Style_Down);
}
else
	this->SetWidgetStyle(Style_Normal);

Explain knowledge point 2

In the program, the state of the simulation is represented by an enumeration type.

type

illustrate

Style_Normal

The initial state of the mouse without any operation

Style_Down

Mouse pressed in wiget

Style_Focus

The operation state when the mouse moves in the widget

Style_Disable

The current widget is in progress

The same content is displayed in each widget: number, text

Because it is just a display function, all QLabel controls are used

QLabel *m_labNumber; //number class pointer

QLabel *m_LabContent; //Content class pointer

The corresponding actual processing

void QCustomWidget::SetWidgetStyle(ENUM_WidgetStyle enumStyle)
{
	//TODO:设置widget风格
	QString qsStyle = "", gStyleNumberNormal = "", gStyleContentNormal = "";
	switch (enumStyle)
	{
	case Style_Normal: //常态显示
	{
		//设置:背景
		qsStyle = "QWidget{background-color:#FFD700}";
		//设置:编号风格
		gStyleNumberNormal = "QLabel{color:#666666; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
		//设置:内容风格
		gStyleContentNormal = "QLabel{color:#666666; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
	}
		break;
	case Style_Down: //按下
	{
		//设置:背景
		qsStyle = "QWidget{background-color:#FFB6C1}";
		//设置:编号风格
		gStyleNumberNormal = "QLabel{color:#0000FF; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
		//设置:内容风格
		gStyleContentNormal = "QLabel{color:#00FFFF; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
	}
		break;
	case Style_Focus: //聚焦
	{
		//设置:背景
		qsStyle = "QWidget{background-color:#FFF0F5}";
		//设置:编号风格
		gStyleNumberNormal = "QLabel{color:#98FB98; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
		//设置:内容风格
		gStyleContentNormal = "QLabel{color:#98FB98; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
	}
		break;
	case Style_Disable: //禁用
	{
		//设置:背景
		qsStyle = "QWidget{background-color:#DCDCDC}";
		//设置:编号风格
		gStyleNumberNormal = "QLabel{color:#696969; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
		//设置:内容风格
		gStyleContentNormal = "QLabel{color:#696969; font-family:Microsoft YaHei UI; font-size:14px;} QLabel{background-color: transparent}";
	}
		break;
	default:
		break;
	}
	this->setStyleSheet(qsStyle);
	m_labNumber->setStyleSheet(gStyleNumberNormal);
	m_labContent->setStyleSheet(gStyleContentNormal);
}

The background style corresponding to different types is also different. You can bring in the code and run it to see the effect. Is it consistent with the effect I showed?

Ha ha! If you try it, you will find that it looks like this:

Why can only text be displayed, what about my background? Where did you go? Didn't I already set it up?

Many Qt novices will encounter such problems here, so they open various search modes, try various methods, and sometimes just change and change, and ignore this problem.

When we create a custom widget, the general method uses the new instance method. In the process of new, in order to manage the hierarchical relationship and the parent-child relationship is clear, this will be passed in as the parent pointer of the newly created window.

Once we pass in the this pointer and do not do any processing in the custom Widget, this will happen at this time.

Subclasses inherit the style of the parent window.

Generally, when encountering this situation, there are two ways to deal with it: rewrite the paintEvent function of the current window, and set the style not to follow the parent window

For convenience, the second method will be used when the background image drawn by the window is not complicated:

this->setAttribute(Qt::WA_StyledBackground);

After setting the above code in the constructor of the current custom widget class, the previous problem of setting the background style but not seeing it will be solved.

Explain knowledge point 3

How to achieve mutual exclusion between multiple widgets?

Anyone who has used the QRadioButton control knows that the control only needs a simple setting function to set mutual exclusion.

For our custom widgets, there is no such function. The mutual exclusion effect can only be set manually with code and the corresponding display effect is replaced according to the selected and unselected states.

Assume that the custom Widget of "Content 1" is currently selected. At this time, a message needs to be triggered in the mouse press response in the Widget to notify the outside world that the current custom Widget has been pressed, and special processing is required.

void QCustomWidget::mousePressEvent(QMouseEvent *event)
{
	this->SetWidgetStyle(Style_Down);
	emit Msg_SendClicked();
	QWidget::mousePressEvent(event);
}

Do special processing in response to the corresponding slot function in the parent class that calls the custom Widget.

At this point, it is easy to realize the mutual exclusion effect of custom Widget.

The implementation of mutual exclusion operations is very simple, and the most important thing to master is how to set the background of the widget.

In many cases, when there are too many nested levels between child windows and parent windows, this kind of problem is most likely to occur, because every time we create a new widget object, the best way is not to follow the style of the parent window every time.

The benefits of this article, free to receive Qt development learning materials package, technical video, including (C++ language foundation, C++ design pattern, introduction to Qt programming, QT signal and slot mechanism, QT interface development-image drawing, QT network, QT database programming, QT project actual combat, QSS, OpenCV, Quick module, interview questions, etc.) ↓↓↓↓↓↓See below↓↓Click on the bottom of the article to receive the fee↓↓

Guess you like

Origin blog.csdn.net/m0_60259116/article/details/130584962