QT页面纯代码实现

一. 内容简介

QT页面纯代码实现。

二. 软件环境

2.1 QT 5.14.1

QT编译器采用的是MSVC2017 64bit

2.2 MatlabR2022b(64位)

2.3 Visual studio 2017

Visual stdio采用2017主要是因为QT5.14.1最高到MSVC2017 64bit。

三. 主要流程

3.1 Qt布局控件详解

3.2 实际布局以及样式调整

3.3 动态删减控件,标签点击事件

4.3 简单测试

四. 具体步骤

4.1 Qt布局控件详解

Qt 共提供了 5 种布局管理器,关系图如下。
在这里插入图片描述
首先介绍,QVBoxLayout,QHBoxLayout,QBoxLayout可以在水平方向或垂直方向上排列控件,由QHBoxLayout、QVBoxLayout所继承。水平布局、垂直布局除了构造时的方向(LeftToRight、TopToBottom)不同外,其它均相同,所以我们这里就拿 QVBoxLayout做主要讲解了,个人觉得这个QVBoxLayout放入一个widget中其实有点像html里面的div。下面都是拿别人讲的,我觉得他讲的比较细。文章在参考里面。

在页面中添加按钮

    QPushButton* pushButton1;
    QPushButton* pushButton2;
    QPushButton* pushButton3;
    QPushButton* pushButton4;
    QVBoxLayout *pLayout;
 
    pLayout = new QVBoxLayout();// 垂直布局 可以当成div
 
    pushButton1 = new QPushButton();        
    pushButton1->setText("pushButton_1");
    pushButton2 = new QPushButton();        
    pushButton2->setText("pushButton_2");
    pushButton3 = new QPushButton();        
    pushButton3->setText("pushButton_3");
    pushButton4 = new QPushButton();        
    pushButton4->setText("pushButton_4");
    
	pLayout->addWidget(pushButton1);
    pLayout->addWidget(pushButton2);
    pLayout->addWidget(pushButton3);
    pLayout->addWidget(pushButton4);
 
    ui->centralwidget->setLayout(pLayout);// 这块是给页面添加进布局,

在这里插入图片描述
然后有一个addStretch()方法,
这方法可以传参,也可以不传,和弹簧控件效果一样,gpt回答(它会自动被放置在布局中并填充布局中的任何可用空间。这可以确保布局中的其他控件按照所需的方式进行布置,例如在它们之间保持固定间距或在窗口大小变化时适应布局。因此,addStretch()方法和添加一个弹簧控件的效果是一样的。)
给参数的话就,

layout = QHBoxLayout()  # 创建水平布局
button1 = QPushButton("Button 1")
button2 = QPushButton("Button 2")
layout.addWidget(button1)
layout.addStretch(1)  # 添加一个弹簧,系数为1
layout.addWidget(button2)
layout.addStretch(2)  # 添加另一个弹簧,系数为2

gpt回答(在上述代码中,我们首先创建了一个水平布局,并在其中添加了两个按钮。然后,我们使用addStretch()方法添加了两个弹簧项,其中第一个弹簧项的弹簧系数为1,第二个弹簧项的弹簧系数为2。这意味着第二个弹簧项将占据第一个弹簧项的两倍空间。当窗口的大小发生变化时,这些弹簧项将自动调整大小以适应布局。)
我在第一个控件前添加addStretch(),在后边添加就都到上边了。
在这里插入图片描述
两端都添加就是居中

    pLayout->addStretch();  // 添加伸缩
    pLayout->addWidget(pushButton1);
    pLayout->addWidget(pushButton2);
    pLayout->addWidget(pushButton3);
    pLayout->addWidget(pushButton4);
    pLayout->addStretch();  // 添加伸缩

在这里插入图片描述
然后每一个中间都添加,就是均分
在这里插入图片描述
在有就设置间隔的

// 这个设置间隔的
pLayout->setSpacing(150);
// 这个是在控件中添加间隔的
pLayout->addSpacing(15);

