Skip to content

Commit a5414a7

Browse files
committed
first commit
1 parent 1431658 commit a5414a7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+665
-0
lines changed

README.md

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# 07. Qt对话框的自适应动态布局(布局跟随窗口大小改变)
2+
## 一、效果图
3+
## 二、制作原理说明
4+
要想实现对话框缩放时候内部的控件跟着动态缩放。需要以下几个关键设置:
5+
1. 给对话框窗口设置一个布局,以后窗口靠这个布局管理
6+
2. 给对话框窗口设置QSizePolicy为Expanding
7+
3. 窗口内包含的控件都设置QSizePolicy::Expanding属性,或自定义控件覆盖resizeEvent来保持自定义控件动态填满父布局。layout不用设置Expanding属性。
8+
4. 对话框窗口设置setMinimumSize
9+
## 三、自定义跟随父布局缩放的控件
10+
本例子中自己实现了两个自定义控件,分别是:
11+
MyVideoWidget:显示视频或图片的控件
12+
MyRangeSlider:调节裁剪范围的控件
13+
这两个控件都重新实现了resizeEvent方法。因此这两个控件,默认就会填满父布局。会跟着父布局扩展而扩展
14+
15+
## 四、在伸缩动态布局中,保持按钮不变形
16+
在本例子中有两个按钮分别设置了图片背景。以实现自己需要的按钮造型。
17+
按钮配图片的方法为:
18+
```cpp
19+
record_btn_p->setStyleSheet("QPushButton{border-image: url(:/img/image/record.png);}"
20+
"QPushButton:hover{border-image: url(:/img/image/rightcheck.png);}"
21+
"QPushButton:pressed{border-image: url(:/img/image/pause.png);}");
22+
```
23+
设置完按钮发现按钮会随着缩放变形,导致很难看。并且设置setGeometry
24+
并不管用。设置按钮的sizePolicy为Fixed也没有用。经过测试发现,最终的固定按钮尺寸的方法为:
25+
```cpp
26+
record_btn_p->setMinimumSize(QSize(28, 28));
27+
record_btn_p->setMaximumSize(QSize(28, 28));
28+
```
29+
当需要只设置垂直方向固定,则需要如下配置:
30+
```cpp
31+
myrange_slider_p->setMaximumHeight(24);
32+
myrange_slider_p->setMinimumHeight(24);
33+
```
34+
当需要只设置水平方向固定,则需要如下配置:
35+
```cpp
36+
myrange_slider_p->setMinimumWidth(100);
37+
myrange_slider_p->setMaximumWidth(100);
38+
```
39+
## 五、自定义控件源码与本例子源码

VideoPlay.pro

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#-------------------------------------------------
2+
#
3+
# Project created by QtCreator 2019-07-12T10:31:44
4+
#
5+
#-------------------------------------------------
6+
7+
QT += core gui
8+
9+
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
10+
11+
TARGET = VideoPlay
12+
TEMPLATE = app
13+
14+
# The following define makes your compiler emit warnings if you use
15+
# any feature of Qt which has been marked as deprecated (the exact warnings
16+
# depend on your compiler). Please consult the documentation of the
17+
# deprecated API in order to know how to port your code away from it.
18+
DEFINES += QT_DEPRECATED_WARNINGS
19+
20+
# You can also make your code fail to compile if you use deprecated APIs.
21+
# In order to do so, uncomment the following line.
22+
# You can also select to disable deprecated APIs only up to a certain version of Qt.
23+
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
24+
25+
CONFIG += c++11
26+
27+
SOURCES += \
28+
main.cpp \
29+
mainwindow.cpp \
30+
ui/capture_video_dialog/capture_video_dialog.cpp \
31+
views/myrangeslider.cpp \
32+
views/myvideowidget.cpp
33+
34+
HEADERS += \
35+
mainwindow.h \
36+
ui/capture_video_dialog/capture_video_dialog.h \
37+
views/myrangeslider.h \
38+
views/myvideowidget.h
39+
40+
FORMS += \
41+
mainwindow.ui
42+
43+
RESOURCES += \
44+
res/res.qrc
45+
46+
# Default rules for deployment.
47+
qnx: target.path = /tmp/$${TARGET}/bin
48+
else: unix:!android: target.path = /opt/$${TARGET}/bin
49+
!isEmpty(target.path): INSTALLS += target

