Skip to content

Commit

Permalink
add L7 L7
Browse files Browse the repository at this point in the history
  • Loading branch information
se7enXF committed Jun 11, 2020
1 parent 1943ae0 commit ebd4b61
Show file tree
Hide file tree
Showing 16 changed files with 253 additions and 13 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.*
!.gitignore
/Lesson_5.结合OpenCV实现视频播放器/*.png
*.mp4
Binary file added Addition/mainwindow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Addition/mainwindow_dock.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions Lesson_1.环境配置与入门/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# 环境配置与入门
## 概要
# 环境配置与入门
第一课,讲述使用Python和PySide2的软件开发环境的配置和显示简单的helloworld界面。
## 软件开发环境
* Windows10(其他操作系统亦可)
Expand All @@ -17,5 +16,6 @@ pip install --index-url=http://download.qt.io/snapshots/ci/pyside/5.11/latest/ p
因此,在下一讲中,会介绍一种结合QtDesigner的用户界面绘制方法,能让我们更高效的实现QtUI。
当你配置好环境,可以直接运行helloworld.py,如果成功运行并显示如下窗口,那么恭喜你入坑!
![hello_world](../Addition/Lesson1.png)
* [第二课](../Lesson_2.使用QtDesigner/README.md)
## 参考文档
[PySide官方文档 Qt for Python](https://doc-snapshots.qt.io/qtforpython/index.html )
3 changes: 2 additions & 1 deletion Lesson_2.使用QtDesigner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,5 @@ class MainWindow(QMainWindow):
```
代码很简单,切记文件名和类名要对应。其他简单的功能实现部分相差不多,具体请参照main.py。
到此,使用PySide创建用户界面的基本流程你都学会了。但是你会发现,这样生成的窗口很不美观,并且拖动大小后,
内部控件没有变化,和Lesson_1显示截然的不同,显得很不自然。想要更好的设置界面,请看下一课。
内部控件没有变化,和Lesson_1显示截然的不同,显得很不自然。想要更好的设置界面,请看下一课。
* [第三课](../Lesson_3.使用布局管理/README.md)
Binary file not shown.
6 changes: 4 additions & 2 deletions Lesson_3.使用布局管理/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
打开QtDesigner,新建一个空白窗口,在主窗口中放置一个垂直布局,然后在主窗口空白处单击鼠标右键,任意选择一
种布局。此时放置的垂直布局框会布满主窗口。然后在该布局中放置一个Label和一个Push Button,他们会自动上下分布。
(Qt中一般使用Label来显示文字和图像)然后修改Label的文字对齐属性为居中。主程序中,要注意窗口控件所属关系,
否则使用“.”方式调用会出现问题。到此处程序能正常执行的话,你就得到了与Lesson_1相同的窗口。
否则使用“.”方式调用会出现问题。到此处程序能正常执行的话,你就得到了与Lesson_1相同的窗口。
![v_layout](../Addition/Layout.png)
## 布局参数
上面窗口的绘制使用了默认参数,美观的布局依赖于参数的设置。
Expand All @@ -24,4 +24,6 @@ QVBoxLayout,下方出现属性编辑器。
当前是QVBoxLayout,因此只考虑垂直比例,如果我们将比例设置为1:1,
即将label的“垂直伸展”和pushButton的“垂直伸展”都设置为1,那么在窗口变化中,上下两个控件垂直高度会一样。
(当使用动态布局,切记分布策略选择“preferred")
![v_layout_size11](../Addition/Layout_Size11.png)
![v_layout_size11](../Addition/Layout_Size11.png)

* [第四课](../Lesson_4.使用QSS美化界面/README.md)
Binary file not shown.
3 changes: 2 additions & 1 deletion Lesson_4.使用QSS美化界面/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ QStatusBar
当某个控件是QWidget的继承类时,可以使用QWidget#[名称]来替代(例如Label)。具体细则请网络查找QSS,
有非常详细的介绍。
## 提醒
本次课程所参考的程序,只是示范如何使用QSS,配色完全是随手选取,请见谅。
本次课程所参考的程序,只是示范如何使用QSS,配色完全是随手选取,请见谅。
* [第五课](../Lesson_5.结合OpenCV实现视频播放器/README.md)
3 changes: 2 additions & 1 deletion Lesson_5.结合OpenCV实现视频播放器/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@
1. 为了循环的播放一帧一帧的图像,使用了QTimer(定时器),让他定时循环溢出,
然后将溢出信号与显示一帧图像的槽程序连接。定时器的循环时间为1000/FPS,单位为毫秒。
2. 为了实现快进,快退等功能,使用了槽连接的连接与断开,让大家更容易理解如何使用槽。
3. 在Qt中显示Mat格式的图像(OpenCV的图像格式),需要相应的转换。
3. 在Qt中显示Mat格式的图像(OpenCV的图像格式),需要相应的转换。
* [第六课](../Lesson_6.另一种槽连接机制/readme.md)
Binary file not shown.
60 changes: 60 additions & 0 deletions Lesson_6.另一种槽连接机制/Slot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# -*- coding:utf-8 -*-
"""
@Author: Fei Xue
@E-Mail: [email protected]
@File: Slot.py
@Time: 2020/6/11 15:41
@Introduction: 另一种槽机制
"""

import sys
import random
from PySide2 import QtWidgets, QtCore


class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()

self.hello = ["Hallo Welt", "Hei maailma", "Hola Mundo", "Привет мир", "Hello world"]
self.resize(400, 300)
self.setWindowTitle('Slot')

# --- 布局和控件 ---#

# 中心控件
self.center_widget = QtWidgets.QWidget()
# 中心控件布局
self.center_widget_layout = QtWidgets.QVBoxLayout()
# 标签
self.show_word = QtWidgets.QLabel('Hello world')
# 设置标签居中
self.show_word.setAlignment(QtCore.Qt.AlignCenter)
# 按钮
self.push_word = QtWidgets.QPushButton('Random word')
# 设置按钮ObjectName,使用connectSlotsByName必须设定
self.push_word.setObjectName('push_word')
# 将标签添加到布局里
self.center_widget_layout.addWidget(self.show_word)
# 将按钮添加到布局里
self.center_widget_layout.addWidget(self.push_word)
# 将布放置到中心控件上
self.center_widget.setLayout(self.center_widget_layout)
# 将中心控件放置到主窗口内
self.setCentralWidget(self.center_widget)

# 设置通过ObjectName来连接槽函数
QtCore.QMetaObject.connectSlotsByName(self)

# 指定下面的函数是槽函数
@QtCore.Slot()
# on_ObjectName_信号 来定义槽函数名
def on_push_word_clicked(self):
self.show_word.setText(random.choice(self.hello))


if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
54 changes: 54 additions & 0 deletions Lesson_6.另一种槽连接机制/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# 信号与槽连接

PyQt5或者PySide2中提供了两种槽连接方式,它们各有优点。

### 1. 通过connect方式连接

* 优点:槽函数复用,可以传参
* 缺点:代码繁琐,冗余
* 示例:

```python
# 定义槽函数
def pushButton_slot_fun(self, x):
print(x)

# 定义控件
push_word = QtWidgets.QPushButton('Random word')
# 槽连接
push_word.clicked.connect(lambda: pushButton_slot_fun('参数'))
```

### 2. 通过connectSlotsByName方式连接

* 优点:代码整洁
* 缺点:不能传参(可能是我不会,网友有会的可以提Issue)
* 示例:

```python
# 定义控件
push_word = QtWidgets.QPushButton('Random word')
# 必须设置控件的名称,即ObjectName
push_word.setObjectName('push_word')

# parent为发出槽信号的控件的parent,如是当前窗口的控件发出信号,这里填self
# 这句话必须在所有setObjectName之后才会生效
QtCore.QMetaObject.connectSlotsByName(parent)

# 用@QtCore.Slot()声明下面是槽函数
@QtCore.Slot()
# 槽函数名的格式为:on_[ObjectName]_[信号]
def on_push_word_clicked():
pass
```

### 最后
* 之前的代码都用【designer生成+py脚本调用】的方式,认为这种方式编程快速。
在我真正部署了大项目之后,才发现完全键入的代码才更有生命力。增删改除控件在
两步走的方式中存在很大问题,而实践中这些动作是必不可少的。
* 说明一下我的代码方式。首先写出框架和基本控件,如果哪个控件的某个熟悉怎么
设置不知道,我会打开designer然后随便放置一个去查看,然后尝试使用set等命令。
如果上述方法不通,我还会打开[Qt文档](https://doc.qt.io/qtforpython/modules.html)
去查看控件的方法,函数,信号,例子。
* 之后的代码将不再使用两步走的方案,我会提供一个快捷方便的函数来构建布局。
* 下一节([第七课](../Lesson_7.主窗口的构成/readme.md))会介绍Qt主窗口的构成。
17 changes: 17 additions & 0 deletions Lesson_7.主窗口的构成/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# 主窗口构成
![mainwindow](../Addition/mainwindow.png)
![maindock](../Addition/mainwindow_dock.png)

* 上图是窗口初始化截图,下图是将dock控件浮动后的截图。
* 从上例分析得知主窗口构成:窗口从上往下由菜单栏,中心区域和状态栏构成。

### 中心区域
* 中心区域可以任意布置控件的区域,主要由中心控件,dock窗口,工具栏组成。
* 之前使用QtDesigner的例子,当新建一个窗口时,相当于创建一个窗口包含菜单栏,
中心区域和状态栏,然后在中心区域放入一个中心控件。我们的操作都是在这个中心
控件上部署的。
* 只有主窗口可以添加中心控件,工具栏和dock控件。

### 最后
* 熟悉掌握窗口的结构,以后控件部署会有条不紊。
* 下一讲([第八课]())会介绍多窗口的继承和嵌套。
96 changes: 96 additions & 0 deletions Lesson_7.主窗口的构成/struct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# -*- coding:utf-8 -*-
"""
@Author: Fei Xue
@E-Mail: [email protected]
@File: struct.py.py
@Time: 2020/6/11 16:58
@Introduction:
"""


import sys
import random
from PySide2 import QtWidgets, QtCore


class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()

self.hello = ["Hallo Welt", "Hei maailma", "Hola Mundo", "Привет мир", "Hello world"]
self.resize(1024, 768)
self.setWindowTitle('Main window struct')

# --- 布局和控件 ---#

# 中心控件
self.center_widget = QtWidgets.QWidget()
self.center_widget.setStyleSheet('*{background: Gold; color: Black}')
# 中心控件布局
self.center_widget_layout = QtWidgets.QVBoxLayout()
# 标签
self.show_word = QtWidgets.QLabel('这是放在中心控件布局中的标签')
# 设置标签居中
self.show_word.setAlignment(QtCore.Qt.AlignCenter)
# 将标签添加到布局里
self.center_widget_layout.addWidget(self.show_word)
# 将布放置到中心控件上
self.center_widget.setLayout(self.center_widget_layout)

# Dock窗口1
self.dock = QtWidgets.QDockWidget('这是Dock1的标题')
self.dock_container = QtWidgets.QWidget()
self.dock_layout = QtWidgets.QVBoxLayout()
self.dock_label = QtWidgets.QLabel('这是放在Dock1中的标签')
self.dock_layout.addWidget(self.dock_label)
self.dock_container.setLayout(self.dock_layout)
self.dock.setWidget(self.dock_container)

# Dock窗口2
self.dock2 = QtWidgets.QDockWidget('这是Dock2的标题')
self.dock2_container = QtWidgets.QWidget()
self.dock2_layout = QtWidgets.QVBoxLayout()
self.dock2_label = QtWidgets.QLabel('这是放在Dock2中的标签')
self.dock2_layout.addWidget(self.dock2_label)
self.dock2_container.setLayout(self.dock2_layout)
self.dock2.setWidget(self.dock2_container)

# 设置工具栏
self.toolBar_top = QtWidgets.QToolBar()
self.tool_top = QtWidgets.QLabel('这是放在工具栏中的一个标签')
self.toolBar_top.addWidget(self.tool_top)

# 将中心控件放置到主窗口内
self.setCentralWidget(self.center_widget)
# 将Dock控件放置到主窗口内
self.addDockWidget(QtCore.Qt.RightDockWidgetArea, self.dock)
self.addDockWidget(QtCore.Qt.LeftDockWidgetArea, self.dock2)
# 将工具栏控件放置到主窗口内
self.addToolBar(self.toolBar_top)

# 设置状态栏永久显示信息
self.statusBar_Permanent = QtWidgets.QLabel('这是放在状态栏中的永久标签')
self.statusBar().addPermanentWidget(self.statusBar_Permanent)
self.statusBar().setStyleSheet('*{background: Aqua; color: Black}')

# 设置菜单栏
self.menu_setup = QtWidgets.QMenu('这是菜单栏中的一个菜单')
self.menuBar().addMenu(self.menu_setup)
self.menuBar().setStyleSheet('*{background: Aqua; color: Black}')


# 设置通过ObjectName来连接槽函数
QtCore.QMetaObject.connectSlotsByName(self)

# 指定下面的函数是槽函数
@QtCore.Slot()
# on_ObjectName_信号 来定义槽函数名
def on_push_word_clicked(self):
self.show_word.setText(random.choice(self.hello))


if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# 简介
Qt是一种强大的图形用户界面构造工具,如今它对于Python也有很好的接口支持,分别是PyQt和PySide。PyQt采用需购买版权的
商业及GPL许可,而PySide采用无需购买版权的LGPL许可。PySide与PyQt有非常相容的API,因此无需版权的PySide更适合广大
Python爱好者的学习。PySide2支持Qt5框架,兼容Python2.7以上版本及Python3.5 以上版本。本教程以PySide2为例,讲述如何从
显示一个简单的hello world窗口到设置井然有序窗口布局。介于作者时间有限,此教程只讲述如何入门并高效使用Qt,至于每个
控件如何使用,各位爱好者自己学习吧,网络上各种资源一大把。俗话说,师傅领进门,修行靠个人,我的每个教程都有详细的代码
供大家参考,有问题可以直接在github上提出,共同进步!
* Qt是一种强大的图形用户界面构造工具,如今它对于Python也有很好的接口支持,
分别是PyQt和PySide。PyQt采用需购买版权的商业及GPL许可,而PySide采用无需
购买版权的LGPL许可。PySide与PyQt有非常相容的API,因此无需版权的PySide更
适合广大Python爱好者的学习。PySide2支持Qt5框架,兼容Python2.7以上版本及
Python3.5以上版本。本教程以PySide2为例,讲述如何从显示一个简单的
hello world窗口到设置井然有序窗口布局。介于作者时间有限,此教程只讲述如何
入门并高效使用Qt,至于每个控件如何使用,各位爱好者自己学习吧,网络上各种资
源一大把。俗话说,师傅领进门,修行靠个人,我的每个教程都有详细的代码供大家
参考,有问题可以直接在github上提出,共同进步!
* 开始[第一课](Lesson_1.环境配置与入门/README.md)
# 致谢
感谢1ZLab对作者的支持!

0 comments on commit ebd4b61

Please sign in to comment.