在这里插入图片描述
然后是addWidget拓展,addWidget可以单独添加一个控件,然后他后边也可以在给定一些参数,第三位就是设置对齐位置了,

	// 里面第二位参数,表示伸缩因子,0的话代表标签大小固定,不会随着容器大小而改变,给值的话,就和上边一样了,
	// 当一个布局中有多个小部件的伸缩因子不同时,它们的大小将根据它们的伸缩因子进行分配。如果一个小部件的伸缩因子为2,而另一个小部件的伸缩因子为1,则前者的大小将是后者的两倍。如果两个小部件的伸缩因子相等,则它们将按照它们的初始大小进行分配。
    pLayout->addWidget(pushButton1,0,Qt::AlignLeft | Qt::AlignTop);

然后是设置容器的margin,容器的margin,而不是控件的margin,就和设值div的margin一样,还是建议用css写,设置为0就没有了
在这里插入图片描述

	// 这种就像css里面的 margin:100;
    pLayout->setMargin(100);
    pLayout->setContentsMargins(10, 100, 10, 100 );

设置拉伸系数

	// 设置pButton1的拉伸系数为1,pButton2拉伸系数为2,当窗体变大时,会优先将pButton2进行拉伸,当达到一定程度时,再拉伸pButton1,pButton1和pButton2的宽度比例为1:2。
	setStretchFactor(pButton1, 1);
	setStretchFactor(pButton2, 2);

这块都是拿别人的,写的很好
可拉伸控件(弹簧)([Qt 教程之Widgets模块] —— QBoxLayout盒模型布局)原文链接:https://blog.csdn.net/maizousidemao/article/details/128124545
其中,index需要注意:
index从0开始;
弹簧和原有控件分别占用一个index;
插入后弹簧后,插入位置后面的index都会加 1;
由于弹簧也是控件,所以布局的控件间距仍适用于弹簧与其他控件之间;
如下图:
布局(A),没有插入弹簧,三个PushButton的index以此为0、1、2;
布局(B),在PushButton1和PushButton2之间插入一个弹簧,则PushButton2和PushButton3的index变为了2、3;
布局©,全部插入弹簧后,index依次变化。
所以手动插入弹簧时要注意index的变化。

void addStretch(int stretch = 0); // 在控件队列最后面添加一个弹簧
void insertStretch(int index, int stretch = 0); // 在指定位置插入一个弹簧
// 一下函数不仅用于弹簧,也可用于其他控件
void setStretch(int index, int stretch); // 设置指定位置控件的拉伸系数
int stretch(int index) const; // 获取指定位置的拉伸系数

在这里插入图片描述
对于拉伸系数stretch,即在sizePolicy的前提下,可拉伸控件按照什么样的比例分配空间,

如果stretch为0,该控件只保留自己最小的空间,不参与空间争夺
如果sizePolicy为Fixed,该控件保持Fixed大小,也不参与空间争夺
如果控件达到了sizePolicy或其他限制的大小,仍无法满足stretch所设置的比例,则控件以限制大小为准,不再按stretch所设置比例拉伸。
如下图,
布局(A),布局空间可以满足控件比例1:2:1,PushButton1、PushButton2和PushButton3的大小分别为98:197:98。
布局(B),布局空间不足以满足控件比例1:2:3,PushButton1和PushButton2的比例明显不满足1:2。
如果布局空间不足以满足控件比例,这里还有个规律,就是先剥夺占比小的控件的空间,优先保证占比大的控件的比例。比如布局(B)中,先剥夺PushButton1的空间,不管他是不是满足控件比例,他们的大小分别为97:118:178,可以发现PushButton2和PushButton3仍然满足2:3的比例。
在这里插入图片描述

// 在控件队列最后面添加一个新控件
// 其中可以指定控件的拉伸系数和对齐方式
void addWidget(QWidget *, int stretch = 0, Qt::Alignment alignment = Qt::Alignment());
// 在指定位置插入一个控件
void insertWidget(int index, QWidget *widget, int stretch = 0, 
                  Qt::Alignment alignment = Qt::Alignment());

最后最后就是设计这个容器的排列方式,水平和垂直也就对齐方式不一样,就水平布局和垂直布局,这两个布局就完事了

	// 方向上
	pLayout->setDirection(QBoxLayout::BottomToTop);
	// 方向下
	pLayout->setDirection(QBoxLayout::TopToBottom);
	// 方向左
	pLayout->setDirection(QBoxLayout::LeftToRight);
	// 方向右
	pLayout->setDirection(QBoxLayout::RightToLeft);

