Qt之应用程序分辨率自适应(字体、控件跟随变化)(转载)

在Qt里,每台电脑的分辨率不一样,比如说你的分辨率是1920*1080,那么到800*480就会有控件显示不完全,所以我们需要控件跟随变化。

我使用的方法较菜,Qt用的不熟

通过layout布局的方式对窗口的分辨率自适应,即将需要将自适应的控件添加进layout布局中,当layout的父对象的尺寸变化时,layout会根据父对象相应的变化宽、高比例对布局中的控件进行缩放,以此来实现相应控件的分辨率自适应。 

但是在QtCreator Designer中添加的layout存在一个问题,如下图在Designer中添加一个Vertical Layout,layout中添加两个PushButton,当运行程序后,调整程序大小,中间的PushButton并不会随着窗口大小而进行缩放。

这是因为在resize事件中,并没有对ui->verticalLayoutWidget进行拉伸,所以我们要重写resizeEvent的函数,

void MainWindow::resizeEvent(QResizeEvent *event)
{
    Q_UNUSED(event);
    QWidget * resizeWidget=ui->verticalLayoutWidget;
    QRect resizeRect=resizeWidget->rect();
    static float baseWidth=400;
    static float baseHeight=300;
    static float widgetWidth=resizeRect.width();
    static float widgetHeight=resizeRect.height();
    static float widgetX=ui->verticalLayoutWidget->geometry().x();
    static float widgetY=ui->verticalLayoutWidget->geometry().y();
    float horRatio=this->rect().width()/baseWidth;
    float verRatio=this->rect().height()/baseHeight;
    //dajust the position of verticalLayoutWidget
    resizeRect.setX(widgetX*horRatio);
    resizeRect.setY(widgetY*verRatio);

    //resize the verticalLayoutWidget
    resizeRect.setWidth(widgetWidth*horRatio);
    resizeRect.setHeight(widgetHeight*verRatio);
    //set Geometry
    resizeWidget->setGeometry(resizeRect);
}

利用layout对控件进行布局缩放使用简单,且无需关注内部细节,但是利用layout进行布局时,控件的位置和大小受布局的约束无法实现大小和位置的精确控制,对于界面又复杂布局要求时layout并不能满足使用要求,对于这部分控件只能自定义控件的缩放,在程序窗口缩放是实现分辨率的自适应

具体的缩放规则与前面类似,在程序窗口尺寸变化时,即首先获得程序窗口的缩放比例horRatio,verRatio放,然后对各个控件的X,Y以及宽度width和高度height进行相应比例的缩放即可,但是对于每个单独的控件都进行自定义缩放,实现起来较复杂,因此需要采用通用的方法来对各个控件进行缩放。 
    由于大部分的可以控件都是继承于QWidget的,因此查找到程序中所有的QWidget对象,然后在实现相应的变换即可。Qt提供了findChildren方法可以查找特定类型的子对象,因此可以利用这个方法来实现查找QWidget的子对象,并进行自定义缩放: 
首先定义结构体来存储控件的基本尺寸及位置

struct AutoResizeOriginalData
{
    QRect data_rect;
    QFont data_font;
};
//define a map to store the resize items
QMap<QWidget*,AutoResizeOriginalData> m_resizeMap;

然后在查找窗口中全部的QWidget对象,这个需要查找的对象需要自己控制,博客中显示不完全,并记录其初始位置

m_autoResizeHandler->setAutoResizeFlag(
            AutoResize::INCLUDE_BUTTON|AutoResize::INCLUDE_COMBOBOX|
            AutoResize::INCLUDE_EDITOR|AutoResize::INCLUDE_LABEL
            );
QWidget *item=NULL;
AutoResizeOriginalData resizeData;
QRect tmp;
QList<QLabel*> _labelList=m_autoResizeObj->findChildren<QLabel *>();
for(auto it=_labelList.begin();it!=_labelList.end();it++)
{
    item=*it;
    tmp=item->geometry();
    tmp.setX(item->x());
    tmp.setY(item->y());
    tmp.setWidth(abs(tmp.width()));
    tmp.setHeight(abs(tmp.height()));
    resizeData.data_rect=tmp;
    resizeData.data_font=item->font();
    m_resizeMap[item]=resizeData;
}
QList<QAbstractButton*> _buttonList=m_autoResizeObj->findChildren<QAbstractButton*>();
for(auto it=_buttonList.begin();it!=_buttonList.end();it++)
{
	item=*it;
	tmp=item->geometry();
	tmp.setX(item->x());
	tmp.setY(item->y());
	tmp.setWidth(abs(tmp.width()));
	tmp.setHeight(abs(tmp.height()));
	resizeData.data_rect=tmp;
	resizeData.data_font=item->font();
	m_resizeMap[item]=resizeData;
}

再重载窗口对象的resizeEvent函数,对各个控件进行自适应控制