main.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include "mainwindow.h"
2+
#include <QApplication>
3+
4+
int main(int argc, char *argv[])
5+
{
6+
QApplication a(argc, argv);
7+
MainWindow w;
8+
w.show();
9+
10+
return a.exec();
11+
}

mainwindow.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include "mainwindow.h"
2+
#include "ui_mainwindow.h"
3+
4+
MainWindow::MainWindow(QWidget *parent) :
5+
QMainWindow(parent),
6+
ui(new Ui::MainWindow)
7+
{
8+
ui->setupUi(this);
9+
}
10+
11+
MainWindow::~MainWindow()
12+
{
13+
delete ui;
14+
}
15+
16+
void MainWindow::on_pushButton_clicked()
17+
{
18+
// CaptureVideoDialog *dialog = new CaptureVideoDialog(this);
19+
// dialog->show();
20+
21+
CaptureVideoDialog captureVideoDialog(this);
22+
if(captureVideoDialog.exec() == QDialog::Accepted) {
23+
24+
25+
}
26+
}

mainwindow.h

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#ifndef MAINWINDOW_H
2+
#define MAINWINDOW_H
3+
4+
#include <QMainWindow>
5+
6+
#include "ui/capture_video_dialog/capture_video_dialog.h"
7+
8+
namespace Ui {
9+
class MainWindow;
10+
}
11+
12+
class MainWindow : public QMainWindow
13+
{
14+
Q_OBJECT
15+
16+
public:
17+
explicit MainWindow(QWidget *parent = nullptr);
18+
~MainWindow();
19+
20+
private slots:
21+
void on_pushButton_clicked();
22+
23+
private:
24+
Ui::MainWindow *ui;
25+
};
26+
27+
#endif // MAINWINDOW_H

mainwindow.ui

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<ui version="4.0">
3+
<class>MainWindow</class>
4+
<widget class="QMainWindow" name="MainWindow">
5+
<property name="geometry">
6+
<rect>
7+
<x>0</x>
8+
<y>0</y>
9+
<width>400</width>
10+
<height>300</height>
11+
</rect>
12+
</property>
13+
<property name="windowTitle">
14+
<string>MainWindow</string>
15+
</property>
16+
<widget class="QWidget" name="centralWidget">
17+
<widget class="QPushButton" name="pushButton">
18+
<property name="geometry">
19+
<rect>
20+
<x>110</x>
21+
<y>110</y>
22+
<width>113</width>
23+
<height>32</height>
24+
</rect>
25+
</property>
26+
<property name="text">
27+
<string>PushButton</string>
28+
</property>
29+
</widget>
30+
</widget>
31+
<widget class="QMenuBar" name="menuBar">
32+
<property name="geometry">
33+
<rect>
34+
<x>0</x>
35+
<y>0</y>
36+
<width>400</width>
37+
<height>22</height>
38+
</rect>
39+
</property>
40+
</widget>
41+
<widget class="QToolBar" name="mainToolBar">
42+
<attribute name="toolBarArea">
43+
<enum>TopToolBarArea</enum>
44+
</attribute>
45+
<attribute name="toolBarBreak">
46+
<bool>false</bool>
47+
</attribute>
48+
</widget>
49+
<widget class="QStatusBar" name="statusBar"/>
50+
</widget>
51+
<layoutdefault spacing="6" margin="11"/>
52+
<resources/>
53+
<connections/>
54+
</ui>

res/image/Thumbs.db

12.5 KB
Binary file not shown.

res/image/app_icon.png

167 KB
Loading

res/image/area.png

25.1 KB
Loading

res/image/backward.png

25.3 KB
Loading

res/image/circle.png

28.3 KB
Loading

res/image/crop.png

25.6 KB
Loading

res/image/defaultsize.png

26.7 KB
Loading

res/image/dxfimport.png

26.8 KB
Loading

res/image/dxfoutput.png

27.1 KB
Loading

res/image/effect.png

27.7 KB
Loading

res/image/erase.png

24.6 KB
Loading

res/image/forward.png

26.2 KB
Loading

res/image/gamma.png

28.1 KB
Loading

res/image/img.png

26.8 KB
Loading

res/image/importimg.png

27.1 KB
Loading

res/image/lamptest.png

27 KB
Loading

res/image/lettera.png

26.4 KB
Loading

res/image/outputvideo.png

25.9 KB
Loading

res/image/pan.png

28.3 KB
Loading

res/image/pause.png

26.9 KB
Loading

res/image/reboot.png

28.2 KB
Loading

