【QT常用技术讲解】控件随窗口自适应变化大小或者移动位置
前言
展示内容比较多的时候,需要拉伸窗口,控件自适应主窗体的变化是有必要的。
效果图
功能讲解
本文分享控件自适应窗口变化的三种情况:原宽高不变,移动X轴坐标、原宽高不变,移动Y轴坐标、X、Y坐标不变,宽度和高度自适应。
获取窗口变化后的响应
窗口变化后的响应,需要重载resizeEvent,需要在头文件中加上以下声明:
protected:void resizeEvent(QResizeEvent *event) override;
自适应变化的要点是,宽和高变化了多少,可在初始化的时候先获取窗口的原始宽(m_width)和原始高(m_height),当窗口变化之后,在resizeEvent中获取到当前的宽和高,减去原始宽、高即为变化的宽和高值,代码如下:
//mainwindow.h
class MainWindow : public QMainWindow
{
private:int m_width;int m_height;
};//mainwindow.cpp
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{m_width = this->width(); // 获取宽度m_height = this->height(); // 获取高度
}void MainWindow::resizeEvent(QResizeEvent *event) {//重载函数,自动调用QMainWindow::resizeEvent(event);//计算变化的宽和高int adapt_width=width()-m_width;int adapt_height=height()-m_height;
}
控件自适应位置和大小
统一使用setGeometry方法,这个方法接受四个参数:x坐标、y坐标、宽度和高度。
//原宽高不变,移动X轴坐标
void MainWindow::adaptWidgetPosX(QWidget* widget, int src_X, int adapt_width){if (!widget) return;widget->setGeometry(src_X + adapt_width >0?(src_X + adapt_width):0,widget->y(),widget->width(),widget->height());
}
//原宽高不变,移动Y轴坐标
void MainWindow::adaptWidgetPosY(QWidget* widget, int adapt_height, int src_Y){if (!widget) return;widget->setGeometry(widget->x(),src_Y+adapt_height>0?(src_Y + adapt_height):0,widget->width(),widget->height());
}
//X、Y坐标不变,宽度和高度自适应
void MainWindow::adaptWidgetPosXY(QWidget* widget, int src_w, int src_h, int adapt_width, int adapt_height){if (!widget) return;widget->setGeometry(widget->x(),widget->y(),src_w+adapt_width,src_h+adapt_height);
}
- adaptWidgetPosX()只能保持宽高不变,控件随主窗口横向延伸而移动,比如效果图中的【首页】菜单中的【移动按钮】
- adaptWidgetPosY()只能保持宽高不变,控件随主窗口纵向延伸而移动,如果效果图【第二页】菜单中的竖线
- adaptWidgetPosXY()保存左顶点X,Y坐标不变,宽高自适应调整,有2类用途:1类是宽高与主框架的变化一样,比如效果图【首页】菜单中的tablewidget;1类是宽高其中一个为0,比如效果图【第二页】菜单中的treewidget。
完整代码如下
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include "src/menu/tab_page2_xtool.h"
#include "src/util/comm_define.h"
#include <QMap>
#include <QString>
#include <QTextStream>
#include <QMouseEvent>QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();void adaptWidgetPosX(QWidget* widget, int src_X, int adapt_width);void adaptWidgetPosY(QWidget* widget, int adapt_height, int src_Y);void adaptWidgetPosXY(QWidget* widget, int src_w, int src_h, int adapt_width, int adapt_height);private:Ui::MainWindow *ui;int m_last_width;int m_last_height;tab_page2_xtool *tabpage2;int m_width;int m_height;int m_tabwidget_width;int m_tabwidget_height;int m_tablewidget_width;int m_tablewidget_height;int m_logowidget_posy;int m_logowidget_width;int m_button_posx;protected:void resizeEvent(QResizeEvent *event) override;bool eventFilter(QObject *watched, QEvent *event) override;//事件过滤器
};
#endif // MAINWINDOW_H
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "src/util/customtabstyle.h"
#include <QTimer>
#include <QDebug>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//UI框体初始化this->setWindowIcon(QIcon(":/img/logo.png"));//设置标题栏的文字从左到右ui->tabWidget->tabBar()->setStyle(new CustomTabStyle);ui->logowidget->installEventFilter(this);//安装事件过滤器,qlabel没有默认自带鼠标点击事件,通过事件过滤器捕获tabpage2 = new tab_page2_xtool(this); // 创建实例ui->tabWidget->addTab(tabpage2,"第二页");m_width = this->width(); // 获取宽度m_height = this->height(); // 获取高度m_tabwidget_width=ui->tabWidget->width();m_tabwidget_height=ui->tabWidget->height();m_tablewidget_width=ui->tableWidget->width();m_tablewidget_height=ui->tableWidget->height();m_logowidget_posy=ui->logowidget->pos().y();m_logowidget_width=ui->logowidget->width();ui->logowidget->move((m_width-m_logowidget_width)/2, m_logowidget_posy);m_button_posx=ui->pushButton->pos().x();ui->tabWidget->setMinimumSize(0, 0); //初始化时设置最小尺寸为0
}MainWindow::~MainWindow()
{delete ui;delete tabpage2;}
//原宽高不变,移动X轴坐标
void MainWindow::adaptWidgetPosX(QWidget* widget, int src_X, int adapt_width){if (!widget) return;widget->setGeometry(src_X + adapt_width >0?(src_X + adapt_width):0,widget->y(),widget->width(),widget->height());
}
//原宽高不变,移动Y轴坐标
void MainWindow::adaptWidgetPosY(QWidget* widget, int adapt_height, int src_Y){if (!widget) return;widget->setGeometry(widget->x(),src_Y+adapt_height>0?(src_Y + adapt_height):0,widget->width(),widget->height());
}
//X、Y坐标不变,宽度和高度自适应
void MainWindow::adaptWidgetPosXY(QWidget* widget, int src_w, int src_h, int adapt_width, int adapt_height){if (!widget) return;widget->setGeometry(widget->x(),widget->y(),src_w+adapt_width,src_h+adapt_height);
}void MainWindow::resizeEvent(QResizeEvent *event) {//重载函数,自动调用QMainWindow::resizeEvent(event);//计算变化的宽和高int adapt_width=width()-m_width;int adapt_height=height()-m_height;//X,Y坐标不变,宽高需要变化的控件:tabWidget、tableWidgetadaptWidgetPosXY(ui->tabWidget,m_tabwidget_width,m_tabwidget_height,adapt_width,adapt_height);adaptWidgetPosXY(ui->tableWidget,m_tablewidget_width,m_tablewidget_height,adapt_width,adapt_height);//在界面上方正中间位置的控件:logowidgetui->logowidget->move((width()-m_logowidget_width)/2, m_logowidget_posy);//宽高不变,X轴需要移动的控件:pushButtonadaptWidgetPosX(ui->pushButton,m_button_posx,adapt_width);tabpage2->adapt(adapt_width,adapt_height);
}bool MainWindow::eventFilter(QObject *watched, QEvent *event) {if(event->type() == QEvent::MouseButtonPress){qDebug() << "QEvent::MouseButtonPress";if (watched == ui->logowidget) {//不同的bar调用的对话框不一样,需要watched识别被点击的控件QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);if (mouseEvent->button() == Qt::LeftButton) {//捕获鼠标单击事件QMessageBox::warning(this, "提醒", "这是logo图标区域.");return true; // 吸收事件}}}return QMainWindow::eventFilter(watched, event); // 其他事件交给默认处理
}
主窗口控制分页控件
分页提供一个adapt(int adapt_width,int adapt_height)用于接收主窗口的宽高变化值,同样也是调用adaptWidgetPosX、adaptWidgetPosY、adaptWidgetPosXY来调整宽高,代码如下:
//tab_page2_xtool.h
#ifndef TAB_PAGE2_XTOOL_H
#define TAB_PAGE2_XTOOL_H#include <QDialog>namespace Ui {
class tab_page2_xtool;
}class tab_page2_xtool : public QDialog
{Q_OBJECTpublic:explicit tab_page2_xtool(QWidget *parent = nullptr);~tab_page2_xtool();void adapt(int adapt_width,int adapt_height);void adaptWidgetPosX(QWidget* widget, int src_X, int adapt_width);//移动X轴、原长度不变void adaptWidgetPosY(QWidget* widget, int adapt_height, int src_Y);//移动Y轴、原长度不变void adaptWidgetPosXY(QWidget* widget, int src_w, int src_h, int adapt_width, int adapt_height);//X、Y不变,宽度和高度增加//void adaptWidgetheight(QWidget* widget, src_w, int src_h, int adapt_height);//宽度不变,高度自适应变化private:Ui::tab_page2_xtool *ui;int m_width;int m_height;int m_line_width;int m_line_height;int m_treewidget_width;int m_treewidget_height;int m_button_posx;
};#endif // TAB_PAGE2_XTOOL_H
//tab_page2_xtool.cpp
#include "tab_page2_xtool.h"
#include "ui_tab_page2_xtool.h"tab_page2_xtool::tab_page2_xtool(QWidget *parent): QDialog(parent), ui(new Ui::tab_page2_xtool)
{ui->setupUi(this);m_button_posx=ui->pushButton->pos().x();m_width = this->width(); // 获取宽度m_height = this->height(); // 获取高度m_line_width=ui->line->width();m_line_height=ui->line->height();m_treewidget_width=ui->treeWidget->width();m_treewidget_height=ui->treeWidget->height();
}tab_page2_xtool::~tab_page2_xtool()
{delete ui;
}void tab_page2_xtool::adapt(int adapt_width,int adapt_height) {//宽高不变,X轴需要移动的控件:pushButtonadaptWidgetPosX(ui->pushButton,m_button_posx,adapt_width);//X,Y坐标不变,宽高需要变化的控件:treeWidget、lineadaptWidgetPosXY(ui->treeWidget,m_treewidget_width,m_treewidget_height,0,adapt_height);adaptWidgetPosXY(ui->line,m_line_width,m_line_height,0,adapt_height);
}//移动X轴、原长度不变
void tab_page2_xtool::adaptWidgetPosX(QWidget* widget, int src_X, int adapt_width){if (!widget) return;widget->setGeometry(src_X + adapt_width >0?(src_X + adapt_width):0,widget->y(),widget->width(),widget->height());
}
//移动Y轴、原长度不变
void tab_page2_xtool::adaptWidgetPosY(QWidget* widget, int adapt_height, int src_Y){if (!widget) return;widget->setGeometry(widget->x(),src_Y+adapt_height>0?(src_Y + adapt_height):0,widget->width(),widget->height());
}
//X、Y不变,宽度和高度增加
void tab_page2_xtool::adaptWidgetPosXY(QWidget* widget, int src_w, int src_h, int adapt_width, int adapt_height){if (!widget) return;widget->setGeometry(widget->x(),widget->y(),src_w+adapt_width,src_h+adapt_height);
}