还有剩下的几种布局,以及分割窗口QSplitter,停靠窗口QDockWidget,堆栈窗体QStackedWidget,用的也少,就放个文章的链接,我以后用到了在整理,第一个里面有剩下的布局,第二个里面有分割窗口QSplitter,停靠窗口QDockWidget,堆栈窗体QStackedWidget。
Qt-5种布局控件详解
Qt布局管理

4.2 实际布局以及样式调整

现在我们有这样一个需求,我们希望有三个按钮总在窗口的最左上角,无论窗口怎么拉伸或拖拽,按钮的位置都不动。那么我们就需要用到两个 layout 嵌套了。大致的思路是在一个垂直的 layout 中嵌套一个水平的 layout,在水平的 layout 右侧设置一个弹簧,在垂直的 layout 下方设置一个弹簧,这样按钮就会一直在左上角了,表示图如下:
在这里插入图片描述

    QVBoxLayout* mainLayout = new QVBoxLayout(this);
    // 水平 Layout
    QHBoxLayout* layout = new QHBoxLayout;
    // 水平 Layout 增加控件
    layout->addWidget(new QPushButton("button1"));
    layout->addWidget(new QPushButton("button2"));
    layout->addWidget(new QPushButton("button3"));
    // 水平 Layout 增加弹簧
    layout->addStretch(1);
    // 将水平 Layout 添加到垂直 Layout
    mainLayout->addLayout(layout);
    // 设置垂直 Layout 弹簧
    mainLayout->addStretch(1);
    ui->centralwidget->setLayout(mainLayout);

水平垂直布局综合应用
水平的五个按钮(按钮在window中)
在window1中放置一个按钮
垂直的两个窗口(window和window1垂直)

	// this是最大窗口  
    this->resize(1500,800);
    //多个窗口不要this
    window = new QWidget();
    button1 = new QPushButton("One");
    button2 = new QPushButton("Two");
    button3 = new QPushButton("Three");
    button4 = new QPushButton("Four");
    button5 = new QPushButton("Five");
 
    QHBoxLayout *layout = new QHBoxLayout;//水平的按钮
    layout->addWidget(button1);
    layout->addWidget(button2);
    layout->addWidget(button3);
    layout->addWidget(button4);
    layout->addWidget(button5);
    window->setLayout(layout);
    window1= new QWidget();
    QPushButton *button1 = new QPushButton("One",window1);//在window1中放置一个按钮
    //this是最大窗口              垂直的窗口
    QVBoxLayout *vlayout = new QVBoxLayout(this);//两个窗口垂直放置
    vlayout->addWidget(window);
    vlayout->addWidget(window1);

在自己布局时候,如果在控件中加上了layout布局,就会发现发现没有办法使用setGeometry函数了,这是因为布局已经被layout管理,没办法设置尺寸啥的了,可以结合widget一起使用,先用widget划分区域,然后再用布局,当然也可以直接不用布局,使用setGeometry()来设置各个控件的大小和位置,使用layout布局是没办法实现控件重叠的,单独使用widget是可以实现控件重叠的,控件重叠可以做一些小功能。页面布局这个以后在写。
页面css写的话,我一般都用id选择器,QT里面好像没有类这个用法,只能单独写样式了。如果控件都是代码写的话,样式设置需要再控件初始化以后读取,早读就没有效果了,可以拿我下边的代码改改。

//    //启动第三阶段
//    splash.showMessage(QObject::tr("加载页面样式..."), Qt::AlignHCenter|Qt::AlignBottom, Qt::black);
//    // 用于延时处理
//    n=QDateTime::currentDateTime();
//    do{
    
    
//        now=QDateTime::currentDateTime();
//    } while (n.secsTo(now)<=0);//1为需要延时的秒数
//    //加载第三阶段的资源,页面样式
//    try {
    
    
//        QFile file("111.css");
//        file.open(QIODevice::ReadOnly);
//        QString styleSheet = QString::fromLatin1(file.readAll());
//        a.setStyleSheet(styleSheet);
//        splash.showMessage(QObject::tr("页面样式加载成功..."), Qt::AlignHCenter|Qt::AlignBottom, Qt::black);
//        n=QDateTime::currentDateTime();
//        do{
    
    
//            now=QDateTime::currentDateTime();
//        } while (n.secsTo(now)<=0);
//    } catch (...) {
    
    
//        splash.showMessage(QObject::tr("页面样式加载失败..."), Qt::AlignHCenter|Qt::AlignBottom, Qt::black);
//        n=QDateTime::currentDateTime();
//        do{
    
    
//            now=QDateTime::currentDateTime();
//        } while (n.secsTo(now)<=0);
//    }
#centralWidget {
      
      
    background-color: #fff;
    font-family: "Microsoft soft";
}
#menuBar {
      
      
    background-color: #d4d4d4;
}
#content_title_label {
      
      
    font-size: 20px;
    line-height: 25px;
    color: black;
    background-color: #f0f0f0;
}
#content_title {
      
      
    background-color: #f8f8f8;
}

