实现Qwidget窗口填满整个主窗口,并跟随鼠标的拖动自动缩放
新建一个窗口,我想在这个窗口上放一个QWidget,并且这个QWidget能够布满整个窗口,还可以随着随鼠标的拖动自动缩放
1、首先给大家介绍一个好用的组件库:qt-material-widgets
(1)开源地址(基于QWidgets)
https://github.com/laserpants/qt-material-widgets
基于Qt Quick(QML)可以参考以下开源项目:
https://github.com/uwerat/qskinny
(2)静态库文件准备
- 先把项目的源码clone 下来,然后双击qt-material-widgets.pro 使用Qt creator打开
- 构建Debug生成静态库文件 libcomponents.a 路径(build-qt-material-widgets-Desktop_Qt_5_15_2_MinGW_64_bit-Debug\components\debug\libcomponents.a)
- 在你的项目里新建文件夹 sdk/material/staticLib
- 把libcomponents.a复制到 sdk/material/staticLib/libcomponents.a 下面;
- 把源码的components文件夹整体复制到sdk/material下面;(注意:components文件夹是clone下来源码的qt-material-widgets\components)
(3)在项目中引入库
-
qmake方式 .pro
#MaterialSDK LIBS += $$PWD/sdk/material/staticLib/libcomponents.a INCLUDEPATH += $$PWD/sdk/material/components PRE_TARGETDEPS += $$PWD/sdk/material/staticLib/libcomponents.a
-
CMake方式 CmakeLists.txt
add_library( libcomponents STATIC IMPORTED ) set_target_properties( libcomponents PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/SDK/Material/lib/libcomponents.a ) target_link_libraries(${PROJECT_NAME} PRIVATE libcomponents)
2、在main.cpp中引入qss文件:
#include "material.h"
#include <QApplication>
#include <QFile>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
// 引入qss文件
QFile file(":/style/style.qss");
if ( file.exists() ) {
// 以只读的方式打开
file.open(QFile::ReadOnly);
// 以字符串的方式保存读出的结果
QString styleSheet = QLatin1String(file.readAll());
// 设置全局样式
qApp->setStyleSheet(styleSheet);
// 关闭文件
file.close();
}
// 初始化一个material窗口
Material material;
// 显示主窗口
material.show();
return app.exec();
}
style.qss文件内容如下,给mainWidget加个背景色,便于观察变化
#mainWidget {
background-color: red;
}
3、新建 material.h文件,内容如下:
#ifndef MATERIAL_H
#define MATERIAL_H
#include <QWidget>
#include <qtmaterialtoggle.h>
QT_BEGIN_NAMESPACE
namespace Ui { class Material; }
QT_END_NAMESPACE
class Material : public QWidget
{
Q_OBJECT
public:
Material(QWidget *parent = nullptr);
~Material();
private:
Ui::Material *ui;
protected:
/* 1、将函数声明为virtual的作用是允许这两个函数在派生类中被重写(override),
* 因为resizeEvent()和moveEvent()是QWidget类中的虚函数,因此在派生类中也要将其声明为virtual,
* 这样就可以在派生类中重新定义这两个函数,以实现派生类中对窗口大小改变和窗口移动事件的处理
*/
virtual void resizeEvent(QResizeEvent *event);
virtual void moveEvent(QMoveEvent *event);
private:
QWidget *mainWidget; // 1、添加mainWidget成员变量
};
#endif // MATERIAL_H
4、新建 material.cpp文件,内容如下:
#include "material.h"
#include "ui_material.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
Material::Material(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Material)
{
ui->setupUi(this);
// 使用Material-widgets
QtMaterialToggle *switchToggle = new QtMaterialToggle();
//switchToggle->setGeometry(50, 50, 164, 96);
// 1、创建一个QWidget容器
mainWidget = new QWidget(this);
// 设置 objectName 属性,QSS 文件中使用 #objectName 来定位到该控件
mainWidget->setObjectName("mainWidget");
// 设置widget容器充满整个窗口,并且跟随窗口缩放
mainWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
mainWidget->setGeometry(0, 0, width(), height());
// Qt中设置窗体大小的方法
// 设置它的最大窗口值和最小窗口值,并且使最大值和最小值相等,窗口的最大化按钮将变得不可用
// mainWidget->setMinimumSize(200, 200);
// mainWidget->setMaximumSize(200, 200);
// 后来发现还有一个方法就是 resize,在构造函数中直接调用他设置大小就可以
//mainWidget->resize( QSize( 1128, 761 ));
QHBoxLayout *layout = new QHBoxLayout(this);
QPushButton *button1 = new QPushButton("按钮1");
QPushButton *button2 = new QPushButton("按钮2");
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(switchToggle);
layout->setSpacing(60); // 设置部件间距为60像素
// Qt::AlignLeft 水平方向靠左
// Qt::AlignRight 水平方向靠右
// Qt::AlignHCenter 水平方向居中
// Qt::AlignTop 垂直方向靠上
layout->setAlignment(Qt::AlignCenter);
// 将布局放到mainWidget上
mainWidget->setLayout(layout);
// 将布局应用到窗口上
// this->setLayout(layout);
//有时候会想让我们的程序窗体固定大小,而该大小是我们在编辑时的大小
//int width = this->geometry().width(); // 找到该窗体的物理大小
//int height = this->geometry().height();
//this->setFixedSize(width,height); //设置窗体固定大小
// 设置窗口的大小,微信PC应用是1138x761
// 设置它的最大窗口值和最小窗口值,并且使最大值和最小值相等,窗口的最大化按钮将变得不可用
// this->setMinimumSize(1128, 761);
// this->setMaximumSize(1128, 761);
// 后来发现还有一个方法就是 resize。在构造函数中直接调用他设置大小就可以
//this->resize( QSize( 1128, 761 ));
// 将容器添加到主窗口中
//this->setCentralWidget(widget);
this->setWindowTitle("QWidget布局");
}
Material::~Material()
{
delete ui;
}
/* 2、如果要实现widget窗口跟随鼠标拖动并自动跟随窗口缩放,
* 需要在QWidget类中重写resizeEvent()函数和moveEvent()函数
*/
// 在resizeEvent()函数中,重新设置widget窗口的大小和位置
void Material::resizeEvent(QResizeEvent *event)
{
QWidget::resizeEvent(event); // 调用父类的resizeEvent()函数
if(this->mainWidget) // 判断是否有widget被添加到Material窗口中
{
// 获取Material窗口的大小
int w = this->width();
int h = this->height();
// 设置widget的大小为Material窗口的大小
this->mainWidget->setGeometry(0, 0, w, h);
}
}
// 在moveEvent()函数中,重新设置widget窗口的位置
void Material::moveEvent(QMoveEvent *event)
{
QWidget::moveEvent(event);
if(this->mainWidget)
{
this->mainWidget->move(0, 0);
}
}
5、效果展示
6、完成