m_horRatio=this->rect().width()/m_baseWidth;
m_verRatio=this->rect().height()/m_baseHeight;
QMapIterator<QWidget*, AutoResizeOriginalData> _itarator(m_resizeMap);
        while(_itarator.hasNext())
        {
            _itarator.next();
            QWidget* _item=_itarator.key();
            QRect tmp=_itarator.value().data_rect;
            tmp.setWidth(tmp.width()*m_horRatio);
            tmp.setHeight(tmp.height()*m_verRatio);
            QRect after=QRect(tmp.x()*m_horRatio,tmp.y()*m_verRatio,tmp.width(),tmp.height());    
_item->setGeometry(after);
        }

 注意:如果界面中有一部分控件包含在layout中,在查找QWidget对象时会把这一部分控件也包含在其中,这样的话在进行尺寸缩放时回合layout相互影响,导致界面发成错位,应去除这些控件,交由layout来控制其缩放,具体操作如下: 
定义一个函数用于移除其所有子对象

void AutoResize::ignoreAllChiledren(QObject* obj)
{
    QList<QObject*> children=obj->children();
    for(auto it=children.begin();it!=children.end();it++)
    {
        QWidget *item=qobject_cast<QWidget*>(*it);
        m_ignoreItem.push_back(item);
        AutoResizeOriginalData resizeData;
        if(!item)
            continue;
        m_resizeMap.remove(item);
    }
}
查找所有的layout:
QString desName="widget";
QList<QLayout*> layoutList=m_autoResizeObj->findChildren<QLayout*>();
for(auto it=layoutList.begin();it!=layoutList.end();it++)
{
    QString objName=(*it)->parent()->objectName();
    if(objName.contains(desName))
    {
        //need to find the items in layout by the parent widget of layout                
        QWidget* layoutWidget=qobject_cast<QWidget*>((*it)->parent());
        ignoreAllChiledren(layoutWidget);
    }
}

 字体缩放

Qt中的字体Qfont定义字体大小是有两种方式,一种是PixelSize,另一种是PointSize,PixelSize实际上是以像素为单位,即PixelSize的大小即为实际的像素大小。PointSize的单位不是像素,它是以字体在屏幕实际显示的大小为单位的,它和屏幕的分辨率以及屏幕的真实尺寸相关,即它的单位即为屏幕上显示的字体大小。 
    对于相同尺寸不同分辨率的屏幕,通过设置PointSize大小的字体,不同分辨率的屏幕上显示的实际字体的大小是一样的,通过设置PointSize的字体来说,字体大小是随着屏幕大小以及分辨率自适应的,因此无须处理字体的缩放;但是对于设置PixelSize大小的字体来说,由于所占分辨率大小固定,因此在相同尺寸上更高分辨率的屏幕上,由于其单位长度内的像素点数更多,即像素密度更大,因此对于更好分辨率的屏幕来说,字体会看起来小一些,要处理这种情况,一种办法就是所有字体都用PointSize来表示大小,但对于已经采用PixelSize的字体来说,就要对其进行控制缩放。 
首先创建用于缩放字体的函数

void AutoResize::fontAutoResize(QWidget *obj,int fontSize) 
{ 
if(fontSize<=0) 
return; 
bool hasTextStyle=false; 
fontSize*=m_fontRatio; 
QFont changedFont; 
changedFont=obj->font(); 
changedFont.setPixelSize(fontSize); 
obj->setFont(changedFont); 
}
由于控件都继承与QWidget,且QWidget具有字体属性,因此可以通过QWidget来查找自控件,并记录相应的字体信息
QWidget *item=NULL;
AutoResizeOriginalData resizeData;
QRect tmp;
QList<QLabel*> _labelList=m_autoResizeObj->findChildren<QLabel *>();
for(auto it=_labelList.begin();it!=_labelList.end();it++)
{
    item=*it;
    tmp=item->geometry();
    tmp.setX(item->x());
    tmp.setY(item->y());
    tmp.setWidth(abs(tmp.width()));
    tmp.setHeight(abs(tmp.height()));
    resizeData.data_rect=tmp;
    resizeData.data_font=item->font();
    m_resizeMap[item]=resizeData;
    //the pixelsize !=-1 when set font size by pixelsize
    if(resizeData.pixelSize()!=-1)
    {
        m_fontMap[item]=resizeData;
    }
}
//计算字体缩放比例
void AutoResize::calculateResizeRatio()
{
    m_horRatio=m_autoResizeObj->width()/m_baseWidth;
    m_verRatio=m_autoResizeObj->height()/m_baseHeight;
    m_fontRatio=m_horRatio<m_verRatio?m_horRatio:m_verRatio;
}
//重载resizeEvent函数,缩放字体

void AutoResize::doAutoResize()
{
    calculateResizeRatio();
    if(m_autoResize)
    {
        QMapIterator<QWidget*,AutoResizeOriginalData> _fontIt(m_fontMap);
        while(_fontIt.hasNext())
        {
            _fontIt.next();
            QWidget* _item=_fontIt.key();
              changedFont=_fontIt.value().data_font;
              fontAutoResize(_item,changedFont.pointSize());
        }
    }
}

到这里就完成了
原文:https://blog.csdn.net/matengxiao/article/details/52853332 
他那里也有代码下载

  • 9
    点赞
  • 80
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值