赞
踩
QT页面纯代码实现。
QT编译器采用的是MSVC2017 64bit
Visual stdio采用2017主要是因为QT5.14.1最高到MSVC2017 64bit。
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布局管理
现在我们有这样一个需求,我们希望有三个按钮总在窗口的最左上角,无论窗口怎么拉伸或拖拽,按钮的位置都不动。那么我们就需要用到两个 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;/*设置鼠标箭头手势*/ }
创建控件方法[两种方法]如下
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);
用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盒模型布局
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。