res/image/record.png

31 KB
Loading

res/image/reset.png

28.3 KB
Loading

res/image/rgb.png

31.1 KB
Loading

res/image/rightcheck.png

32.3 KB
Loading

res/image/standard.psd

425 KB
Binary file not shown.

res/image/zoomin.png

30.3 KB
Loading

res/image/zoomout.png

29.1 KB
Loading

res/res.qrc

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<RCC>
2+
<qresource prefix="/img">
3+
<file>image/record.png</file>
4+
<file>image/pause.png</file>
5+
<file>image/rightcheck.png</file>
6+
</qresource>
7+
</RCC>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
2+
#include "capture_video_dialog.h"
3+
4+
5+
CaptureVideoDialog::CaptureVideoDialog(QWidget *parent) :
6+
QDialog(parent)
7+
{
8+
SetupUI(this);
9+
10+
}
11+
12+
CaptureVideoDialog::~CaptureVideoDialog()
13+
{
14+
15+
}
16+
17+
18+
void CaptureVideoDialog::SetupUI(QDialog *dialog) {
19+
20+
if (dialog->objectName().isEmpty())
21+
dialog->setObjectName(QString::fromUtf8("capturingDialog"));
22+
dialog->setWindowModality(Qt::NonModal);
23+
dialog->resize(dialog_w_, dialog_h_);
24+
25+
//给主窗口设置 尺寸策略,为了内部布局可以跟着窗口一起扩展,需要用“Expanding”
26+
QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
27+
dialog->setSizePolicy(sizePolicy);
28+
dialog->setMinimumSize(QSize(dialog_w_, dialog_h_));
29+
30+
QVBoxLayout *main_v_layout;
31+
main_v_layout = new QVBoxLayout(dialog);//只有这个布局需要传入主窗口对象,表示这个布局是管理窗口的布局
32+
main_v_layout->setObjectName(QString::fromUtf8("verticalLayout"));
33+
main_v_layout->setSpacing(0);//设置布局内的布局与布局之间或控件与控件之间的距离
34+
main_v_layout->setContentsMargins(0, 0, 0, 0);//设置主窗口dialog与此主布局之间的margin
35+
36+
QHBoxLayout *video_h_layout;
37+
video_h_layout = new QHBoxLayout();//其他的子布局 ,不要传入主窗口的对象
38+
video_h_layout->setObjectName(QString::fromUtf8("video_h_layout"));
39+
40+
//video
41+
MyVideoWidget *my_video_widget_p;
42+
my_video_widget_p = new MyVideoWidget();
43+
my_video_widget_p->setObjectName(QString::fromUtf8("my_video_widget_p"));
44+
// QSizePolicy video_view_size_policy(QSizePolicy::Expanding, QSizePolicy::Expanding);
45+
// my_video_widget_p->setSizePolicy(video_view_size_policy);
46+
video_h_layout->addWidget(my_video_widget_p);
47+
48+
QHBoxLayout *toolbar_h_layout;
49+
toolbar_h_layout = new QHBoxLayout();//其他的子布局 ,不要传入主窗口的对象
50+
toolbar_h_layout->setObjectName(QString::fromUtf8("horizontalLayout_2"));
51+
toolbar_h_layout->setSpacing(6); //设置控件与控件之间的距离
52+
toolbar_h_layout->setContentsMargins(6, 3, 6,3);//设置各个边单独的 margin距离
53+
54+
//tool bar
55+
//range
56+
MyRangeSlider *myrange_slider_p;
57+
myrange_slider_p = new MyRangeSlider();//不需要传入父窗口对象
58+
myrange_slider_p->setObjectName(QString::fromUtf8("myrange_slider_p"));
59+
myrange_slider_p->setMaximumHeight(24);
60+
myrange_slider_p->setMinimumHeight(24);
61+
myrange_slider_p->setMinimumWidth(100);
62+
63+
//tool bar rocord btn
64+
QPushButton *record_btn_p;
65+
record_btn_p = new QPushButton();//不需要传入父窗口对象
66+
record_btn_p->setObjectName(QString::fromUtf8("record_btn_p"));
67+
record_btn_p->setFocusPolicy(Qt::NoFocus);
68+
record_btn_p->setFlat(true);
69+
record_btn_p->setMinimumSize(QSize(28, 28));
70+
record_btn_p->setMaximumSize(QSize(28, 28));
71+
record_btn_p->setStyleSheet("QPushButton{border-image: url(:/img/image/record.png);}"
72+
"QPushButton:hover{border-image: url(:/img/image/rightcheck.png);}"
73+
"QPushButton:pressed{border-image: url(:/img/image/pause.png);}");
74+
75+
//tool bar ok btn
76+
QPushButton *ok_btn_p;
77+
ok_btn_p = new QPushButton();//不需要传入父窗口对象
78+
ok_btn_p->setObjectName(QString::fromUtf8("ok_btn_p"));
79+
ok_btn_p->setMinimumSize(QSize(28,28));
80+
ok_btn_p->setMaximumSize(QSize(28, 28));
81+
ok_btn_p->setStyleSheet("QPushButton{border-image: url(:/img/image/record.png);}"
82+
"QPushButton:hover{border-image: url(:/img/image/rightcheck.png);}"
83+
"QPushButton:pressed{border-image: url(:/img/image/pause.png);}");
84+
85+
toolbar_h_layout->addWidget(myrange_slider_p);
86+
toolbar_h_layout->addWidget(record_btn_p);
87+
toolbar_h_layout->addWidget(ok_btn_p);
88+
toolbar_h_layout->setStretch(0, 8);
89+
toolbar_h_layout->setStretch(1, 1);
90+
toolbar_h_layout->setStretch(2, 1);
91+
92+
main_v_layout->addLayout(video_h_layout);
93+
main_v_layout->addLayout(toolbar_h_layout);
94+
//由于控件自己支持延展因此不需要如下设置
95+
// main_v_layout->setStretch(0, 5);//设置第一个添加的布局的比例
96+
// main_v_layout->setStretch(1, 5);//设置第二个添加的布局的比例
97+
98+
99+
//直接把这两个背景分别设置到 video_h_layout 和 toolbar_h_layout
100+
//就可以看到 main_v_layout->setStretch的效果了
101+
/*
102+
QWidget *video_h_layout_bg = new QWidget();
103+
video_h_layout_bg->setObjectName("video_h_layout_bg");
104+
video_h_layout_bg->setProperty("video-bg", true);
105+
video_h_layout_bg->setStyleSheet("QWidget[video-bg=\"true\"] {background-color: #ff0000;}");
106+
video_h_layout->addWidget(video_h_layout_bg);
107+
108+
109+
QWidget *toolbar_h_layout_bg = new QWidget();
110+
toolbar_h_layout_bg->setObjectName("toolbar_h_layout_bg");
111+
toolbar_h_layout_bg->setProperty("toolbar-bg", true);
112+
toolbar_h_layout_bg->setStyleSheet("QWidget[toolbar-bg=\"true\"] {background-color: #00ff00;}");
113+
toolbar_h_layout->addWidget(toolbar_h_layout_bg);
114+
*/
115+
116+
117+
118+
RetranslateUi(dialog);
119+
120+
QMetaObject::connectSlotsByName(dialog);
121+
}
122+
123+
void CaptureVideoDialog::RetranslateUi(QDialog *dialog) {
124+
dialog->setWindowTitle(QApplication::translate("CaptureVideoDialog", "CaptureVideoDialog"));
125+
126+
}
127+
128+
129+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
2+
3+
#ifndef CAPTURE_VIDEO_DIALOG_H
4+
#define CAPTURE_VIDEO_DIALOG_H
5+
6+
#include <QApplication>
7+
#include <QDialog>
8+
#include <QPushButton>
9+
#include <QLabel>
10+
#include <QVBoxLayout>
11+
#include <QPushButton>
12+
#include <QSlider>
13+
14+
15+
16+
#include "../../views/myvideowidget.h"
17+
#include "../../views/myrangeslider.h"
18+
19+
class CaptureVideoDialog: public QDialog
20+
{
21+
Q_OBJECT
22+
public:
23+
explicit CaptureVideoDialog(QWidget *parent = nullptr);
24+
~CaptureVideoDialog();
25+
26+
private:
27+
void SetupUI(QDialog *dialog);
28+
void RetranslateUi(QDialog *dialog);
29+
30+
private:
31+
32+
33+
private slots:
34+
//函数名规则:on_子对象名_信号名
35+
36+
37+
private:
38+
const int dialog_w_ = 280;
39+
const int dialog_h_ = 180;
40+
41+
private:
42+
43+
};
44+
45+
#endif // CAPTURE_VIDEO_DIALOG_H

0 commit comments

Comments
 (0)