实现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、完成



















