QT自适应窗口的一种实现

前言:

QT自身的自适应Layout运用起来,比较复杂,并且需要比较多的时间来调配置各种参数,特别是在原有界面上增加/减少一些控件时的修改,很多时候让人抓狂。本文介绍了一种比较方便的方法来实现这适应窗口大小。

这种方式简单来说就是在Widget创建时,把Widget的初始大小以及其中的控件及其初始大小记录下来,然后在Widget中重载resizeEvent,在此实现中根据Widget的当前大小与初始大小的比例,动态把其中的各控件进行放缩。

为了更方便的实现,可以把这个放缩功能定义在一个基类中,代码如下:

1. UsefulFunsEditor中定义一些公共性质的函数


//UsefulFunsEditor.h

#pragma once

#include <vector>

void NoteWidgetGeometry(std::vector<std::pair<QWidget*, QRect>>& tMap, QWidget* widget);
void ResizeWidget( QWidget* widget, const QRect& srcRect, float scale_x, float scale_y );
void ResizeWidgets( const std::vector<std::pair<QWidget*, QRect>>& tMap, const QSize& parentSrcSize, const QSize& parentDstSize )


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//UsefulFunsEditor.cpp

#include <QWidget>

//把控件保存入表中
void NoteWidgetGeometry(std::vector<std::pair<QWidget*, QRect>>& tMap, QWidget* widget)
{
	if( widget == nullptr )
	{
		return;
	}
	std::pair<QWidget*, QRect> tPair;
	tPair.first = widget;
	tPair.second = widget->geometry();
	tMap.push_back(tPair);
}

//控件放缩
void ResizeWidget( QWidget* widget, const QRect& srcRect, float scale_x, float scale_y )
{
	QRect tRect = srcRect;
	int top = tRect.top();
	int bottom = tRect.bottom();
	int left = tRect.left();
	int right= tRect.right();
	top *= scale_y;
	bottom *= scale_y;
	left *= scale_x;
	right *= scale_x;
	tRect.setRect(left, top, right-left+1, bottom-top+1);
	widget->setGeometry(tRect);
	//widget->setAutoFillBackground()
	widget->setFixedSize(right-left+1, bottom-top+1);
}

//表中所有控件放缩
void ResizeWidgets( const std::vector<std::pair<QWidget*, QRect>>& tMap, const QSize& parentSrcSize, const QSize& parentDstSize )
{
	if( tMap.empty() )
	{
		return;
	}
	if( parentSrcSize.width() <= 0 || parentSrcSize.height() <= 0 )
	{
		return;
	}

	float scale_x = (float)(parentDstSize.width())/parentSrcSize.width();
	float scale_y = (float)(parentDstSize.height())/parentSrcSize.height();
	auto itEnd = tMap.end();
	QRect rect;
	QRect srcRect;
	QString name;
	for( auto it = tMap.begin(); it != itEnd; ++it )
	{
		const std::pair<QWidget*, QRect>& tPair = *it;
		QWidget* widget = tPair.first;

		name = widget->objectName();

		srcRect = widget->geometry();

		ResizeWidget( tPair.first, tPair.second, scale_x, scale_y );

		rect = widget->geometry();
	}
}

用于缩放的Widget基类

头文件

/*
===================================================================
WidgetChildClean.h

纯静版,没有相关Parent设置

2022-10-22 edit by lgy
===================================================================
*/

#pragma once

#include <vector>

#include "QWidget"

class WidgetChildClean :public QWidget
{
public:
	WidgetChildClean(QWidget *parent = 0, Qt::WFlags flags = 0);
	virtual ~WidgetChildClean();

	virtual void Update(int delta_ms);
	virtual void Active();
protected:

	virtual void InitWidgetGeometry();
	virtual void resizeEvent(QResizeEvent * event);
	
protected:
	QSize mBaseSrcSize;
	std::vector<std::pair<QWidget*, QRect> > mChildrenRectsMap;
};

实现文件


#include "QResizeEvent"

#include "WidgetChildClean.h"

#include "UsefulFunsEditor.h"

WidgetChildClean::WidgetChildClean(QWidget *parent, Qt::WFlags flags):QWidget(parent, flags)
{

}
WidgetChildClean::~WidgetChildClean()
{

}

