所有与PyQT以及Pyside2的基础教学都在以下网址,本人QT的专栏内容是自己学习过程中的一些笔记和遇到的一些问题做了整理,特此声明。
基础网站: www.python3.vip
视频教学: https://www.bilibili.com/video/BV1cJ411R7bP?p=1
官方文档: https://doc.qt.io/qt-5/qtexamplesandtutorials.html
pip install pyside2 安装puside2库
pyside2、pyQt5都是基于Qt库的。Qt库时用c++开发的,Pyside2、PyQt5可以让我们通过python语言来使用。
区别:Pyside2是Qt亲儿子,PyQt5是义子(由riverbank computing开发的),Pyside2是2018年7月分面世的,出生过晚,两者在语法上几乎没有区别,一般只需要略作修改,比如说改一下库名就可以。
其实,我们可以用QT界面生成器 Qt Designer ,拖拖拽拽就可以直观的创建出程序大体的界面。
Windows下,运行 Python安装目录下 Scripts\pyside2-designer.exe 这个可执行文件,可以把这个目录添加到Windows环境变量,这样方便查找。
pyside-uic是用来将qtdesigner设计的界面转成代码的,具体操作步骤如下:
在pycharm中点击 File -- settings -- tools -- Extternal ,然后点击加号,会弹出来以下界面
主要设置的是Name和Tool Settings中那三个参数。
Name :在pycharm中显示的这个外部工具的名称(可以自己看着起);
Program:这里选择pyside2-uic.exe所在的位置。是在Scripts文件夹中的,不在site-package中;
Arguments:这里设置的是将ui文件转为代码后,文件的名称(test.ui------>ui_test.py);
Working directory:这里的意思是,转化成功后,将文件放在当前目录下;
设置好上面的四个参数后,点击ok就好,Qt-designer的添加和它一样,不过Qt-designer在site-package文件夹下,并且里面设置的参数有所出入,具体看下图:
安装和设置就到此结束了,使用的时候,右键Ui文件,然后在External Tools选项中,就能找到这两个设置。
如果在使用过程中,想通过命令行来将Ui文件转成py文件,可以用以下命令:
Pyside-uic xxxx.ui -o - yyyy.py
在designer界面中,有自动生成代码的功能,但是不能用,可以通过以下方式来让其回复正常:
去 D:\python-3.6.2\Lib\site-packages\PySide2 中,新建一个bin文件,然后把该目录下的uic.exe粘贴进去,然后就可以正常使用了。
mainwindow中独有的两个对象,一个是toolbar,另一个是statusbar。toolbar必须要在mainwindow中才可以被创建,在右边的对象查看器中,右键mianwindow,点击“添加工具栏”,
如需要多个工具栏的话,重复多点几次就ok了。
为工具栏添加action,首先打开动作编辑器,在最上方视图中可以选择,然后新建动作,如果需要给动作添加图片的话,在编辑动作当中图标的那一栏点击下箭头,就ok了。
如果添加完图片需要把设置的名称也显示出来,去action所在的toolbar中,在toolbar的属性编辑器,从最下面绿色那一块找到”toolButtonStyle“这个选项,然后选择ToolButtonTextUnderIcon“,就可以显示相应文字了。
from PySide2.QtGui import QIcon
app = QApplication([])
# 加载icon
app.setWindowIcon(QIcon('logo.png'))
它的作用和css差不多,用于Qt界面的渲染。一般都是选全局,在全局中修改样式。
一个基本的示例:
QPushButton{
color:red;
font-size:18px;
}
*{
font-family:楷体; # 这玩意里可以打中文的
font-size:20px;
color:brown
}
语法有selector和declaration组成,QPushButton是selector,后面的是declaration。
Universal Selector | * | 星号匹配所有的界面元素 |
Type Selector | QPushButton | 选择所有 QPushButton类型 (包括其子类) |
Class Selector | .QPushButton | 选择所有 QPushButton类型 ,但是不包括其子类 |
ID Selector | QPushButton#okButton | 选择所有 对象名为 okButton 的QPushButton类型 |
Property Selector | QPushButton[flat="false"] | 选择所有 flat 属性值为 false 的 QPushButton类型 |
Descendant Selector | QDialog QPushButton | 选择所有 QDialog 内部 QPushButton类型 |
Child Selector | QDialog > QPushButton | 选择所有 QDialog 直接子节点 QPushButton类型,意思是只要儿子 |
flat是QPushButton的一个属性,一点flat,它的边框就不见了。也可以根据它的其他属性做选择,它有个bug,就是改了字体大小以后,可能有些框内的字体不会改变,这个就要通过关闭后重新打开designer来解决。
可以通过属性编辑器上方窗口的绿色加号,来为某个元素增加一个属性,通过这个我们自定义的标志属性,就可以通过类似于 QPushButton[flat="false"] 的方式去快速修改元素样式。
以下是鼠标悬浮按钮特效示例:
我们可以这样指定当鼠标移动到一个元素上方的时候,元素的显示样式:
QPushButton:hover { color: red }
再比如,指定一个元素是disable状态的显示样式:
QPushButton:disabled { color: red }
再比如,指定一个元素是鼠标悬浮,并且处于勾选(checked)状态的显示样式:
QCheckBox:hover:checked { color: white }
如果一个元素被多层渲染,则它最先显示最靠近它的。
以下是颜色渲染、背景图片设置、边框设置:
QTextEdit { background-color: yellow }
颜色可以使用红绿蓝数字,像这样
QTextEdit { background-color: #e7d8d8 }
也可以像这样指定背景图片
QTextEdit {background-image: url(gg03.png);}
可以像这样指定边框
border:1px solid #1d649c;
其中:
1px 是边框宽度
solid 是边框线为实线, 也可以是 dashed(虚线) 和 dotted(点)
比如
*[myclass=bar2btn]:hover{
border:1px solid #1d649c;
}
边框也可以指定为无边框 border:none
可以这样指定元素的 文字字体、大小、颜色
*{
font-family:微软雅黑;
font-size:15px;
color: #1d649c;
}
可以这样指定元素的 宽度、高度
QPushButton {
width:50px;
height:20px;
}
可以这样指定元素的 margin
QTextEdit {
margin:10px 11px 12px 13px
}
分别指定了元素的上右下左margin。
也可以使用 margin-top, margin-right, margin-bottom, margin-left 单独指定 元素的上右下左margin
比如
QTextEdit {
margin:10px 50px;
padding:10px 50px;
}
font-picture中,元素边界是一条线没有图片中那么宽就仅仅是一条线
按钮设置圆角
#generate{
border - radius: 10px;
}
在多线程处理问题是,尤其是往主界面打印东西,不要用两个线程来交叉处理界面,因为有很大的概率会报错或者崩溃,在处理主界面打印信息是,最好是子线程去收集信号,然后再交给主线程去处理。----白月黑羽 20集
设置窗口居中,可以设置最后三行的位置函数,来调整窗口的具体位置::
def center(self):
qr = self.frameGeometry() # 获取主窗口的整个形状大小
cp = QDesktopWidget().availableGeometry().center() # QtGui中的QDesktopWidget类提供了桌面窗口的信息,包含了屏幕尺寸的数据
# 算出相对于整个显示器的绝对位置。并且从这个绝对位置当中,获取屏幕的中心点。
qr.moveCenter(cp) # 将主窗口移动到屏幕中心点
self.move(qr.topLeft()) # 将窗口左上角的点和屏幕左上角的点相对应
窗口最大化(可以手动关闭窗口)
self.showMaximized()
全屏幕显示(不可以手动关闭窗口)
screen = QtGui.QDesktopWidget().screenGeometry()
setGeometry(0,0,screen.width(), screen.height())
QlineEdit相关操作
1.设置文本不可编辑,下列三种方法都可以
setEnabled(false);
setFocusPolicy(QCore.tQt.NoFocus); //无法获得焦点,自然无法输入,其他文本控件类似,需要from pyqtgraph.Qt
hasAcceptableInput(false);
2.设置提示文字
setPlaceholderText() 设置提示文字
settext() 设置文本内容
text() 获取文本内容
1.基类名称:QOpenGLWidget 要选好要提升的类它的父类名称是什么
2.提升的类名称:GLViewWidget 这个代表你要把这个窗体提升为哪个类,它必须是基类的子类,不能乱写
3.头文件:pyqtgraph.opengl 这个是GLViewWidget所在的目录,必须要知道的,
提升完成以后用uic生成代码,然后就可以看到,它的本质其实是 from pyqtgraph.opengl import GLViewWidget,也就是 fron 3 import 2
在designer中,最下面的pixmap中指定,然后勾选scaledContents就可以让图片自适应,使用Qlabel设置图片的时候,发现设置好以后图片不显示,说是因为图片位深度必须是32位的,但是没什么用,通过手动设置就可以显示出来了,代码如下:
self.company_logo.setPixmap('Static/logo.png')
如果想让表头自定义大小,先选中整个表格,然后加样式,加样式的时候,如果样式的颜色变了,说明是有用的。
QTabBar::tab{height:200}
表头1的名字叫tab,改完之后就ok了。
方法一:这个比较短,但是功能不全
from PySide2.QtWidgets import QApplication
import sys
if __name__ == "__main__":
app = QApplication(sys.argv)
screen = QApplication.primaryScreen().grabWindow(QApplication.desktop().winId())
print(QApplication.desktop().winId())
screen.save("../Matplotlib_Numpy/123.jpg")
方法二:
# from Qt import __binding__
#
# print(__binding__)
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtCore import *
'''
# Qt 中无法导入 QScreen 类
try:
from PySide2.QtGui import QScreen
except:
from PySide2.QtGui import QScreen
'''
import sys
class WScreenShot(QWidget):
# win = ''
#
# @classmethod
# def run(cls):
# cls.win = cls()
# cls.win.show()
def __init__(self, parent=None):
super(WScreenShot, self).__init__(parent)
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
self.setStyleSheet('''background-color:black; ''')
self.setWindowOpacity(0.6)
# desktop = QApplication.desktop()
# rect = desktop.availableGeometry()
desktopRect = QDesktopWidget().screenGeometry()
self.setGeometry(desktopRect)
self.setCursor(Qt.CrossCursor)
self.blackMask = QBitmap(desktopRect.size())
self.blackMask.fill(Qt.black)
self.mask = self.blackMask.copy()
self.isDrawing = False
self.startPoint = QPoint()
self.endPoint = QPoint()
def paintEvent(self, event):
if self.isDrawing:
self.mask = self.blackMask.copy()
pp = QPainter(self.mask)
pen = QPen()
pen.setStyle(Qt.NoPen)
pp.setPen(pen)
brush = QBrush(Qt.white)
pp.setBrush(brush)
pp.drawRect(QRect(self.startPoint, self.endPoint))
self.setMask(QBitmap(self.mask))
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.startPoint = event.pos()
self.endPoint = self.startPoint
self.isDrawing = True
def mouseMoveEvent(self, event):
if self.isDrawing:
self.endPoint = event.pos()
self.update()
def mouseReleaseEvent(self, event):
if event.button() == Qt.LeftButton:
self.endPoint = event.pos()
# PySide2
# screenshot = QPixmap.grabWindow(QApplication.desktop().winId())
# PySide2
# screenshot = QApplication.primaryScreen().grabWindow(0)
# 通用
screenshot = QApplication.primaryScreen().grabWindow(QApplication.desktop().winId())
rect = QRect(self.startPoint, self.endPoint)
outputRegion = screenshot.copy(rect)
outputRegion.save('d:/sho54t.jpg', format='JPG', quality=100)
self.close()
if __name__ == '__main__':
# app = QApplication.instance() or QApplication(sys.argv)
# WScreenShot.run()
# app.exec_()
app = QApplication(sys.argv)
win = WScreenShot()
win.show()
app.exec_()
# app = QApplication(sys.argv)
# win = DesktopChosenBox(700, 500, 30)
# win.show()
# app.exec_()
方法一:手写界面
from PySide2.QtWidgets import QApplication,QMainWindow,QPushButton,QPlainTextEdit,QMessageBox
# QtWidgets 专门负责控件的,其中包含几个类,应用程序、主窗口、按钮、纯文本的框、弹出通知的对话框
def handleCalc():
info = textEdit.toPlainText()
salary_above_20k = ''
salary_below_20k = ''
for line in info.splitlines():
if not line.strip():
continue
parts = line.split(' ')
# 去掉列表中的空字符串内容
parts = [p for p in parts if p]
name, salary, age = parts
if int(salary) >= 20000:
salary_above_20k += name + '\n'
else:
salary_below_20k += name + '\n'
QMessageBox.about(window,
'统计结果',
f'''薪资20000 以上的有:\n{salary_above_20k}
\n薪资20000 以下的有:\n{salary_below_20k}'''
)
# 创建一个应用,提供了整个图形界面的底层管理功能,中括号表示填一个空参数,因为参数具有定制功能
# QApplication 提供了整个图形界面程序的底层管理功能,比如:
# 初始化、程序入口参数的处理,用户事件(对界面的点击、输入、拖拽)分发给各个对应的控件,等等…
# 既然QApplication要做如此重要的初始化操作,我们必须在任何界面控件对象创建前,先创建它。
app = QApplication([])
# 建立主窗口
window = QMainWindow()
# 设置窗口尺寸
window.resize(500,400)
# 调整运行时窗口出现位置
window.move(300,300)
# 设置窗口的标题
window.setWindowTitle('资薪统计')
# 里面的window值向它的父级窗口
textEdit = QPlainTextEdit(window)
textEdit.setPlaceholderText('请输入资薪表')
textEdit.move(10,25)
textEdit.resize(300,350)
button = QPushButton('统计',window)
button.move(380,80)
button.clicked.connect(handleCalc)
window.show()
# 进入QApplication的事件处理循环,接收用户的输入事件(),并且分配给相应的对象去处理。
app.exec_()
# 在 Qt 系统中, 当界面上一个控件被操作时,比如 被点击、被输入文本、被鼠标拖拽等, 就会发出 信号 ,英文叫 signal 。
# 就是表明一个事件(比如被点击、被输入文本)发生了。
# 我们可以预先在代码中指定 处理这个 signal 的函数,这个处理 signal 的函数 叫做 slot 。
方法二:通过类直接加载Ui文件
from PySide2.QtWidgets import QApplication, QMessageBox
from PySide2.QtUiTools import QUiLoader
from PySide2.QtGui import QIcon
class Stats:
def __init__(self):
# 从文件中加载UI定义
# 从 UI 定义中动态 创建一个相应的窗口对象
# 注意:里面的控件对象也成为窗口对象的属性了
# 比如 self.ui.button , self.ui.textEdit
self.ui = QUiLoader().load('designer--1.ui')
self.ui.Button.clicked.connect(self.handleCalc)
def handleCalc(self):
info = self.ui.TextEdit.toPlainText()
salary_above_20k = ''
salary_below_20k = ''
for line in info.splitlines():
if not line.strip():
continue
parts = line.split(' ')
parts = [p for p in parts if p]
name,salary,age = parts
if int(salary) >= 20000:
salary_above_20k += name + '\n'
else:
salary_below_20k += name + '\n'
QMessageBox.about(self.ui,
'统计结果',
f'''薪资20000 以上的有:\n{salary_above_20k}
\n薪资20000 以下的有:\n{salary_below_20k}'''
)
app = QApplication([])
app.setWindowIcon(QIcon('title-picture.jpeg'))
stats = Stats()
stats.ui.show()
app.exec_()
方法三:把Ui文件转为py文件后,通过类来操作(这个有两种写法,个人常用的写法忽略)
'''该文件命名为mainWin.py'''
from PySide2.QtWidgets import QWidget, QCheckBox, QApplication, QPushButton, QLabel, QVBoxLayout, QFormLayout
import subFirst
import sys
class Example(QWidget):
def __init__(self):
QWidget.__init__(self)
self.initUI()
self.setWindowTitle('主窗口')
def initUI(self):
self.cb = QCheckBox('复选框', self) # 添加一个复选框
self.cb.stateChanged.connect(self.changecb) # 关联复选框槽函数
self.bt = QPushButton('确定', self) # 添加一个按钮
self.bt.clicked.connect(self.go) # 关联按钮槽函数
self.label = QLabel() # 添加一个标签
self.formlayout = QFormLayout()
self.formlayout.addRow(self.cb, self.label)
self.vbox = QVBoxLayout()
self.vbox.addLayout(self.formlayout)
self.vbox.addWidget(self.bt)
self.setLayout(self.vbox)
self.resize(400, 300)
self.show()
def go(self): # 按钮槽函数
if self.cb.isChecked():
subFirstWindow = subFirst.firstSub(self) # 打开第一个子窗口
subFirstWindow.show()
else:
pass
def changecb(self): # 复选框槽函数
if self.cb.isChecked():
self.label.setText('单选框已被勾选,点击确定跳转到子窗口')
else:
self.label.setText(' ')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())