#charView {
      
      
	border: 0;
	background-color: #fff;
}
#tab_tittle1 {
      
      
    font-size: 15px;
    line-height: 25px;
    color: black;
    font-weight: bold; 
}
#lineEdit {
      
      
    border: 1px solid #c5c5c5; 
    border-radius: 3px;
    font-size: 13px;
}
#comboBox {
      
      
    border: 1px solid gray;   /* 边框 */
    border-radius:2px;   /* 圆角 */
    padding: 0px 0px 0px 10px; /* 上内边距、右内边距、下内边距、左内边距 */
    color: rgba(51,51,51,1);
    background: transparent;
    text-align: AlignHCenter;
    color:rgb(123,123,123);/*字体颜色*/
}

QLineEdit{
    
    
    border: 1px solid #c5c5c5; 
    border-radius: 3px;
    font-size: 13px;
}

#page_1 {
      
      
    background-color: #fff;
}

#tab_11 {
      
      
    overflow: hidden;
}
#imgTab {
      
      
    overflow: hidden;
}
#centralWidget {
      
      
    background-color: #f0f0f0;;
}
#content_img {
      
      
    padding: 0;
    background-color: #fff;
}
#widget {
      
      
    padding: 0;
    background-color: #fff; 
}
#page_1 {
      
      
    background-color: #fff; 
}

#tabWidget_setParameters 
{
    
    
    background-color: #fff; 
}
#toolBox {
      
      
    background-color: #fff; 
}
#page_1 {
      
      
    background-color: #fff;
}
#toolBox2 {
      
      
    background-color: #fff; 
}
#comboBox_7 {
      
      
    border: 1px solid gray;   /* 边框 */
    border-radius:2px;   /* 圆角 */
    padding: 0px 0px 0px 10px; /* 上内边距、右内边距、下内边距、左内边距 */
    color: rgba(51,51,51,1);
    background: transparent;
    text-align: center;
    color:rgb(123,123,123);/*字体颜色*/
}

#pausebutton_1 {
      
      
    border: 1px solid gray;   /* 边框 */
    border-radius:2px;   /* 圆角 */
    /* 上内边距、右内边距、下内边距、左内边距 */
    /*padding-right: 25px;*/
    color: rgba(51,51,51,1);
    background: transparent;
    text-align: center;
    color:rgb(123,123,123);/*字体颜色*/
    cursor: pointer;/*设置鼠标箭头手势*/
}


4.3 动态删减控件,标签点击事件

创建控件方法[两种方法]如下
1.自定义所有控件(不推荐)
2.动态创建所有控件(推荐)

     this->resize(1500,800);
     leftwin = new QWidget();
     topwin = new QWidget();
     indexwin = new QWidget();
 
     //方法一:自定义所有控件
     //控件水平
     QHBoxLayout *hboxlayout = new QHBoxLayout(topwin);
     searchEdit = new QLineEdit();
     userBtn = new QPushButton();
     vipBtn = new QPushButton();
     hboxlayout->addWidget(searchEdit);
     hboxlayout->addWidget(userBtn);
     hboxlayout->addWidget(vipBtn);
     //方法二:动态创建所有控件
     //按钮控件垂直
     QVBoxLayout *vboxlayout1 = new QVBoxLayout(indexwin);
     QStringList funBtnlist;
     funBtnlist<<"logo"<<"视频"<<"动漫"<<"电影";
     for(int i=0;i<funBtnlist.size();i++)
     {
    
    
         QPushButton *newBtn = new QPushButton(funBtnlist.at(i));
         vboxlayout1->addWidget(newBtn);
     }
     //两个窗口垂直
     QVBoxLayout *vboxlayout = new QVBoxLayout(this);
     vboxlayout->addWidget(topwin);
     vboxlayout->addWidget(indexwin);

