PyQt5保姆级教程-- 从入门到精通
Posted 今晚务必早点睡
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PyQt5保姆级教程-- 从入门到精通相关的知识,希望对你有一定的参考价值。
PyQt5保姆级教程-- 从入门到精通
主要内容:
1 | Qt Designer |
---|---|
2 | PyQt5基本窗口控件(QMainWindow、Qwidget、Qlabel、QLineEdit、菜单、工具栏等) |
3 | PyQt5高级组件(QTableView、QListView、容器、线程等) |
4 | PyQt5布局管理(QBoxLayout、QGirdLayout、QFormLayout、嵌套布局等) |
5 | PyQt5信号与槽(事件处理、数据传递等) |
6 | PyQt5图形与特效(定制窗口风格、绘图、QSS与UI美化、不规则窗口、设置样式等) |
7 | PyQt5扩展应用(制作PyQt5安装程序、数据处理、第三方绘图库在PyQt5中的应用、UI自动化测试等) |
搭建PyQt5开发环境
工具:
Python
PyQt5模块
PyCharm
在PyCharm里面安装PyQt5
pip install PyQt5 -i https://pypi.douban.com/simple
在PyCharm里面安装Qt的工具包
pip install PyQt5-tools -i https://pypi.douban.com/simple
在安装tools时,报如下错误:
1.pip install PyQt5-tools安装失败
WARNING: Ignoring invalid distribution -yqt5 (e:\\venvs\\pyqt5_demo1\\lib\\site-packages)
Installing collected packages: pyqt5, click, qt5-tools, pyqt5-plugins, pyqt5-tools
ERROR: Could not install packages due to an OSError: [WinError 5] 拒绝访问。: 'e:\\\\venvs\\\\pyqt5_demo1\\\\Lib\\\\site-packages\\\\PyQt5\\\\QtCore.pyd'
Check the permissions.
解决办法:
第一步:
将pip install ...
加入--user
为pip install --user ...
即可
pip install PyQt5-tools -i https://pypi.douban.com/simple --user
换个思路
重启电脑,继续输入第一条命令安装
原因分析,可能占用了进程。
2.配置Qt Designer
Working directory:$FileDir$
3.配置PyUIC
Program:python的安装目录下的python.exe文件
Arguments:-m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py
4.配置Pyrcc
Program:python的安装目录下的Scripts文件夹的pyrcc5.exe文件
Arguments:$FileName$ -o $FileNameWithoutExtension$_rc.py
展示效果如下:
5.ui转py的过程:
1.点击EXternal Tools里面的QTDesigner,会跳转到QT界面,
拖动组件,调整好界面,保存为first文件,它会默认生成first.ui文件
选中文件,鼠标右击,打开扩展,选择PyUIC,它会生成.py文件
将.ui文件转化为.py文件的命令行方法:
python -m PyQt5.uic.pyuic demo.ui -o demo.py
6.开发第一个基于PyQt5的桌面应用
必须使用两个类: QApplication和QWidget。都在PyQt5.QtWidgets。
第一个类表示应用程序,第二个类表示窗口
输入如下代码:
# 开发第一个基于PyQt5的桌面应用
import sys
from PyQt5.QtWidgets import QApplication,QWidget
if __name__ == '__main__':
# 创建QApplication类的实例
app = QApplication(sys.argv)
# 创建一个窗口
w = QWidget()
# 设置窗口尺寸 宽度300,高度150
w.resize(400,200)
# 移动窗口
w.move(300,300)
# 设置窗口的标题
w.setWindowTitle('第一个基于PyQt5的桌面应用')
# 显示窗口
w.show()
# 进入程序的主循环,并通过exit函数确保主循环安全结束(该释放资源的一定要释放)
sys.exit(app.exec_())
效果如下:
也可以在命令行运行
python 文件名.py
7.基本操作
左侧是可以选择的组件,右侧可以设定属性值,设置完成之后,可以在窗体选择预览,选择查看c++和python代码。
8.在QtDesigner中使用水平布局(Vertical Layout)
两种方式:
(1)先移组件,再布局。
放置五个按钮,让这五个按钮等宽的,水平的排列
(全部选中–>鼠标右键–>布局–>水平布局 预览)
预览:
(2)先布局,再移组件。
生成demo1.ui文件
转成demo2.py文件,转成py文件,才能在程序里面调。
生成的代码如下:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'demo1.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(70, 50, 651, 51))
self.widget.setObjectName("widget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.pushButton = QtWidgets.QPushButton(self.widget)
self.pushButton.setObjectName("pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.pushButton_2 = QtWidgets.QPushButton(self.widget)
self.pushButton_2.setObjectName("pushButton_2")
self.horizontalLayout.addWidget(self.pushButton_2)
self.pushButton_3 = QtWidgets.QPushButton(self.widget)
self.pushButton_3.setObjectName("pushButton_3")
self.horizontalLayout.addWidget(self.pushButton_3)
self.pushButton_4 = QtWidgets.QPushButton(self.widget)
self.pushButton_4.setObjectName("pushButton_4")
self.horizontalLayout.addWidget(self.pushButton_4)
self.widget1 = QtWidgets.QWidget(self.centralwidget)
self.widget1.setGeometry(QtCore.QRect(110, 160, 578, 194))
self.widget1.setObjectName("widget1")
self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget1)
self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout_2.setObjectName("horizontalLayout_2")
self.listView = QtWidgets.QListView(self.widget1)
self.listView.setObjectName("listView")
self.horizontalLayout_2.addWidget(self.listView)
self.pushButton_5 = QtWidgets.QPushButton(self.widget1)
self.pushButton_5.setObjectName("pushButton_5")
self.horizontalLayout_2.addWidget(self.pushButton_5)
self.checkBox = QtWidgets.QCheckBox(self.widget1)
self.checkBox.setObjectName("checkBox")
self.horizontalLayout_2.addWidget(self.checkBox)
self.radioButton = QtWidgets.QRadioButton(self.widget1)
self.radioButton.setObjectName("radioButton")
self.horizontalLayout_2.addWidget(self.radioButton)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "Button1"))
self.pushButton_2.setText(_translate("MainWindow", "Button2"))
self.pushButton_3.setText(_translate("MainWindow", "Button3"))
self.pushButton_4.setText(_translate("MainWindow", "Button4"))
self.pushButton_5.setText(_translate("MainWindow", "PushButton"))
self.checkBox.setText(_translate("MainWindow", "CheckBox"))
self.radioButton.setText(_translate("MainWindow", "RadioButton"))
如何在程序里面调用,先新建一个Run_demo1.py文件
代码如下:
import sys
import demo1
from PyQt5.QtWidgets import QApplication,QMainWindow
if __name__ == '__main__':
# 只有直接运行这个脚本,才会往下执行
# 别的脚本文件执行,不会调用这个条件句
# 实例化,传参
app = QApplication(sys.argv)
# 创建对象
mainWindow = QMainWindow()
# 创建ui,引用demo1文件中的Ui_MainWindow类
ui = demo1.Ui_MainWindow()
# 调用Ui_MainWindow类的setupUi,创建初始组件
ui.setupUi(mainWindow)
# 创建窗口
mainWindow.show()
# 进入程序的主循环,并通过exit函数确保主循环安全结束(该释放资源的一定要释放)
sys.exit(app.exec_())
运行:
弹出如下窗口:
此时出现了一个小问题:
如何解决: (将此目录生成源代码目录)
设置完成之后,等待加载完成,导入文件名底下的红线消失
9.在QtDesigner中使用垂直布局(Horizontal Layout)
和水平布局的操作类似,也有两种布局方式:
(1) 先移动组件,再布局
(2) 先布局,再移动组件
点击保存,生成垂直布局文件demo2.ui
右键demo2.ui,生成demo2.py文件
demo2.py的代码如下:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'demo2.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(180, 150, 441, 371))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.label = QtWidgets.QLabel(self.verticalLayoutWidget)
self.label.setObjectName("label")
self.verticalLayout_2.addWidget(self.label)
self.pushButton_6 = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.pushButton_6.setObjectName("pushButton_6")
self.verticalLayout_2.addWidget(self.pushButton_6)
self.pushButton_5 = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.pushButton_5.setObjectName("pushButton_5")
self.verticalLayout_2.addWidget(self.pushButton_5)
self.pushButton_4 = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.pushButton_4.setObjectName("pushButton_4")
self.verticalLayout_2.addWidget(self.pushButton_4)
self.checkBox = QtWidgets.QCheckBox(self.verticalLayoutWidget)
self.checkBox.setObjectName("checkBox")
self.verticalLayout_2.addWidget(self.checkBox)
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(40, 40, 95, 121))
self.widget.setObjectName("widget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.widget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.pushButton = QtWidgets.QPushButton(self.widget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
self.pushButton_2 = QtWidgets.QPushButton(self.widget)
self.pushButton_2.setObjectName("pushButton_2")
self.verticalLayout.addWidget(self.pushButton_2)
self.pushButton_3 = QtWidgets.QPushButton(self.widget)
self.pushButton_3.setObjectName("pushButton_3")
self.verticalLayout.addWidget(self.pushButton_3)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "TextLabel"))
self.pushButton_6.setText(_translate("MainWindow", "PushButton"))
self.pushButton_5.setText(_translate("MainWindow", "PushButton"))
self.pushButton_4.setText(_translate("MainWindow", "PushButton"))
self.checkBox.setText(_translate("MainWindow", "CheckBox"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
self.pushButton_2.setText(_translate("MainWindow", "PushButton"))
self.pushButton_3.setText(_translate("MainWindow", "PushButton"))
在python程序里面调用,新建Run_demo2.py文件
代码如下:
import sys
import demo2
from PyQt5.QtWidgets import QApplication,QMainWindow
if __name__ == '__main__':
# 只有直接运行这个脚本,才会往下执行
# 别的脚本文件执行,不会调用这个条件句
# 实例化,传参
app = QApplication(sys.argv)
# 创建对象
mainWindow = QMainWindow()
# 创建ui,引用demo1文件中的Ui_MainWindow类
ui = demo2.Ui_MainWindow()
# 调用Ui_MainWindow类的setupUi,创建初始组件
ui.setupUi(mainWindow)
# 创建窗口
mainWindow.show()
# 进入程序的主循环,并通过exit函数确保主循环安全结束(该释放资源的一定要释放)
sys.exit(app.exec_())
运行程序:
10.在QtDesigner里面同时创建垂直布局和水平布局
新建一个 main window,点击 创建
在布局的时候,windows里面,可以通过ctrl+上下左右进行微调。
文件保存,命名为demo3.ui文件,同样用拓展工具,生成demo3.py文件。
同样,新建运行文件Run_demo3.py文件,代码如下:
import sys
import demo3
from PyQt5.QtWidgets import QApplication,QMainWindow
if __name__ == '__main__':
# 只有直接运行这个脚本,才会往下执行
# 别的脚本文件执行,不会调用这个条件句
# 实例化,传参
app = QApplication(sys.argv)
# 创建对象
mainWindow = QMainWindow()
# 创建ui,引用demo1文件中的Ui_MainWindow类
ui = demo3.Ui_MainWindow()
# 调用Ui_MainWindow类的setupUi,创建初始组件
ui.setupUi(mainWindow)
# 创建窗口
mainWindow.show()
# 进入程序的主循环,并通过exit函数确保主循环安全结束(该释放资源的一定要释放)
sys.exit(app.exec_())
运行代码,结果如下:
11.在QtDesigner中同时使用栅格布局(Grid Layout)
拖放四个按钮之后,选中栅格布局
选中之后,效果如下:
拖拽边角,可以放大:
练习:利用栅格布局实现计算器数字区域
拖动button键调整好位置,全选之后选中布局,再选栅格布局
点击栅格之后,效果如下:
保存,生成demo4.ui文件
同样进行上述操作,转成demo4.py文件,新建Run_demo4.py文件,代码如下:
import sys
import demo4
from PyQt5.QtWidgets import QApplication,QMainWindow
if __name__ == '__main__':
# 只有直接运行这个脚本,才会往下执行
# 别的脚本文件执行,不会调用这个条件句
# 实例化,传参
app = QApplication(sys.argv)
# 创建对象
mainWindow = QMainWindow()
# 创建ui,引用demo1文件中的Ui_MainWindow类
ui = demo4.Ui_MainWindow()
# 调用Ui_MainWindow类的setupUi,创建初始组件
ui.setupUi(mainWindow)
# 创建窗口
mainWindow.show()
# 进入程序的主循环,并通过exit函数确保主循环安全结束(该释放资源的一定要释放)
sys.exit(app.exec_())
效果如下:
栅格布局的注意点:摆放控件要尽可能的整齐,这样系统才会正确的识别。
栅格布局和水平布局,垂直布局一样,可以后期添加控件。
12.向栅格布局中拖动控件
13.在QtDesigner中使用表单布局(Form Layout)
新建一个 main window,点击 创建
选择需要的控件,进行如下操作:
调整好布局,保存文件为demo5.ui
利用pyUIC插件,生成python代码调试
创建Run_demo5.py文件,执行代码如下:
import sys
import demo5
from PyQt5.QtWidgets import QApplication,QMainWindow
if __name__ == '__main__':
# 只有直接运行这个脚本,才会往下执行
# 别的脚本文件执行,不会调用这个条件句
# 实例化,传参
app = QApplication(sys.argv)
# 创建对象
mainWindow = QMainWindow()
# 创建ui,引用demo1文件中的Ui_MainWindow类
ui = demo5.Ui_MainWindow()
# 调用Ui_MainWindow类的setupUi,创建初始组件
ui.setupUi(mainWindow)
# 创建窗口
mainWindow.show()
# 进入程序的主循环,并通过exit函数确保主循环安全结束(该释放资源的一定要释放)
sys.exit(app.exec_())
效果如下:
14.在容器中完成布局
跟上面一样,新建一个MainWindow,添加对应的组件,鼠标右键点击,变形为对应的容器。
同理,生成demo6.py文件,新建Run_demo6文档,添加代码
import sys
import demo6
from PyQt5.QtWidgets import QApplication,QMainWindow
if __name__ == '__main__':
# 只有直接运行这个脚本,才会往下执行
# 别的脚本文件执行,不会调用这个条件句
# 实例化,传参
app = QApplication(sys.argv)
# 创建对象
mainWindow = QMainWindow()
# 创建ui,引用demo1文件中的Ui_MainWindow类
ui = demo6.Ui_MainWindow()
# 调用Ui_MainWindow类的setupUi,创建初始组件
ui.setupUi(mainWindow)
# 创建窗口
mainWindow.show()
# 进入程序的主循环,并通过exit函数确保主循环安全结束(该释放资源的一定要释放)
sys.exit(app.exec_())
运行程序
15.在QtDesigner中使用绝对布局
跟上面一样,新建一个MainWindow,添加对应的组件,
同理,生成demo7.py文件,新建Run_demo7文档,添加代码(代码如上,略作修改),PyCharm里运行如下:
15.在QtDesigner中使用分割线与间隔
跟上面一样,新建一个MainWindow,
新建4个按钮,设置水平间隔,新建3个按钮,设置垂直间隔
在A2和A3之间设立分割线,在B2和B3之间设立分割线
保存文件为demo8.ui ,转为demo8.py代码,新建Run_demo8.py,添加代码(代码如上,略作修改),PyCharm里运行如下:
16.布局的最大尺寸和最小尺寸
默认状态下,它的尺寸可以自由调节,跟上面一样,新建一个MainWindow,
可以看到,原本这个bushButton控件最小宽高可以到0,最大宽高可以到1677215
通过改变右侧栏的值,就可以设置它不小于多少,不大于多少。
16.尺寸策略(sizePolicy)
对于大多数控件来说,sizeHint(期望尺寸)是只可读的,也就是说,你布局的时候不管拖拽多大,最后输出的还是默认值
读取pushButton的期望尺寸:
self.pushButton.sizeHint().width()
self.pushButton.sizeHint().height()
即可以看到,一个pushButton的期望尺寸,宽是41,高度是28
在demo7里进行上面操作,还是得到一样的数值。
同理,也可以进行读取其他控件的操作,比如读取textBrowser的宽高,代码如下:
self.c.sizeHint().width()
self.textBrowser.sizeHint().height()
效果如下:
即可以看到:控件textBrowser的默认宽高分别为256和192。
同样,也可以看最小的期望尺寸,以pushButton为例,其代码如下:
self.pushButton.minimumSizeHint().width()
self.pushButton.minimumSizeHint().height()
还是以demo7.py测试
可以看到,对于大部分控件来说,它的期望尺寸和最小期望尺寸是一样的
为何使用尺寸策略:
就是因为拓展的组件无论如何拖拽大小,经过布局设置之后,会回到默认的大小,为了让布局更有个性,采用尺寸策略,可以改变组件的期望尺寸。如图:
练习,左侧放树,构造分栏效果
保存文档为demo9.ui,转为demo9.py代码,新建Run_demo9.py,添加代码(代码如上,略作修改),PyCharm里运行如下:
17.在QtDesigner里面设置控件之间的伙伴关系
即控件关联之后,可以通过一个控件来控制另外一个控件
新建一个MainWindow,布局如下,保存为demo10.ui
接着:
如上图所示,水平布局后面的“H”为热键 ,Ctrl +1 为快捷键
垂直布局后面的“V”为热键 ,Ctrl +2 为快捷键
热键:只有在这个菜单显示时,按“H”时,才会起作用。菜单关闭时,按“H”不起作用。“V”同理。
然后给demo10.ui文件的lable添加热键:
给姓名添加热键成:姓名(&A):
给年龄添加热键成:年龄(&B):
给邮箱添加热键成:邮箱(&C):
然后打开编辑伙伴,按住鼠标左键,选中lable指向Line Edit
然后选择编辑窗口部件,会切回到正常的部件
保存文件为demo10.ui ,转为demo10.py代码,新建Run_demo10.py,添加代码(代码如上,略作修改),PyCharm里运行如下:
再添加三个lable试一下效果,删除掉原来的demo10.py文件,用新保存的demo10.ui去生成新的demo10.py文件,点击运行查看效果
果然,按住alt+a,alt+b,alt+c,alt+d,alt+e.alt+f分别在右边对应的的Line Edit里面有焦点光标。
拓展:
18.如何修改控件的Tab顺序
新建一个MainWindow,布局如下,在Edit里面,选中 编辑 Tab顺序,在控件前端就会出现序号,这个序号就是顺序
也可以选中从这里开始或者重新开始,依次点击形成顺序。
接下来选中统一的 Line Edit来演示
保存文档为demo11.ui,转为demo11.py代码,新建Run_demo11.py,添加代码(代码如上,略作修改),PyCharm里运行如下:
按Tab 键,焦点光标就会按照指定的顺序在Line Edit内跳转
19.在QtDesigner中完成信号与槽的设置
信号(signal)与槽(slot)是Qt的核心机制,由于PyQt忠实的继承了Qt的所有特性,所有信号与槽也是PyQt的核心机制。
信号:是由对象或控件发射出去的消息。可以理解为按钮的单击事件。
当单击按钮时,按钮就会向外部发送单击的消息,这些发送出去的信号需要一些代码来拦截,这些代码就是槽
槽本质上是一个函数或者方法,信号可以理解为事件,槽可以理解为事件函数
信号与槽的设置:就是需要将信号和槽绑定
一个信号可以和多个槽绑定,一个槽可以拦截多个信号。
信号和槽绑定有两种方式,一种是用QtDesigner进行绑定,一种是在代码中进行绑定
(1)用QtDesigner进行信号和槽绑定
需求:单机按钮,关闭窗口
新建一个MainWindow,拖拽一个pashButton按钮,修改文本为“关闭窗口”
在Edit里选择编辑信号/槽,点击pashButton按钮向外拖拽,
在Edit里选择编辑信号/槽,点击pashButton按钮向外拖拽,松开鼠标,左栏选择clicked(),勾选左下角“显示从QWidget”继承信号和槽,右栏选择close(),然后点击右下角ok.
在Edit里面选择“编辑窗口部件”,对布局页面进行恢复。
在“窗体”里选择“预览于”,选择“Windows风格”
此时点击页面的“关闭窗口”,则页面就会关闭
练习
添加两个CheckBox进行如下操作:
给第一个CheckBox进行信号与槽的绑定
给第二个CheckBox进行信号与槽的绑定
在Edit里面选择"编辑窗口部件"进行恢复主窗口
恢复完成后,窗口如下:
预览效果如下:
取消勾选check box的选项,下面的line Edit视角效果也会相应的变换。
保存文档为demo12.ui,转为demo12.py代码,新建Run_demo12.py,添加代码(代码如上,略作修改),PyCharm里运行如下:
拓展:
(2)用代码完成关闭主窗口
见第23节
20 在QtDesigner中为窗口添加菜单和工具栏
一个窗口,应该拥有菜单栏,工具栏,状态栏
新建一个MainWindow,添加菜单栏,添加完成之后,也可以右键点击,选择移除,同理添加工具栏。
给菜单栏添加内容:
在”窗体“里选择预览,效果如下:
在菜单和工具条里面如何添加按钮?
不管是菜单还是工具条的按钮,是一个action的动作,添加步骤如下:
在"视图"里,选择动作编辑器
两个菜单自动生成两个动作,双击可用设置动作
点击"ok"之后,主窗口变化如下:
保存文档为demo13.ui,转为demo13.py代码,新建Run_demo13.py,添加代码(代码如上,略作修改),PyCharm里运行如下:
21 创建主窗口
主窗口类型,有三种窗口
窗口类型 | 说明 |
---|---|
QMainWindow | 可以包含菜单栏、工具栏、状态栏和标题栏,是最常见的窗口形式 |
QDialog | 是对话窗口的基类。没有菜单栏、工具栏、状态栏 |
QWidget | 不确定窗口的用途,就使用QWidget |
如下图所示,新建一个controls文件夹,在controls里面新建images文件夹用来装图片,在controls里面新建
FirstMainWin.py文件。
在FirstMainWin.py文件中,添加代码如下:
# 第一个主窗口
# 把所有和UI有关的代码都放在一个类里面,创建窗口只要创建类的实例就可以了
import sys
# 从PyQt里面创建窗口和应用
from PyQt5.QtWidgets import QMainWindow,QApplication
# 用来添加图标
from PyQt5.QtGui import QIcon
# 定义一个类,这个类从QMainWindow里面继承
class FristMainWin(QMainWindow):
# 初始化
def __init__(self,parent=None):
super(FristMainWin,self).__init__(parent)
# 设置主窗口的标题13 万字 C 语言从入门到精通保姆级教程2021 年版 (建议收藏)
友情提示:先关注收藏,再查看,13 万字保姆级 C 语言从入门到精通教程。
文章目录
- 计算机常识
- 什么是计算机程序 ?
- 什么是计算机语言 ?
- 常见的计算机语言类型有哪些 ?
- 什么是C语言?
- C语言历史
- C语言标准
- C语言现状
- 为什么要学习C语言?
- 如何学好C语言
- 工欲善其事必先利其器
- 编写C语言程序用什么工具 ?
- 什么是Qt Creator ?
- Qt Creator安装
- 什么是环境变量?
- 为什么要配置系统变量,不配置用户变量
- Qt Creator快捷键
- 如何创建C语言程序
- 如何创建C语言文件
- C语言程序组成
- 函数定义格式
- 如何执行定义好的函数
- 如何运行编写好的程序
- main函数注意点及其它写法
- C语言程序练习
- 初学者如何避免程序出现BUG
- 多语言对比
- 什么是注释?
- 为什么要使用注释?
- 注释的分类
- 注释的注意点
- 注释的应用场景
- 使用注释的好处
- 什么是关键字?
- 关键字分类
- 什么是标识符?
- 标识符命名规则
- 练习
- 标识符命名规范
- 什么是数据?
- 数据分类
- C语言数据类型
- 什么是常量?
- 常量的类型
- 什么是变量?
- 如何定义变量
- 如何使用变量?
- 变量的初始化
- 如何修改变量值?
- 变量之间的值传递
- 如何查看变量的值?
- 变量的作用域
- 变量内存分析(简单版)
- printf函数
- Scanf函数
- scanf运行原理
- putchar和getchar
- 运算符基本概念
- 运算符分类
- 运算符的优先级和结合性
- 算数运算符
- 赋值运算符
- 自增自减运算符
- sizeof运算符
- 逗号运算符
- 关系运算符
- 逻辑运算符
- 三目运算符
- 类型转换
- 阶段练习
- 流程控制基本概念
- 选择结构
- 选择结构switch
- 循环结构
- 循环结构while
- 循环结构do while
- 循环结构for
- 四大跳转
- 循环的嵌套
- 图形打印
- 函数基本概念
- 函数的分类
- 函数的定义
- 函数的参数和返回值
- 函数的声明
- main函数分析
- 递归函数(了解)
- 进制基本概念
- 进制转换
- 十进制小数转换为二进制小数
- 二进制小数转换为十进制小数
- 原码反码补码
- 位运算符
- 变量内存分析
- char类型内存存储细节
- 类型说明符
- short和long
- signed和unsigned
- 数组的基本概念
- 定义数组
- 初始化数组
- 数组的使用
- 数组的遍历
- 数组长度计算方法
- 练习
- 数组内部存储细节
- 数组的越界问题
- 数组注意事项
- 数组和函数
- 数组元素作为函数参数
- 数组名作为函数参数
- 数组名作函数参数的注意点
- 计数排序(Counting Sort)
- 选择排序
- 冒泡排序
- 插入排序
- 希尔排序
- 折半查找
- 进制转换(查表法)
- 二维数组
- 二维数组的定义
- 二维数组的初始化
- 二维数组的应用场景
- 二维数组的遍历和存储
- 二维数组的遍历
- 二维数组的存储
- 二维数组与函数
- 二维数组作为函数参数注意点
- 作业
- 字符串的基本概念
- 字符串的初始化
- 字符串输出
- 字符串常用方法
- 练习
- 字符串数组基本概念
- 指针基本概念
- 什么是指针
- 什么是指针变量
- 定义指针变量的格式
- 指针变量的初始化方法
- 访问指针所指向的存储空间
- 指针类型
- 二级指针
- 练习
- 指针访问数组元素
- 指针与字符串
- 指向函数指针
- 什么是结构体
- 定义结构体类型
- 定义结构体变量
- 结构体成员访问
- 结构体变量的初始化
- 结构体类型作用域
- 结构体数组
- 结构体指针
- 结构体内存分析
- 结构体变量占用存储空间大小
- 结构体嵌套定义
- 结构体和函数
- 共用体
- 枚举
- 全局变量和局部变量
- auto和register关键字
- static关键字
- extern关键字
- static与extern对函数的作用
- Qt Creator编译过程做了什么?
- 计算机是运算过程分析
- 预处理指令
- 预处理指令的概念
- 宏定义
- 带参数的宏定义
- 条件编译
- typedef关键字
- 宏定义与函数以及typedef区别
- const关键字
- 如何使用const?
- 内存管理
- 进程空间
- 栈内存(Stack)
- 堆内存(Heap)
- malloc函数
- free函数
- calloc函数
- realloc函数
- 链表
- 静态链表
- 动态链表
- 动态链表头插法
- 动态链表尾插法
- 动态链优化
- 链表销毁
- 链表长度计算
- 链表查找
- 链表删除
- 作业
- 文件基本概念
- 文件的打开和关闭
- 一次读写一个字符
- 一次读写一行字符
- 一次读写一块数据
- 读写结构体
- 其它文件操作函数
计算机常识
-
什么是计算机 ?
- 顾名思义,就是能够进行数据运算的机器(台式电脑、笔记本电脑、平板电脑、智能手机)
- 计算机_百度百科
-
计算机的发明者是谁 ?
- 关于电子计算机的发明者是谁这一问题,有好几种答案:
- 1936年***英国数学家图灵***首先提出了一种以程序和输入数据相互作用产生输出的计算机***构想***,后人将这种机器命名为通用图灵计算机
- 1938年***克兰德·楚泽***发明了首台采用***继电器***进行工作的计算机,这台计算机命名为***Z1***,但是继电器是机械式的,并不是完全的电子器材
- 1942年***阿坦那索夫和贝利***发明了首台采用***真空管***的计算机,这台计算机命名为***ABC***
- 1946年ENIAC诞生,它拥有了今天计算机的主要结构和功能,是通用计算机
- 现在世界上***公认***的第一台现代电子计算机是1946年在美国宾夕法尼亚大学诞生的ENIAC(Electronic Numerical Integrator And Calculator)
- 计算机特点是什么 ?
-
计算机是一种电器, 所以计算机只能识别两种状态, 一种是通电一种是断电
-
正是因为如此, 最初ENIAC的程序是由很多开关和连接电线来完成的。但是这样导致***改动一次程序要花很长时间***(需要人工重新设置很多开关的状态和连接线)
-
-
为了提高效率,工程师们想能不能把程序和数据都放在存储器中, 数学家冯·诺依曼将这个思想以数学语言系统阐述,提出了存储程序计算机模型(这是所谓的冯·诺依曼机)
-
那利用数学语言如何表示计算机能够识别的通电和断电两种状态呢?
- 非常简单用0和1表示即可
- 所以计算机能识别的所有指令都是由0和1组成的
- 所以计算机中存储和操作的数据也都是由0和1组成的
0和1更准确的是应该是高电平和低电平, 但是这个不用了解, 只需要知道计算机只能识别0和1以及存储的数据都是由0和1组成的即可。
什么是计算机程序 ?
-
计算机程序是为了告诉计算机"做某件事或解决某个问题"而用"***计算机语言***编写的命令集合(语句)
-
只要让计算机执行这个程序,计算机就会自动地、有条不紊地进行工作,计算机的一切操作都是由程序控制的,离开程序,计算机将一事无成
-
现实生活中你如何告诉别人如何做某件事或者解决某个问题?
- 通过人能听懂的语言: 张三你去楼下帮我买一包烟, 然后顺便到快递箱把我的快递也带上来
- 其实我们通过人能听懂的语言告诉别人做某件事就是在发送一条条的指令
- 计算机中也一样, 我们可以通过计算机语言告诉计算机我们想做什么, 每做一件事情就是一条指令, 一条或多条指令的集合我们就称之为一个计算机程序
什么是计算机语言 ?
- 在日常生活、工作中, 语言是人们交流的工具
- 中国人和中国人交流,使用中文语言
- 美国人和美国人交流,使用英文语言
- 人想要和计算机交流,使用计算机语言
- 可以看出在日常生活、工作中,人们使用的语言种类很多
- 如果一个很牛人可能同时掌握了中文语言和英文语言, 那么想要和这个人交流既可以使用中文语言,也可以使用英文语言
- 计算机其实就是一个很牛的人, 计算机同时掌握了几十门甚至上百门语言, 所以我们只要使用任何一种计算机已经掌握的语言就可以和计算机交流
常见的计算机语言类型有哪些 ?
- 机器语言
- 所有的代码里面只有0和1, 0表示不加电,1表示加电(纸带存储时 1有孔,0没孔)
- 优点:直接对硬件产生作用,程序的执行效率非常非常高
- 缺点:指令又多又难记、可读性差、无可移植性
- 汇编语言
- 符号化的机器语言,用一个符号(英文单词、数字)来代表一条机器指令
- 优点:直接对硬件产生作用,程序的执行效率非常高、可读性稍好
- 缺点:符号非常多和难记、无可移植性
- 高级语言
- 非常接近自然语言的高级语言,语法和结构类似于普通英文
- 优点:简单、易用、易于理解、远离对硬件的直接操作、有可移植性
- 缺点:有些高级语言写出的程序执行效率并不高
- 对比(利用3种类型语言编写1+1)
- 机器语言
10111000 00000001 00000000 00000101 00000001 00000000
- 汇编语言
MOV AX, 1 ADD AX, 1
- 高级语言
1 + 1
什么是C语言?
- C语言是一种用于和计算机交流的高级语言, 它既具有高级语言的特点,又具有汇编语言的特点
- 非常接近自然语言
- 程序的执行效率非常高
- C语言是所有编程语言中的经典,很多高级语言都是从C语言中衍生出来的,
- 例如:C++、C#、Object-C、Java、Go等等
- C语言是所有编程语言中的经典,很多著名的系统软件也是C语言编写的
- 几乎所有的操作系统都是用C语言编写的
- 几乎所有的计算机底层软件都是用C语言编写的
- 几乎所有的编辑器都是C语言编写的
C语言历史
- 最早的高级语言:FORTRAN–>ALGOL–>CPL–>BCPL–>C–>C++等
“初,世间无语言,仅电路与连线。及大牛出,天地开,始有 FORTRAN、 LISP、ALGOL 随之, 乃有万种语”
- 1963年英国剑桥大学推出了CPL(Combined Programming Langurage)语言。 CPL语言在ALGOL 60的基础上接近硬件一些,但规模比较大,难以实现
- 1967年英国剑桥大学的 Matin Richards(理查兹)对CPL语言做了简化,推出了 BCPL (Base Combined Programming Langurage)语言
- 1970年美国贝尔实验室的 Ken Thompson(肯·汤普逊) 以 BCPL 语言为基础,又作了进一步的简化,设计出了很简单的而且很接近硬件的 B 语言(取BCPL的第一个字母),并用B语言写出了第一个 UNIX 操作系统。但B语言过于简单,功能有限
- 1972年至1973年间,贝尔实验室的 Dennis.Ritchie(丹尼斯·里奇) 在 B语言的基础上设计出了C语言(取BCPL的第二个字母)。C语言即保持 BCPL 语言和B语言的优点(精练、接近硬件),又克服了他们的缺点(过于简单,数据无类型等)
C语言标准
- 1983年美国国家标准局(American National Standards Institute,简称ANSI)成立了一个委员会,开始制定C语言标准的工作
- 1989年C语言标准被批准,这个版本的C语言标准通常被称为ANSI C(C89)
- 1999年,国际标准化组织ISO又对C语言标准进行修订,在基本保留原C语言特征的基础上,针对应该的需要,增加了一些功能,命名为***C99***
- 2011年12月,ANSI采纳了ISO/IEC 9899:2011标准。这个标准通常即***C11,它是C程序语言的现行标准***
C语言现状
- 年度编程语言
- 该奖项颁发给了一年中最热门的编程语言
- 编程语言排行榜查看
为什么要学习C语言?
- 40多年经久不衰
- 了解操作系统、编译原理、数据结构与算法等知识的最佳语言
- 了解其它语言底层实现原理必备语言
- 基础语法与其它高级语言类似,学会C语言之后再学习其它语言事半功倍,且知根知底
当你想了解底层原理时,你才会发现后悔当初没有学习C语言
当你想学习一门新的语言时, 你才会发现后悔当初没有学习C语言
当你使用一些高级框架、甚至系统框架时发现提供的API都是C语言编写的, 你才发现后悔当初没有学习C语言
学好数理化,走遍天下都不拍
学好C语言,再多语言都不怕
如何学好C语言
学习本套课程之前 学习本套课程中 学习本套课程之后 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gHyaoC72-1623039894713)(https://upload-images.jianshu.io/upload_images/647982-c724f6cd01191121.png?imageMogr2/auto-orient/strip)]
- 如何达到这样的效果
工欲善其事必先利其器
编写C语言程序用什么工具 ?
- 记事本(开发效率低)
- Vim(初学者入门门槛高)
- VSCode(不喜欢)
- eclipse(不喜欢)
- CLion(深爱, 但收费)
- Xcode(逼格高, 但得有苹果电脑)
- Qt Creator(开源免费,跨平台安装和运行)
什么是Qt Creator ?
- Qt Creator 是一款新的轻量级集成开发环境(IDE)。它能够跨平台运行,支持的系统包括 Windows、Linux(32 位及 64 位)以及 Mac OS X
- Qt Creator 的设计目标是使开发人员能够利用 Qt 这个应用程序框架更加快速及轻易的完成开发任务
- 开源免费, 简单易用, 能够满足学习需求
集成开发环境(IDE,Integrated Development Environment )是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具。集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务套。
Qt Creator安装
-
切记囫囵吞枣, 不要纠结里面的东西都是什么含义, 初学者安装成功就是一种成功
-
下载Qt Creator离线安装包:
- http://download.qt.io/archive/qt/
- 极速下载地址:
- 链接:https://pan.baidu.com/s/1gx0hNDBJkA2gx5wF1Jx34w
提取码:0fg9
-
以管理身份运行离线安装包
-
下一步,下一步,下一步,等待ing…
+
+
-
注意安装路径中最好不要出现中文
-
对于初学者而言全选是最简单的方式(重点!!!)
-
配置Qt Creator开发环境变量
你的安装路径\\5.11.0\\mingw53_32\\bin
你的安装路径\\Tools\\mingw530_32\\bin
- 启动安装好的Qt Creator
- 非全选安装到此为止, 全选安装继续往下看
- 出现这个错误, 忽略这个错误即可
- 等待安装完毕之后解决刚才的错误
- 找到安装目录下的strawberry.msi,双击运行
什么是环境变量?
- 打开我们添加环境变量的两个目录, 不难发现里面大部分都是.exe的可执行程序
- 如果我们不配置环境变量, 那么每次我们想要使用这些"可执行程序"都必须"先找到这些应用程序对应的文件夹"才能使用
- 为了方便我们在电脑上"任何地方"都能够使用这些"可执行程序", 那么我们就必须添加环境变量, 因为Windows执行某个程序的时候, 会先到"环境变量中Path指定的路径中"去查找
为什么要配置系统变量,不配置用户变量
- 用户变量只针对使用这台计算机指定用户
- 一个计算机可以设置多个用户, 不同的用户用不同的用户名和密码
- 当给计算机设置了多个用户的时候,启动计算机的时候就会让你选择哪个用户登录
- 系统变量针对使用这台计算机的所有用户
- 也就是说设置了系统变量, 无论哪个用户登录这台计算机都可以使用你配置好的工具
Qt Creator快捷键
如何创建C语言程序
- 这个世界上, 几乎所有程序员入门的第一段代码都是Hello World.
- 原因是当年C语言的作者Dennis Ritchie(丹尼斯 里奇)在他的名著中第一次引入, 传为后世经典, 其它语言亦争相效仿, 以示敬意
如何创建C语言文件
C语言程序组成
-
手机有很多功能, “开机”,“关机”,“打电话”,“发短信”,"拍照"等等
-
手机中的每一个功能就相当于C语言程序中的一个程序段(函数)
-
众多功能中总有一个会被先执行,不可能多个功能一起执行
-
想使用手机必须先执行手机的开机功能
-
所以C语言程序也一样,由众多功能、众多程序段组成, 众多C语言程序段中总有一个会被先执行, 这个先执行的程序段我们称之为"主函数"
-
一个C语言程序由多个"函数"构成,每个函数有自己的功能
-
一个程序***有且只有一个主函数***
-
如果一个程序没有主函数,则这个程序不具备运行能力
-
程序运行时系统会***自动调用***主函数,而其它函数需要开发者***手动调用***
-
主函数有固定书写的格式和范写
函数定义格式
- 主函数定义的格式:
- int 代表函数执行之后会返回一个整数类型的值
- main 代表这个函数的名字叫做main
- () 代表这是一个函数
- {} 代表这个程序段的范围
- return 0; 代表函数执行完之后返回整数0
int main() {
// insert code here...
return 0;
}
- 其它函数定义的格式
- int 代表函数执行之后会返回一个整数类型的值
- call 代表这个函数的名字叫做call
- () 代表这是一个函数
- {} 代表这个程序段的范围
- return 0; 代表函数执行完之后返回整数0
int call() {
return 0;
}
如何执行定义好的函数
- 主函数(main)会由系统自动调用, 但其它函数不会, 所以想要执行其它函数就必须在main函数中手动调用
- call 代表找到名称叫做call的某个东西
- () 代表要找到的名称叫call的某个东西是一个函数
- ; 代表调用函数的语句已经编写完成
- 所以call();代表找到call函数, 并执行call函数
int main() {
call();
return 0;
}
- 如何往屏幕上输出内容
- 输出内容是一个比较复杂的操作, 所以系统提前定义好了一个专门用于输出内容的函数叫做printf函数,我们只需要执行系统定义好的printf函数就可以往屏幕上输出内容
- 但凡需要执行一个函数, 都是通过函数名称+圆括号的形式来执行
- 如下代码的含义是: 当程序运行时系统会自动执行main函数, 在系统自动执行main函数时我们手动执行了call函数和printf函数
- 经过对代码的观察, 我们发现两个问题
- 并没有告诉printf函数,我们要往屏幕上输出什么内容
- 找不到printf函数的实现代码
int call(){
return 0;
}
int main(){
call();
printf();
return 0;
}
- 如何告诉printf函数要输出的内容
- 将要输出的内容编写到printf函数后面的圆括号中即可
- 注意: 圆括号中编写的内容必须用双引号引起来
printf("hello world\\n");
- 如何找到printf函数的实现代码
- 由于printf函数是系统实现的函数, 所以想要使用printf函数必须在使用之前告诉系统去哪里可以找到printf函数的实现代码
- #include <stdio.h> 就是告诉系统可以去stdio这个文件中查找printf函数的声明和实现
#include <stdio.h>
int call(){
return 0;
}
int main(){
call();
printf("hello world\\n");
return 0;
}
如何运行编写好的程序
- 方式1:
- 点击小榔头将"源代码"编译成"可执行文件"
- 找到编译后的源代码, 打开终端(CMD)运行可执行文件
- 方式2
- 直接点击Qt开发工具运行按钮
main函数注意点及其它写法
- C语言中,每条完整的语句后面都必须以分号结尾
int main(){
printf("hello world\\n") // 如果没有分号编译时会报错
return 0;
}
int main(){
// 如果没有分号,多条语句合并到一行时, 系统不知道从什么地方到什么地方是一条完整语句
printf("hello world\\n") return 0;
}
- C语言中除了注释和双引号引起来的地方以外都不能出现中文
int main(){
printf("hello world\\n"); // 这里的分号如果是中文的分号就会报错
return 0;
}
- 一个C语言程序只能有一个main函数
int main(){
return 0;
}
int main(){ // 编译时会报错, 重复定义
return 0;
}
- 一个C语言程序不能没有main函数
int call(){ // 编译时报错, 因为只有call函数, 没有main函数
return 0;
}
int mian(){ // 编译时报错, 因为main函数的名称写错了,还是相当于没有main函数
return 0;
}
- main函数前面的int可以不写或者换成void
#include <stdio.h>
main(){ // 不会报错
printf("hello world\\n");
return 0;
}
#include <stdio.h>
void main(){ // 不会报错
printf("hello world\\n");
return 0;
}
- main函数中的return 0可以不写
int main(){ // 不会报错
printf("hello world\\n");
}
- 多种写法不报错的原因
- C语言最早的时候只是一种规范和标准(例如C89, C11等)
- 标准的推行需要各大厂商的支持和实施
- 而在支持的实施的时候由于各大厂商利益、理解等问题,导致了实施的标准不同,发生了变化
- Turbo C
- Visual C(VC)
- GNU C(GCC)
- 所以大家才会看到不同的书上书写的格式有所不同, 有的返回int,有的返回void,有的甚至没有返回值
- 所以大家只需要记住最标准的写法即可, no zuo no die
#include <stdio.h>
int main(){
printf("hello world\\n");
return 0;
}
Tips:
语法错误:编译器会直接报错
逻辑错误:没有语法错误,只不过运行结果不正确
C语言程序练习
- 编写一个C语言程序,用至少2种方式在屏幕上输出以下内容
*** ***
*********
*******
****
**
- 普通青年实现
printf(" *** *** \\n");
printf("*********\\n");
printf(" *******\\n");
printf(" ****\\n");
printf(" **\\n");
- 2B青年实现
printf(" *** *** \\n*********\\n *******\\n ****\\n **\\n");
- 文艺青年实现(装逼的, 先不用理解)
int i = 0;
while (1) {
if (i % 2 == 0) {
printf(" *** *** \\n");
printf("*********\\n");
printf(" *******\\n");
printf(" ****\\n");
printf(" **\\n");
}else
{
printf("\\n");
printf(" ** ** \\n");
printf(" *******\\n");
printf(" *****\\n");
printf(" **\\n");
}
sleep(1);
i++;
system("cls");
}
初学者如何避免程序出现BUG
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\\ = /O
____/`---'\\____
. ' \\\\| |// `.
/ \\\\||| : |||// \\
/ _||||| -:- |||||- \\
| | \\\\\\ - /// | |
| \\_| ''\\---/'' | |
\\ .-\\__ `-` ___/-. /
___`. .' /--.--\\ `. . __
."" '< `.___\\_<|>_/___.' >'"".
| | : `- \\`.;`\\ _ /`;.`/ - ` : | |
\\ \\ `-. \\_ __\\ /__ _/ .-` / /
======`-.____`-.___\\_____/___.-`____.-'======
`=---='
.............................................
佛祖保佑 有无BUG
━━━━━━神兽出没━━━━━━
┏┓ ┏┓
┏┛┻━━━━━━┛┻┓
┃ ┃
┃ ━ ┃
┃ ┳┛ ┗┳ ┃
┃ ┃
┃ ┻ ┃
┃ ┃
┗━┓ ┏━┛Code is far away from bug with the animal protecting
┃ ┃ 神兽保佑,代码无bug
┃ ┃
┃ ┗━━━┓
┃ ┣┓
┃ ┏━━┛┛
┗┓┓┏━┳┓┏┛
┃┫┫ ┃┫┫
┗┻┛ ┗┻┛
━━━━━━感觉萌萌哒━━━━━━
´´´´´´´´██´´´´´´´
´´´´´´´████´´´´´´
´´´´´████████´´´´
´´`´███▒▒▒▒███´´´´´
´´´███▒●▒▒●▒██´´´
´´´███▒▒▒▒▒▒██´´´´´
´´´███▒▒▒▒██´ 项目:第一个C语言程序
´´██████▒▒███´´´´´ 语言: C语言
´██████▒▒▒▒███´´ 编辑器: Qt Creator
██████▒▒▒▒▒▒███´´´´ 版本控制:git-github
´´▓▓▓▓▓▓▓▓▓▓▓▓▓▒´´ 代码风格:江哥style
´´▒▒▒▒▓▓▓▓▓▓▓▓▓▒´´´´´
´.▒▒▒´´▓▓▓▓▓▓▓▓▒´´´´´
´.▒▒´´´´▓▓▓▓▓▓▓▒
..▒▒.´´´´▓▓▓▓▓▓▓▒
´▒▒▒▒▒▒▒▒▒▒▒▒
´´´´´´´´´███████´´´´´
´´´´´´´´████████´´´´´´´
´´´´´´´█████████´´´´´´
´´´´´´██████████´´´´ 大部分人都在关注你飞的高不高,却没人在乎你飞的累不累,这就是现实!
´´´´´´██████████´´´ 我从不相信梦想,我,只,相,信,自,己!
´´´´´´´█████████´´
´´´´´´´█████████´´´
´´´´´´´´████████´´´´´
________▒▒▒▒▒
_________▒▒▒▒
_________▒▒▒▒
________▒▒_▒▒
_______▒▒__▒▒
_____ ▒▒___▒▒
_____▒▒___▒▒
____▒▒____▒▒
___▒▒_____▒▒
███____ ▒▒
████____███
█ _███_ _█_███
——————————————————————————女神保佑,代码无bug——————————————————————
多语言对比
- C语言
#include<stdio.h>
int main() {
printf("南哥带你装B带你飞");
return 0;
}
- C++语言
#include<iostream>
using namespace std;
int main() {
cout << "南哥带你装B带你飞" << endl;
return 0;
}
- OC语言
#import <Foundation/Foundation.h>
int main() {
NSLog(@"南哥带你装B带你飞");
return 0;
}
- Java语言
class Test
{
public static viod main()
{
system.out.println("南哥带你装B带你飞");
}
}
- Go语言
package main
import "fmt" //引入fmt库
func main() {
fmt.Println("南哥带你装B带你飞")
}
什么是注释?
- 注释是在所有计算机语言中都非常重要的一个概念,从字面上看,就是注解、解释的意思
- 注释可以用来解释某一段程序或者某一行代码是什么意思,方便程序员之间的交流沟通
- 注释可以是任何文字,也就是说可以写中文
- 被注释的内容在开发工具中会有特殊的颜色
为什么要使用注释?
- 没有编写任何注释的程序
void printMap(char map[6][7] , int row, int col);
int main(int argc, const char * argv[])
{
char map[6][7] = {
{'#', '#', '#', '#', '#', '#', '#'},
{'#', ' ', ' ', ' ', '#' ,' ', ' '},
{'#', 'R', ' ', '#', '#', ' ', '#'},
{'#', ' ', ' ', ' ', '#', ' ', '#'},
{'#', '#', ' ', ' ', ' ', ' ', '#'},
{'#', '#', '#', '#', '#', '#', '#'}
};
int row = sizeof(map)/sizeof(map[0]);
int col = sizeof(map[0])/ sizeof(map[0][0]);
printMap(map, row, col);
int pRow = 2;
int pCol = 1;
int endRow = 1;
int endCol = 6;
while ('R' != map[endRow][endCol]) {
printf("亲, 请输入相应的操作\\n");
printf("w(向上走) s(向下走) a(向左走) d(向右走)\\n");
char run;
run = getchar();
switch (run) {
case 's':
if ('#' != map[pRow + 1][pCol]) {
map[pRow][pCol] = ' ';
pRow++;//3
map[pRow][pCol] = 'R';
}
break;
case 'w':
if ('#' != map[pRow - 1][pCol]) {
map[pRow][pCol] = ' ';
pRow--;
map[pRow][pCol] = 'R';
}
break;
case 'a':
if ('#' != map[pRow][pCol - 1]) {
map[pRow][pCol] = ' ';
pCol--;
map[pRow][pCol] = 'R';
}
break;
case 'd':
if ('#' != map[pRow][pCol + 1]) {
map[pRow][pCol] = ' ';
pCol++;
map[pRow][pCol] = 'R';
}
break;
}
printMap(map, row, col);
}
printf("你太牛X了\\n");
printf("想挑战自己,请购买完整版本\\n");
return 0;
}
void printMap(char map[6][7] , int row, int col)
{
system("cls");
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("%c", map[i][j]);
}
printf("\\n");
}
}
- 编写了注释的程序
/*
R代表一个人
#代表一堵墙
// 0123456
####### // 0
# # // 1
#R ## # // 2
# # # // 3
## # // 4
####### // 5
分析:
>1.保存地图(二维数组)
>2.输出地图
>3.操作R前进(控制小人行走)
3.1.接收用户输入(scanf/getchar)
w(向上走) s(向下走) a(向左走) d(向右走)
3.2.判断用户的输入,控制小人行走
3.2.1.替换二维数组中保存的数据
(
1.判断是否可以修改(如果不是#就可以修改)
2.修改现有位置为空白
3.修改下一步为R
)
3.3.输出修改后的二维数组
4.判断用户是否走出出口
*/
// 声明打印地图方法
void printMap(char map[6][7] , int row, int col);
int main(int argc, const char * argv[])
{
// 1.定义二维数组保存迷宫地图
char map[6][7] = {
{'#', '#', '#', '#', '#', '#', '#'},
{'#', ' ', ' ', ' ', '#' ,' ', ' '},
{'#', 'R', ' ', '#', '#', ' ', '#'},
{'#', ' ', ' ', ' ', '#', ' ', '#'},
{'#', '#', ' ', ' ', ' ', ' ', '#'},
{'#', '#', '#', '#', '#', '#', '#'}
};
// 2.计算地图行数和列数
int row = sizeof(map)/sizeof(map[0]);
int col = sizeof(map[0])/ sizeof(map[0][0]);
// 3.输出地图
printMap(map, row, col);
// 4.定义变量记录人物位置
int pRow = 2;
int pCol = 1;
// 5.定义变量记录出口的位置
int endRow = 1;
int endCol = 6;
// 6.控制人物行走
while ('R' != map[endRow][endCol]) {
// 6.1提示用户如何控制人物行走
printf("亲, 请输入相应的操作\\n");
printf("w(向上走) s(向下走) a(向左走) d(向右走)\\n");
char run;
run = getchar();
// 6.2根据用户输入控制人物行走
switch (run) {
case 's':
if ('#' != map[pRow + 1][pCol]) {
map[pRow][pCol] = ' ';
pRow++;//3
map[pRow][pCol] = 'R';
}
break;
case 'w':
if ('#' != map[pRow - 1][pCol]) {
map[pRow][pCol] = ' ';
pRow--;
map[pRow][pCol] = 'R';
}
break;
case 'a':
if ('#' != map[pRow][pCol - 1]) {
map[pRow][pCol] = ' ';
pCol--;
map[pRow][pCol] = 'R';
}
break;
case 'd':
if ('#' != map[pRow][pCol + 1]) {
map[pRow][pCol] = ' ';
pCol++;
map[pRow][pCol] = 'R';
}
break;
}
// 6.3重新输出行走之后的地图
printMap(map, row, col);
}
printf("你太牛X了\\n");
printf("想挑战自己,请购买完整版本\\n");
return 0;
}
/**
* @brief printMap
* @param map 需要打印的二维数组
* @param row 二维数组的行数
* @param col 二维数组的列数
*/
void printMap(char map[6][7] , int row, int col)
{
// 为了保证窗口的干净整洁, 每次打印都先清空上一次的打印
system("cls");
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("%c", map[i][j]);
}
printf("\\n");
}
}
注释的分类
-
单行注释
- // 被注释内容
- 使用范围:任何地方都可以写注释:函数外面、里面,每一条语句后面
- 作用范围: 从第二个斜线到这一行末尾
- 快捷键:Ctrl+/
-
多行注释
- /* 被注释内容 */
- 使用范围:任何地方都可以写注释:函数外面、里面,每一条语句后面
- 作用范围: 从第一个/*到最近的一个*/
注释的注意点
- 单行注释可以嵌套单行注释、多行注释
// 南哥 // it666.com
// /* 江哥 */
// 帅哥
- 多行注释可以嵌套单行注释
/*
// 作者:LNJ
// 描述:第一个C语言程序作用:这是一个主函数,C程序的入口点
*/
- 多行注释***不能***嵌套多行注释
/*
哈哈哈
/*嘻嘻嘻*/
呵呵呵
*/
注释的应用场景
- 思路分析
/*
R代表一个人
#代表一堵墙
// 0123456
####### // 0
# # // 1
#R ## # // 2
# # # // 3
## # // 4
####### // 5
分析:
>1.保存地图(二维数组)
>2.输出地图
>3.操作R前进(控制小人行走)
3.1.接收用户输入(scanf/getchar)
w(向上走) s(向下走) a(向左走) d(向右走)
3.2.判断用户的输入,控制小人行走
3.2.1.替换二维数组中保存的数据
(
1.判断是否可以修改(如果不是#就可以修改)
2.修改现有位置为空白
3.修改下一步为R
)
3.3.输出修改后的二维数组
4.判断用户是否走出出口
*/
- 对变量进行说明
// 2.计算地图行数和列数
int row = sizeof(map)/sizeof(map[0]);
int col = sizeof(map[0])/ sizeof(map[0][0]);
- 对函数进行说明
/**
* @brief printMap
* @param map 需要打印的二维数组
* @param row 二维数组的行数
* @param col 二维数组的列数
*/
void printMap(char map[6][7] , int row, int col)
{
system("cls");
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("%c", map[i][j]);
}
printf("\\n");
}
}
- 多实现逻辑排序
// 1.定义二维数组保存迷宫地图
char map[6][7] = {
{'#', '#', '#', '#', '#', '#', '#'},
{'#', ' ', ' ', ' ', '#' ,' ', ' '},
{'#', 'R', ' ', '#', '#', ' ', '#'},
{'#', ' ', ' ', ' ', '#', ' ', '#'},
{'#', '#', ' ', ' ', ' ', ' ', '#'},
{'#', '#', '#', '#', '#', '#', '#'}
};
// 2.计算地图行数和列数
int row = sizeof(map)/sizeof(map[0]);
int col = sizeof(map[0])/ sizeof(map[0][0]);
// 3.输出地图
printMap(map, row, col);
// 4.定义变量记录人物位置
int pRow = 2;
int pCol = 1;
// 5.定义变量记录出口的位置
int endRow = 1;
int endCol = 6;
// 6.控制人物行走
while ('R' != map[endRow][endCol]) {
... ...
}
使用注释的好处
- 注释是一个程序员必须要具备的良好习惯
- 帮助开发人员整理实现思路
- 解释说明程序, 提高程序的可读性
- 初学者编写程序可以养成习惯:先写注释再写代码
- 将自己的思想通过注释先整理出来,在用代码去体现
- 因为代码仅仅是思想的一种体现形式而已
什么是关键字?
- 关键字,也叫作保留字。是指一些被C语言赋予了特殊含义的单词
- 关键字特征:
- 全部都是小写
- 在开发工具中会显示特殊颜色
- 关键字注意点:
- 因为关键字在C语言中有特殊的含义, 所以不能用作变量名、函数名等
- C语言中一共有32个关键字
1 2 3 4 5 6 7 8 char short int long float double if else return do while for switch case break continue default goto sizeof auto register static extern unsigned signed typedef struct enum union void const volatile
这些不用专门去记住,用多了就会了。在编译器里都是有特殊颜色的。 我们用到时候会一个一个讲解这个些关键字怎么用,现在浏览下,有个印象就OK了
关键字分类
什么是标识符?
- 从字面上理解,就是用来标识某些东西的符号,标识的目的就是为了将这些东西区分开来
- 其实标识符的作用就跟人类的名字差不多,为了区分每个人,就在每个人出生的时候起了个名字
- C语言是由函数构成的,一个C程序中可能会有多个函数,为了区分这些函数,就给每一个函数都起了个名称, 这个名称就是标识符
- 综上所述: 程序员在程序中给函数、变量等起名字就是标识符
标识符命名规则
- 只能由字母(a~z、 A~Z)、数字、下划线组成
- 不能包含除下划线以外的其它特殊字符串
- 不能以数字开头
- 不能是C语言中的关键字
- 标识符严格区分大小写, test和Test是两个不同的标识符
练习
- 下列哪些是合法的标识符
fromNo22 from#22 my_Boolean my-Boolean 2ndObj GUI lnj Mike2jack 江哥 _test test!32 haha(da)tt jack_rose jack&rose
标识符命名规范
- 见名知意,能够提高代码的可读性
- 驼峰命名,能够提高代码的可读性
- 驼峰命名法就是当变量名或函数名是由多个单词连接在一起,构成标识符时,第一个单词以小写字母开始;第二个单词的首字母大写.
- 例如: myFirstName、myLastName这样的变量名称看上去就像驼峰一样此起彼伏
什么是数据?
-
生活中无时无刻都在跟数据打交道
- 例如:人的体重、身高、收入、性别等数据等
-
在我们使用计算机的过程中,也会接触到各种各样的数据
- 例如: 文档数据、图片数据、视频数据等
数据分类
-
静态的数据
- 静态数据是指一些永久性的数据,一般存储在硬盘中。硬盘的存储空间一般都比较大,现在普通计算机的硬盘都有500G左右,因此硬盘中可以存放一些比较大的文件
- 存储的时长:计算机关闭之后再开启,这些数据依旧还在,只要你不主动删掉或者硬盘没坏,这些数据永远都在
- 哪些是静态数据:静态数据一般是以文件的形式存储在硬盘上,比如文档、照片、视频等。
-
动态的数据
- 动态数据指在程序运行过程中,动态产生的临时数据,一般存储在内存中。内存的存储空间一般都比较小,现在普通计算机的内存只有8G左右,因此要谨慎使用内存,不要占用太多的内存空间
- 存储的时长:计算机关闭之后,这些临时数据就会被清除
- 哪些是动态数据:当运行某个程序(软件)时,整个程序就会被加载到内存中,在程序运行过程中,会产生各种各样的临时数据,这些临时数据都是存储在内存中的。当程序停止运行或者计算机被强制关闭时,这个程序产生的所有临时数据都会被清除。
-
既然硬盘的存储空间这么大,为何不把所有的应用程序加载到硬盘中去执行呢?
- 主要***原因就是内存的访问速度比硬盘快N倍***
- 静态数据和动态数据的相互转换
- 也就是从磁盘加载到内存
- 动态数据和静态数据的相互转换
- 也就是从内存保存到磁盘
- 数据的计量单位
- 不管是静态还是动态数据,都是0和1组成的
- 数据越大,包含的0和1就越多
1 B(Byte字节) = 8 bit(位)
// 00000000 就是一个字节
// 111111111 也是一个字节
// 10101010 也是一个字节
// 任意8个0和1的组合都是一个字节
1 KB(KByte) = 1024 B
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB
C语言数据类型
- 作为程序员, 我们最关心的是内存中的动态数据,因为我们写的程序就是在内存中运行的
- 程序在运行过程中会产生各种各样的临时数据,为了方便数据的运算和操作, C语言对这些数据进行了分类, 提供了丰富的数据类型
- C语言中有4大类数据类型:基本类型、构造类型、指针类型、空类型
什么是常量?
- "量"表示数据。常量,则表示一些固定的数据,也就是不能改变的数据
- 就好比现实生活中生男生女一样, 生下来是男孩永远都是男孩, 生下来是女孩就永远都是女孩, 所以性别就是现实生活中常量的一种体现
- 不要和江哥吹牛X说你是泰国来的, 如果你真的来自泰国, 我只能说你赢了
常量的类型
-
整型常量
- 十进制整数。例如:666,-120, 0
- 八进制整数,八进制形式的常量都以0开头。例如:0123,也就是十进制的83;-011,也就是十进 制的-9
- 十六进制整数,十六进制的常量都是以0x开头。例如:0x123,也就是十进制的291
- 二进制整数,逢二进一 0b开头。例如: 0b0010,也就是十进制的2
-
实型常量
- 小数形式
- 单
以上是关于PyQt5保姆级教程-- 从入门到精通的主要内容,如果未能解决你的问题,请参考以下文章