void WidgetChildClean::Update(int delta_ms)
{

}
void WidgetChildClean::Active()
{
	show();
}
void WidgetChildClean::InitWidgetGeometry()
{
	mBaseSrcSize = size();
}
void WidgetChildClean::resizeEvent(QResizeEvent * event)
{
	QSize curSize = event->size();
	ResizeWidgets(mChildrenRectsMap, mBaseSrcSize, curSize);
}

注意:resizeEvent会在每次变化大小时会有调用,我们重点是在新创建的Widget类时,把WidgetChildClean当作一个基类。

实现的例子,注:例子是直接从项目中拿出来的,有大量与项目相关的实现,读者需要只要把相关的地方修改为自己的代码即可,我懒得重新写一个可运行的例子了:

/*
===================================================================
WidgetBGRecordTable.h



2022-10-22 edit by lgy
===================================================================
*/

#pragma once

#include "ui_uiBGRecordTable.h"
#include "WidgetChildClean.h"
#include "MovieRecordDB.h"

class CControlClient;
class WidgetBGRecordTable : public WidgetChildClean
{
	Q_OBJECT
public:
	WidgetBGRecordTable(QWidget *parent = 0, Qt::WFlags flags = 0);
	virtual ~WidgetBGRecordTable();
	
	virtual void Update(int delta_ms);
	virtual void Active();

	void EmptyAll();
	void ClearTree();
	void FreshRecordHeader(const std::map<int, std::string>& idNameList);
	void ShowRecordTree(const DateMovieRecordMap& records);	
protected:

	virtual void InitWidgetGeometry();
private:

	

private:
	Ui::Form_BGRecordTable ui;

	std::map<int, std::string> mIDNameMap;
};


#include "WidgetBGRecordTable.h"
#include "UsefulFunsEditor.h"

WidgetBGRecordTable::WidgetBGRecordTable(QWidget *parent, Qt::WFlags flags):WidgetChildClean(parent, flags)
{
	ui.setupUi(this);
	InitWidgetGeometry();
}
WidgetBGRecordTable::~WidgetBGRecordTable()
{
	
}

void WidgetBGRecordTable::Update(int delta_ms)
{

}
void WidgetBGRecordTable::Active()
{
	
}

void WidgetBGRecordTable::InitWidgetGeometry()
{
	mBaseSrcSize = size();
	WIDGET_GEOMETRY(treeWidget_Record);
}


void WidgetBGRecordTable::EmptyAll()
{
	ui.treeWidget_Record->clear();
	QTreeWidgetItem* item = ui.treeWidget_Record->headerItem();
	int count = item->columnCount();
	for( int i = 0; i < count; ++i )
	{
		item->setText(i, "");
	}
}

void WidgetBGRecordTable::ClearTree()
{
	ui.treeWidget_Record->clear();
}

void WidgetBGRecordTable::FreshRecordHeader(const std::map<int, std::string>& idNameList)
{
	mIDNameMap = idNameList;
	QTreeWidgetItem* head = ui.treeWidget_Record->headerItem();
	int count = head->columnCount();
	for( int i = 0; i < count; ++i )
	{
		head->setText(i, "");
	}

	head->setText(0, QString::fromWCharArray(L"时间"));

	int i=0;
	for( auto it = idNameList.begin(); it!=idNameList.end(); it++ )
	{
		i=i+1;
		QString name = AsciiStrToQStr(it->second);
		head->setText(i, name);
	}
}

void WidgetBGRecordTable::ShowRecordTree(const DateMovieRecordMap& records)
{
	ui.treeWidget_Record->clear();
	if( records.empty() )
	{
		return;
	}

	for( auto rit = records.rbegin(); rit != records.rend(); ++rit )
	{
		QString qnum;
		qnum.setNum(rit->first);
		QStringList qstrList;
		qstrList.append(qnum);
		for( auto it = rit->second.begin(); it != rit->second.end(); it++ )
		{
			int id = it->first;
			RecordDef d = it->second;
			if( mIDNameMap.count(id)== 0 )
			{
				qstrList.append("0");
			}
			else
			{
				QString qstr_play;
				qstr_play.setNum(d.play_c);
				qstrList.append(qstr_play);

			}
		}
		QTreeWidgetItem* item = new QTreeWidgetItem(ui.treeWidget_Record, qstrList);
		ui.treeWidget_Record->addTopLevelItem(item);
	}
}

初始图:

 放缩后的图

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值