清除布局器所有控件

// 1.ui->verticalLayout->removeItem(child);只是将控件从布局管理器里移除,此时控件依然会在界面显示
// 2.delete child->widget();将对象销毁才可以使得控件不在界面展示
#include "verticallayoutwidget.h"
#include "ui_verticallayoutwidget.h"

VerticalLayoutWidget::VerticalLayoutWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::VerticalLayoutWidget)
{
    
    
    ui->setupUi(this);
    for(int i=0;i<3;i++){
    
    
        QLabel *label = new QLabel;
        label->setStyleSheet("background:white");
        label->setText("label"+QString::number(i));
        ui->verticalLayout->addWidget(label);
    }
}

VerticalLayoutWidget::~VerticalLayoutWidget()
{
    
    
    delete ui;
}

void VerticalLayoutWidget::on_pushButton_clicked()
{
    
    
    QLayoutItem *child;
    while ((child = ui->verticalLayout->itemAt(0)) != nullptr) {
    
    
        ui->verticalLayout->removeItem(child);
        delete child->widget();
        delete child;
        child = nullptr;
    }
}

标签点击事件

// .h
bool eventFilter(QObject *obj, QEvent *event);
// .c
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    
    
    if (event->type() == QEvent::MouseButtonPress)
    {
    
    
        // 处理鼠标单击事件
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        // 判断鼠标单击是否发生在标签内部
        if (obj == ui->label && ui->label->rect().contains(mouseEvent->pos()))
        {
    
    
        }
        return true;
    }
    return QObject::eventFilter(obj, event);
}

	// 安装事件过滤器
    ui->label->installEventFilter(this);
    ui->label_h->installEventFilter(this);
    ui->label_hf->installEventFilter(this);
    ui->label_t->installEventFilter(this);
    ui->label_p->installEventFilter(this);

4.3 简单测试

用layout管理时候,感觉他管理的布局很乱,没办法像前端那样,写margin,padding啥的,写了也没用,纯代码布局还是不让layout管理了,
就用widget切分布局,然后给每一个wiget单独设置里面的东西,里面layout管理方式不知道和qml中是否一样,layout控件管理方式我在另外一个里面写了QML中RowLayout和row区别,实现类似于前端那样的布局方式(http://t.csdn.cn/3VlJS)

    QWidget* leftWidget;
    QWidget* rightWidget;
    leftWidget = new QWidget();
    rightWidget = new QWidget();
    // 如果不写这个,下面的样式是不会生效的
    leftWidget->setObjectName("leftWidget");
    rightWidget->setObjectName("rightWidget");

    leftWidget->setParent(ui->centralwidget);
    rightWidget->setParent(ui->centralwidget);

	// 这个宽高包含了margin的,直接定位的话,margin好像也没什么意义了
    leftWidget->setGeometry(20,0,90,100);//设置位置以及宽高
    rightWidget->setGeometry(200,0,90,100);//设置位置以及宽高
    
    // 样式表也可以写在全局的,名字要匹配的,然后样式里面写width以及height都是没办法生效的,
    // 样式表的作用可能也就是改改颜色字体以及改改样子了,并不像前端那样可以玩玩整整的调整布局
    leftWidget->setStyleSheet("#leftWidget {width: 100px;height: 100px;margin: 0px; background-color: red;}");
    rightWidget->setStyleSheet("#rightWidget {width: 100px;height: 100px;margin: 0px; background-color: blue;}");

在这里插入图片描述
在这里插入图片描述

五. 参考

Qt-5种布局控件详解
QT QVBoxLayout 垂直布局控件
Qt 之水平/垂直布局(QBoxLayout、QHBoxLayout、QVBoxLayout)
Qt水平布局,垂直布局和嵌套布局 layout
【Qt学习】 垂直布局和水平布局
QVBoxLayout QLayoutItem 清除布局器所有控件
[Qt 教程之Widgets模块] —— QBoxLayout盒模型布局

猜你喜欢

转载自blog.csdn.net/qq_45179361/article/details/130480514
今日推荐