pyqt5快速pyqt5 开发环境搭建与实战 怎么样

PyQt5中的事件和信号
在这部分PyQt5编程教程中,我们探索应用中事件和信号的发生。
所有的GUI应用都是事件驱动的。事件主要由应用的用户操作产生的。但是事件可能由其他条件触发,比如:一个网络连接,一个窗口管理器,一个定时器,这些动作都可能触发事件的产生。当我们调用应用的exec_()方法时,应用进入了主循环。主循环用于检测事件的产生并且将事件送到用于处理的对象中去。
在事件模型,有三个参与者
事件源是状态发生改变的对象。它产生了事件。事件对象(evnet)封装了事件源中的状态变化。事件目标是想要被通知的对象。事件源对象代表了处理一个事件直到事件目标做出响应的任务。
PyQt5有一个独一无二的信号和槽机制来处理事件。信号和槽用于对象之间的通信。当指定事件发生,一个事件信号会被发射。槽可以被任何Python脚本调用。当和槽连接的信号被发射时,槽会被调用。
这个例子演示了PyQt5中的信号和槽的使用。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
ZetCode PyQt5 tutorial
In this example, we connect a signal
of a QSlider to a slot of a QLCDNumber.
author: Jan Bodnar
last edited: January 2015
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (QWidget, QLCDNumber, QSlider,
QVBoxLayout, QApplication)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
lcd = QLCDNumber(self)
sld = QSlider(Qt.Horizontal, self)
vbox = QVBoxLayout()
vbox.addWidget(lcd)
vbox.addWidget(sld)
self.setLayout(vbox)
sld.valueChanged.connect(lcd.display)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Signal & slot')
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
在我们的例子中,我们显示了一个QtGui.QLCDNumber和一个QtGui.QSlider类。我们拖动滑块条的把手,lcd数字会变化。
sld.valueChanged.connect(lcd.display)
这里,我们将滑块条的valueChanged信号和lcd数字显示的display槽连接在一起。
发送者是一个发送了信号的对象。接受者是一个接受了信号的对象。槽是对信号做出反应的方法。
Figure: Signal & slot
重写事件处理函数
PyQt中的事件处理通常通过重写事件处理函数来处理。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
ZetCode PyQt5 tutorial
In this example, we reimplement an
event handler.
author: Jan Bodnar
last edited: January 2015
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QApplication
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Event handler')
self.show()
def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape:
self.close()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
在我们的例子中,我们重写了keyPressEvent()事件处理函数。
def keyPressEvent(self, e):
if e.key() == Qt.Key_Escape:
self.close()
如果我们点击了Esc按钮,应用将会被终止。
事件发送者
有时需要方便的知道哪一个组件是信号发送者。因此,PyQt5拥有了sender()方法来解决这个问题。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
ZetCode PyQt5 tutorial
In this example, we determine the event sender
author: Jan Bodnar
last edited: January 2015
import sys
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
btn1 = QPushButton("Button 1", self)
btn1.move(30, 50)
btn2 = QPushButton("Button 2", self)
btn2.move(150, 50)
btn1.clicked.connect(self.buttonClicked)
btn2.clicked.connect(self.buttonClicked)
self.statusBar()
self.setGeometry(300, 300, 290, 150)
self.setWindowTitle('Event sender')
self.show()
def buttonClicked(self):
sender = self.sender()
self.statusBar().showMessage(sender.text() + ' was pressed')
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
在我们的例子中,我们有两个按钮。在buttonClikced()方法中,我们调用sender()方法来判断哪一个按钮是我们按下的。
btn1.clicked.connect(self.buttonClicked)
btn2.clicked.connect(self.buttonClicked)
两个按钮都连接到了同一个槽中。
def buttonClicked(self):
sender = self.sender()
self.statusBar().showMessage(sender.text() + ' was pressed')
我们调用sender()方法判断发送信号的信号源是哪一个。然后在应用的状态栏上显示被按下的按钮的标签内容。
Figure: Event sender
从QObejct生成的对象可以发送信号。在下面的例子中我们将会看到怎样去发送自定义的信号。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
ZetCode PyQt5 tutorial
In this example, we show how to emit a
author: Jan Bodnar
last edited: January 2015
import sys
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QMainWindow, QApplication
class Communicate(QObject):
closeApp = pyqtSignal()
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.c = Communicate()
self.c.closeApp.connect(self.close)
self.setGeometry(300, 300, 290, 150)
self.setWindowTitle('Emit signal')
self.show()
def mousePressEvent(self, event):
self.c.closeApp.emit()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
我们创建一个新的信号叫做closeApp。当触发鼠标点击事件时信号会被发射。信号连接到了QMainWindow的close()方法。
class Communicate(QObject):
closeApp = pyqtSignal()
信号使用了pyqtSignal()方法创建,并且成为外部类Communicate类的属性。
self.c = Communicate()
self.c.closeApp.connect(self.close)
把自定义的closeApp信号连接到QMainWindow的close()槽上。
def mousePressEvent(self, event):
self.c.closeApp.emit()
当我们在窗口上点击一下鼠标,closeApp信号会被发射。应用中断。
这部分的PyQt5教程中,我们概览了信号了槽机制。
阅读(...) 评论()Python 跨平台PyQt5开发系列(三)案例实战
Python 跨平台PyQt5开发系列(三)案例实战
一、前言:我们在前面学习了一些使用PyQt5开发的相关知识,本次我们将实现一个简单的电子时钟来加强python的编码能力及PyQt5相关开发知识的使用。本次我们主要用到两个新的知识点:1、QTimer描述:QTimer类提供了定时器信号和单触发定时器。它在内部使用定时器事件来提供更通用的定时器。使用操作:创建一个QTimer,使用start来开始并且把它的timeout()连接到适当的槽。当这段时间过去了,它将会发射timeout()信号。2、QLCDNumber用于显示LCD数字。它可以显示几乎任意大小的数字。可以显示十进制、十六进制、八进制或二进制数。使用display()槽连接到数据源。二、编码实战OK,我们先来看下本次的效果图吧。我们先来看下完整的代码,然后再分段来讲解。代码不多,50行不到哦。代码详解:1、首先我们继承QWidget来创建一个自定义时钟类。2、在initUI方法里完成界面的编写。3、在init_timer方法里完成有关时钟的初始化。我们看下initUI里面的代码:- 设置大小那些我们就不讲了,本次我们还多了一个类QPalette,我们通过它来设置组件的背景颜色及字体的背景颜色等。背景颜色的设置self.main_p = QPalette();:创建一个QPalette类,其相当于调色板self.main_p.setColor(QPalette.Background,Qt.darkYellow); :设置背景颜色为darkYellowself.setAutoFillBackground(True); :设置窗体自动填充背景颜色self.setPalette(self.main_p);:把调色板设置给我们的顶级窗口就可以了哦。这样背景颜色就设置好了。LCD显示组件的设置self.lcd = QLCDNumber();创建一个QLCDNumberself.lcd.setDigitCount(10); 设置显示数字个数self.lcd.setMode(QLCDNumber.Dec);设置显示模式为十进制self.lcd.setSegmentStyle(QLCDNumber.Flat);:设置样式为平面模式再下来是一段设置里面字体颜色的,与背景颜色类似,我就不说了显示时间:self.lcd.display(time.strftime(‘%X’,time.localtime()))time.strftime():接收时间元组,并返回以可读字符串表示的当地时间,格式由参数format决定。%X 表示显示本地相应的时间表示time.localtime()获取本地时间。self.main_layout = QVBoxLayout(); 创建一个盒子布局self.main_layout.addWidget(self.lcd);把我们的显示组件添加到布局中。self.main_layout.setAlignment(Qt.AlignCenter);:设置组件在布局的中心self.setLayout(self.main_layout);:设置给我们的顶层布局电子钟的初始化我们再看下init_timer方法self.timer = QTimer();:创建一个定时器self.timer.setInterval(1000);:设置定时器每1秒触发一次timeout信号self.timer.start();:启动定时器self.timer.timeout.connect(self.updatetime);:timeout信号与updatetime方法关联,再timeout触发时,通知我们的updatetime.再updatetime里更新显示的时间。三、总结本次我们学习了QTimer的使用、QLCDNumber的显示、还增加了背景颜色、字体颜色的设置等。后面我们将一点一点增加复杂度,循序渐进。小伙伴们有什么好的建议都可以给我留言哦!如果看到了这里,说明你已经看完了,感谢你的支持喜欢就点一下哦,谢谢!@著作权归作者所有,转载请联系作者 用心写好每一篇文章
本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。
百家号 最近更新:
简介: 喜欢数码产品和了解,有一些见解
作者最新文章2534人阅读
http://blog.csdn.net/weiaitaowang/article/details/
一文对PyQt5与Eric6的安装做了详细的记录。这次将结合使用PyQt5和Eric6以实例的方式向大家展示PyQt5与Eric6的极速GUI开发,同时也可以让大家对PyQt5与Eric6先混个脸熟。
用 Eric6 与 PyQt5 结合,非常方便的实现界面与逻辑分离,满足的极速GUI编程,你只需要关注程序的逻辑实现,而不需要在界面上花很多时间。
可以说这是一对GUI开发完美的组合!
好了,闲言碎语少说,来点实际的吧!
为了方便使用在正式开始之前我们先简单配置一下Eric6的项目工作区
打开 Eric6
选择菜单栏 设置-首选项
在左侧列表中选择项目-多重项目,点击右侧图标后选定硬盘中的一个位置,我这里是F:\Python\PyQt5文件夹。选好后点击右下方的OK按钮。
简单配置后,让我们正式开始体验极速GUI开发
打开Eric6,菜单栏中选择项目-新建
在项目属性对话框中的项目名称中输入Hello,你会发现右下方的OK按钮不可用。究其原因是项目文件夹中显示的是我们刚设置的多重项目工作区目录,也就是说在该目录下可以存在多个项目。多个项目混在一起肯定是不行的了,还要将它们用文件夹区分开来,简而言之就是该目录下的每个文件夹就是一个项目(当然了,自己胡乱创建的文件夹肯定不是了,呵呵!)。找到原因后我们就可以解决问题了。
点击项目文件夹后面的图标
在打开的选择项目文件夹对话框中右键点击空白处,在弹出的菜单中选择新建-文件夹
更改新建文件夹的名称为Hello(一般与项目名称同),选中该文件夹后点击右下方的选择文件夹按钮
回到项目属性对话框后可以看到项目文件夹已变成F:\Python\PyQt5\Hello,同时右下角的OK按钮已显示可用。
点击OK按钮后出现一个提示框,是否将已有文件添加到项目中?虽然该项目文件夹下还没有任何文件,但是这里选择Yes,因为我曾经选择No后到运行脚本时发现不能执行该功能。
点击Yes后在弹出的文件类型关联对话框直接OK
观察程序主界面的标题栏发现显示Hello – eric6。在项目浏览器的顶部源代码标签里自动为我们生成一个_init_.py文件,该文件中没有任何代码,我们不用去理会。
点击源代码标签右边的窗体标签,在标签下面的空白处右键点击,弹出的菜单选择新建窗体
弹出新建窗体对话框,可以选择其它窗体类型,这里我们使用默认对话框类型,点击OK按钮
在弹出的新建窗体保存对话框中可以看到程序已将路径定位到项目文件夹下,输入文件名后点击保存按钮
在Eric6的窗体标签下可以看到程序已自动创建了HelloWindow.ui文件
点击上一步的保存按钮后,计算机会直接打开Qt设计师,并自动将HelloWindow.ui加载到程序中
在左侧的Widget Box里找到Push Button控件,用鼠标左键按住该控件不放,拖拽到HelloWindow.ui的设计窗体。拖拽两个Push Button控件到窗体
再找到Label控件,拖拽一个该控件到窗体
在程序的右侧观察对象查看器与属性编辑器。使用对象查看器可以快速选取窗体中的控件,属性编辑器可以编辑修改窗体、控件的各种属性。
利用对象查看器选择我们刚拖拽的三个控件,分别将它们的objectName属性更改成:
左边PushButton:Button_ok右边PushButton:Button_close
Label:label
分别将它们的text属性更改成:
左边PushButton:确定右边PushButton:关闭Label:显示
编辑信号/槽
接下来给关闭按钮添加退出程序的命令。在Qt设计师中,可以很直观的为控件添加事件命令,在PyQt5中这种方式添加的事件命令被称为信号/槽。(注:信号/槽机制是PyQt独有的信号传递机制,使用非常方便)
点击工具栏的编辑信号/槽图标
鼠标移动到关闭控件上面,左键按下拖拽处红色地线标志后松开鼠标
弹出配置链接窗口,在该窗口中勾选显示从QWidget继承的信号和槽
在左侧列表选择clicked(),在右侧列表选择close()。
这个操作的意义为:当点击关闭按钮时,执行关闭命令
点击OK后可以看到刚选择的两项已链接附加到关闭按钮上
点击工具栏中的保存按钮后关闭Qt设计师程序
回到Eric6中,右键点击HelloWindow.ui文件,在弹出的菜单中选择编译窗体
稍等片刻后程序会提示编译成功
返回源代码标签可以发现项目中多了一个Ui_HelloWindow.py文件,双击该文件可以查看我们设计好的窗体代码
点击菜单栏的开始-运行脚本(或直接按键盘F2键)
在弹出的运行脚本对话框直接OK
OK后即可看到我们刚在Qt设计师中设计的窗体,点击关闭按钮
弹出对话框中直接OK,即可关闭该程序
进一步完善程序
到现在我们没有编写一句代码即可实现了程序的显示与退出
接下来我们手动给确定按钮添加事件命令
在Eric6中的项目浏览器中找到HelloWindow.ui文件,右键点击该文件,弹出菜单中选择生成对话框代码
在弹出的窗体代码产生器窗口中点击新建
弹出新建对话框类中输入类名后点击OK
回到窗体代码产生器窗口后展开Button_ok(QPushButton),勾选on_Button_ok_clicked(),点击OK
在项目浏览器中可以看到源代码标签下又多了一个HelloWindow.py文件
双击该文件查看程序内容。若现在F2,程序将会报错,将
from .Ui_HelloWindow import Ui_Dialog
中.Ui前面的点去掉
from Ui_HelloWindow import Ui_Dialog
保存后若F2,发现还是不行,程序一闪而过。给源码添加以下内容
保存后F2,没问题了,可以点击确定按钮后还是会报错,是因为我们还没有告诉程序点击确定按钮后程序做出什么反应,修改on_Button_ok_clicked函数如下
保存后F2,点击确定后Label内容显示会变成这是我的第一个 PyQt5 程序,一切正常
附录与后记
附加图:Label控件的位置与宽度
附加图:完成后的文件
虽然我们通过这个实例能够感受得到PyQt5与Eric6结合使用的强大功能与极速GUI开发的能力非比寻常,可是对于像我这样刚接触PyQt5与Eric6的童鞋来说,要想发挥PyQt5与Eric6的强大功能与极速开发也是痴人说梦,究其原因是PyQt5与Eric6的结合让我们只用少量的代码编写就可以实现很多强大的功能,几乎底层的代码都不用去自己编写,因此,PyQt5真正强大的内容离我们很远。
这个实例就像一层窗户纸被捅破了,但是我们根本就迈不过去。所以若要真的学会PyQt5我们还需多学些PyQt5的底层内容,多手动编写一些代码。当随着我们的PyQt5水平不断提高,到那时我们会发现PyQt5与Eric6结合使用才是如虎添翼,驰骋在程序的海洋。
最后将HelloWindow.py代码完整贴附如下:
Module implementing HelloWindow.
import sys
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtWidgets import QDialog, QApplication
from Ui_HelloWindow import Ui_Dialog
class HelloWindow(QDialog, Ui_Dialog):
Class documentation goes here.
def __init__(self, parent=None):
Constructor
@param parent reference to the parent widget
@type QWidget
super(HelloWindow, self).__init__(parent)
self.setupUi(self)
@pyqtSlot()
def on_Button_ok_clicked(self):
self.label.setText('这是我的第一个 PyQt5 程序')
if __name__ == '__main__':
app = QApplication(sys.argv)
dlg = HelloWindow()
dlg.show()
sys.exit(app.exec_())
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:129925次
积分:4267
积分:4267
排名:第7583名
原创:298篇
转载:20篇
(21)(2)(8)(9)(5)(7)(10)(4)(19)(11)(17)(45)(2)(10)(4)(26)(23)(7)(5)(1)(1)(2)(5)(12)(5)(1)(2)(1)(2)(2)(5)(1)(6)(32)(5)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'1308人阅读
Python(21)
一个典型的GUI应用程序可以抽象为:主界面(菜单栏、工具栏、状态栏、内容区域),二级界面(模态、非模态),信息提示(Tooltip),程序图标等组成。本篇根据作者使用PyQt5编写的一个工具,介绍如何使用PyQt5构建一个典型的GUI应用。
QMainWindow类提供一个有菜单条、锚接窗口(例如工具条)和一个状态条的主应用程序窗口。主窗口通常用在提供一个大的中央窗口部件(例如文本编辑或者绘制画布)以及周围菜单、工具条和一个状态条。QMainWindow常常被继承,因为这使得封装中央部件、菜单和工具条以及窗口状态变得更容易。
创建菜单的代码如下:
self.addMenu = self.menuBar().addMenu(&&添加&)
self.addMenu.addAction(self.addAvatarAct)
self.addMenu.addAction(self.addAvatarSetAct)
self.addMenu.addAction(self.addAvatarDecorationAct)
self.modifyMenu = self.menuBar().addMenu(&&修改&)
self.modifyMenu.addAction(self.modifyAvatarAct)
self.modifyMenu.addAction(self.modifyAvatarSetAct)
self.settingMenu = self.menuBar().addMenu(&&设置&)
self.settingMenu.addAction(self.settingAct)
其中每个菜单项,关联一个QAction,定义了图标、菜单名、回调函数、快捷键等等,这里没有设置快捷键。
self.addAvatarAct = QAction(QIcon(&res/ico/addAvatar.ico&), &&Add Avatar&, self, triggered=self.addAvatar)
self.addAvatarSetAct = QAction(QIcon(&res/ico/addAvatarSet.ico&), &&Add AvatarSet&, self, triggered=self.addAvatarSet)
self.addAvatarDecorationAct = QAction(QIcon(&res/ico/addAvatarDecoration.ico&), &&Add AvatarDecoration&, self, triggered=self.addAvatarDecoration)
self.modifyAvatarAct = QAction(QIcon(&res/ico/modifyAvatar.ico&), &&Modify Avatar or Decoration&, self, triggered=self.modifyAvatar)
self.modifyAvatarSetAct = QAction(QIcon(&res/ico/modifyAvatarSet.ico&), &&Modify AvatarSet&, self, triggered=self.modifyAvatarSet)
self.settingAct = QAction(QIcon(&res/ico/settingPath.ico&), &&路径&, self, triggered=self.settingPath)
self.homeAct = QAction(QIcon(&res/ico/home.ico&), &&首页&, self, triggered=self.homePage)
说明:QAction类提供了一个可以同时出现在菜单和工具条上的抽象用户界面操作。
在图形用户界面应用程序中很多命令可以通过菜单选项、工具条按钮和键盘快捷键调用。因为同一个操作将会被执行,而与它的调用方法无关,并且因为菜单和工具条必须保持同步,所以提供一个操作这样的命令很有用。一个操作可以被添加到菜单和工具条中并且将会自动使它们同步。例如,如果用户按下“加粗”工具条按钮,“加粗”菜单项将会自动被选中。
QAction可以包含图标、菜单文本、快捷键、状态条文本、这是什么文本和工具提示。它们可以分别通过()、()、()、()、()、()和()来设置。
创建工具栏的代码如下:
self.toolbar = self.addToolBar('Home')
self.toolbar.addAction(self.homeAct)
self.toolbar = self.addToolBar('AddAvatar')
self.toolbar.addAction(self.addAvatarAct)
self.toolbar = self.addToolBar('AddAvatarDecoration')
self.toolbar.addAction(self.addAvatarDecorationAct)
self.toolbar = self.addToolBar('AddAvatarSet')
self.toolbar.addAction(self.addAvatarSetAct)
self.toolbar = self.addToolBar('ModifyAvatar')
self.toolbar.addAction(self.modifyAvatarAct)
self.toolbar = self.addToolBar('ModifyAvatarSet')
self.toolbar.addAction(self.modifyAvatarSetAct)
工具栏项也需要关联一个QAction,可以和菜单项共用一个QAction,即一个QAction可以被关联到多个地方。
设置状态栏,只需要:
self.statusBar().showMessage(&数据加载完成&)
第一次调用self.statusBar()获取工具栏时,会初始化工具栏实例,后面再次调用不会在创建新的实例。
程序图标分为2个:程序窗口图标;执行文件的图标。
l&&setWindowIcon(QIcon(“res/ico/icon.ico”))设置程序窗口的图标
l&&执行文件的图标,通过打包工具设置
PyQt的布局系统提供了一个规定子窗口部件布局的简单的和强有力的方式。当你一旦规定了合理的布局,你就会获得如下利益:
l&&布置子窗口部件。
l&&最高层窗口部件可感知的默认大小。
l&&最高层窗口部件可感知的最小大小。
l&&调整大小的处理。
l&&当内容改变的时候自动更新:
n&&字体大小、文本或者子窗口部件的其它内容。
n&&隐藏或者显示子窗口部件。
n&&移去一些子窗口部件。
PyQt支持的布局方式有很多,如下表所示:
布局相关类
QBoxLayout
Lines up child widgets horizontally or vertically
QButtonGroup
Container to organize groups of button widgets
QFormLayout
Manages forms of input widgets and their associated labels
QGraphicsAnchor
Represents an anchor between two items in a QGraphicsAnchorLayout
QGraphicsAnchorLayout
Layout where one can anchor widgets together in Graphics View
QGridLayout
Lays out widgets in a grid
Group box frame with a title
QHBoxLayout
Lines up widgets horizontally
The base class of geometry managers
QLayoutItem
Abstract item that a QLayout manipulates
QSizePolicy
Layout attribute describing horizontal and vertical resizing policy
QSpacerItem
Blank space in a layout
QStackedLayout
Stack of widgets where only one widget is visible at a time
QStackedWidget
Stack of widgets where only one widget is visible at a time
QVBoxLayout
Lines up widgets vertically
QWidgetItem
Layout item that represents a widget
其中使用比较多的是以下布局方式(或者说是我使用比较多,不代表大家):
水平布局&QHBoxLayout垂直布局&QVBoxLayout网格布局&QGridLayout
水平布局(QHBoxLayout)顾名思义,将空间水平切成多段,然后通过addWidget、addItem将widget填充指定的位置。如下代码即实现了上图中,适合角色选择的水平布局:
hbox = QHBoxLayout()
self.roleChkBoxGroup.setLayout(hbox)
for _, v in sorted(ParseKeywords.profession.items()):
&&&&&&&&&checkBox = QRadioButton(v[&cname&] + & & + str(v[&value&]))
&&&&&&&&&hbox.addWidget(checkBox)
删除一个控件,使用removeWidget,或者调用QWidget.hide()一样可以从布局中删除,直到QWidget.show()被调用。下面的垂直布局、网格布局,甚至其他布局都是注意的。
垂直布局(QVBoxLayout)顾名思义,将空间垂直切成多段,然后通过addWidget、addItem将widget填充指定的位置。如下代码即实现了上图中,细节信息的垂直布局(垂直布局中,还嵌套了水平布局):
vbox = QVBoxLayout()
groupBox.setLayout(vbox)
count = QWidget()
hbox = QHBoxLayout()
countLabel = QLabel(&细节数目:&)
hbox.addWidget(countLabel)
self.countSpineBox = QSpinBox()
self.countSpineBox.setRange(0, 10)
self.countSpineBox.valueChanged.connect(self.countSpineValueChanged)
hbox.addWidget(self.countSpineBox)
hbox.addStretch()
count.setLayout(hbox)
vbox.addWidget(count)&&&#垂直布局,添加widget1
self.detailTable = QTableWidget()
self.detailTable.setColumnCount(9)
self.detailTable.setHorizontalHeaderLabels(
&&&&&&&&&['有效期', '货币类型', '价格',
'普通折扣价', '蓝钻价', '蓝钻折扣价', '超级蓝钻折扣价',
'赠送礼包ID', '快捷购买'])
vbox.addWidget(self.detailTable)&&&#垂直布局,添加widget2
垂直布局中,还嵌套了水平布局。
说明:QHBoxLayout、QVBoxLayout都是继承自QBoxLayout,为了更好的控制布局,都继承了以下方法:
l&&QBoxLayout.addSpacing (size)
&&&添加一个不能伸缩的空间(一个QSpacerItem),其宽度设置为size到布局末尾。框布局提供了默认的边距margin和spacing,这是额外添加的空间。
l&&QBoxLayout.addStretch(stretch)
&&&添加一个可伸缩的空间(一个QSpacerItem),设0为最小值并且伸缩因子为stretch直到布局末尾
网格布局(QGridLayout)顾名思义,将空间划分成多行多列的网络,然后通过addWidget、addItem将widget填充到指定的单元格(cell)。这个比较像网页中使用table布局的思路。下面的代码即创建上图中的网格布局:
grid = QGridLayout()
grid.addWidget(setidLabel, 0, 0)
grid.addWidget(self.setidLineEdit, 0, 1)
grid.addWidget(QLabel(&(第1位-2,第2~3位-表示适用角色,第4~5位-挂点位置,第6~8位-序号)&),
grid.addWidget(subidLabel, 1, 0)
grid.addWidget(self.subidLineEdit, 1, 1)
grid.addWidget(QLabel(&(套装包含的物品,多个物品适用逗号分隔;必须在套装之前添加)&), 1, 2)
grid.addWidget(fashionLabel, 2, 0)
grid.addWidget(self.fashionLineEdit, 2, 1)
grid.addWidget(nameLabel, 3, 0)
grid.addWidget(self.nameLineEdit, 3, 1)
grid.addWidget(descLabel, 4, 0)
grid.addWidget(self.descLineEdit, 4, 1)
grid.addWidget(marketTagLabel, 5, 0)
grid.addWidget(self.tagCombox, 5, 1)
grid.addWidget(recommendLabel, 6, 0)
grid.addWidget(self.recommendCombox, 6, 1)
grid.addWidget(roleLabel, 8, 0)
grid.addWidget(self.roleChkBoxGroup, 8, 1)
grid.addWidget(beginLabel, 9, 0)
grid.addWidget(self.beginTime, 9, 1)
grid.addWidget(endLabel, 10, 0)
grid.addWidget(self.endTime, 10, 1)
gridWidget = QWidget()
gridWidget.setLayout(grid)
上述往网格中添加的widget都是占一个单元格的情况,其实还支持占用几个单元格。如下代码,往网格中的第二行、第一列添加一个widget,占用1行、2列:
grid.addWidget(self.createDetail(), 1, 0,&1, 2)
网格布局默认是均分每列,为了更好的控制布局,QGridLayout为每列提供了最小宽度(setColumnMinimumWidth())、伸缩因子(setColumnStretch()),为每行提供了最小高度(setRowMinimumHeight())、伸缩因子(setRowStretch())。最小宽/高度很好理解,伸缩因子如下面代码,设置了第二列和三列的比例是1:2。
layout.setColumnStretch(1, 10)
layout.setColumnStretch(2, 20)
3.&二级弹窗
QDialog类是对话框窗口的基类。对话框窗口是主要用于短期任务以及和用户进行简要通讯的顶级窗口。QDialog可以是模态对话框也可以是非模态对话框。QDialog支持扩展性并且可以提供返回值。它们可以有默认按钮。
内置对话框
内置常用的对话框有:、、、、、、、、。
内置的对话框提供了一些常用的功能,使用起来也必将遍历。编写该工具使用到了,选择文件、目录的对话框QFileDialog。
自定义对话框
如果内置的对话框不能满足需求,可以自定义对话框(继承自QDialog)。如下定义了一个设置路径的对话框:
class SettingDialog(QDialog):&
&&& def __init__(self, parent=None):&
&&&&&&& super(SettingDialog, self).__init__(parent)&
&&&&&&& self.path = Global.path&
&&&&&&& self.initUI()&
&&&&&&& self.setWindowIcon(QIcon(&res/ico/settingPath.ico&))&
&&&&&&& self.setWindowTitle(&设置&)&
&&&&&&& self.resize(240, 100)&
&&& def initUI(self):&
&&&&&&& grid = QGridLayout()&
&&&&&&& grid.addWidget(QLabel(&路径:&), 0, 0)&
&&&&&&& self.pathLineEdit = QLineEdit()&
&&&&&&& self.pathLineEdit.setFixedWidth(200)&
&&&&&&& self.pathLineEdit.setText(Global.path)
&&&&&&& grid.addWidget(self.pathLineEdit, 0, 1)&
&&&&&&& button = QPushButton(&更改&)&
&&&&&&& button.clicked.connect(self.changePath)&
&&&&&&& grid.addWidget(button, 0, 2)&
&&&&&&& grid.addWidget(QLabel(&&font color='#ff0000'&包含Keywords.xml、Avatar,AvatarSet,Market.xls的路径&/font&&),
1, 0, 1, 3)&
&&&&&&& buttonBox = QDialogButtonBox()&
&&&&&&& buttonBox.setOrientation(Qt.Horizontal)& #&设置为水平方向
&&&&&&& buttonBox.setStandardButtons(QDialogButtonBox.Ok|QDialogButtonBox.Cancel)&
&&&&&&& buttonBox.accepted.connect(self.accept)& #&确定
&&&&&&& buttonBox.rejected.connect(self.reject)& #&取消
&&&&&&& grid.addWidget(buttonBox, 2, 1)&
&&&&&&& self.setLayout(grid)&
&&& def changePath(self):&
&&&&&&& open = QFileDialog()&
&&&&&&& self.path = open.getExistingDirectory()&
&&&&&&& self.pathLineEdit.setText(self.path)&
&&&&&&& print(self.path)
使用对话框,只需要:
dialog = SettingDialog()&
if dialog.exec_():
&&&&&& # -----
4.&常用组件
下面介绍编写工具过程中使用到的组件的一些注意事项。
QTableWidget
如果有很多列,QTableWidget出出现水平滚动条,但是有不希望有滚动条可以通过设置列自适应方式:
tw.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
保证所以列都能显示,不会出现水平滚动条,这样有的单元格显示会被截断显示,如图中的&青年套装下装&--&&青年套装...&,这时可以设置单元的tooltip提供完整显示的途径。
编写工具时,有要求QTableWidget展示出来的数据不能编辑,是通过以下方式实现:
tw.setEditTriggers(QAbstractItemView.NoEditTriggers)
QAbstractItemView还定义了其它的模式,如下表所示:
Description
QAbstractItemView.NoEditTriggers
No editing possible.
QAbstractItemView.CurrentChanged
Editing start whenever current item changes.
QAbstractItemView.DoubleClicked
Editing starts when an item is double clicked.
QAbstractItemView.SelectedClicked
Editing starts when clicking on an already selected item.
QAbstractItemView.EditKeyPressed
Editing starts when the platform edit key has been pressed over an item.
QAbstractItemView.AnyKeyPressed
Editing starts when any key is pressed over an item.
QAbstractItemView.AllEditTriggers
Editing starts for all above actions.
设置QTableWidget按行选择:
tw.setSelectionBehavior(QAbstractItemView::SelectRows);& //整行选中的方式
QAbstractItemView还定义了其它的模式,如下表所示:
Description
QAbstractItemView.SelectItems
Selecting single items.
QAbstractItemView.SelectRows
Selecting only rows.
QAbstractItemView.SelectColumns
Selecting only columns.
如果希望单击QTableWidget表头进行数据排序,可以简单通过以下接口实现:
tw.setSortingEnabled(True)
但是,排序需要注意的2个问题:
l&&点了下qtablewidget&的标题,它排序正常,修改数据,在查询,数据显示有问题
重新获取数据之前先关闭可排序性,获取到数据之后再开启排序性
l&&排序规则问题,默认使用字母排序
使用以下方式设置单元格,会使用字母排序
item = QTableWidgetItem()
item.setData(Qt.DisplayRole, &xxx&)
item = QTableWidgetItem()
item.setText(&xxx&)
如果需要按照数值排序需要使用以下方式设置单元格
item = QTableWidgetItem()
item.setData(Qt.DisplayRole, int(1212))
自定义单元格控件
可以对QTableWidget自定义(添加)widget,如下为QTableWidget设置单元格为一个下拉选择的QCombox
combox = QComboBox()
for _, v in ParseKeyword.currencyType.items():
&&&&&&&&&combox.addItem(v[&cname&], v[&value&])
combox.setCurrentText(&点券&)
tw.setCellWidget(row, 1, combox)
效果如下图所示:
QDateTimeEdit
显示格式
默认的时间显示格式(如 17:42),可能不满足需求,可以通过setDisplayFormat()设置显示格式来定制。格式选项如下所示:
这些是可能用到的日期表达式:
l&&d&-&没有前置0的数字的天(1-31)
l&&dd&-&前置0的数字的天(01-31)
l&&ddd&-&缩写的日名称(Mon-Sun)。使用QDate.shortDayName()。
l&&dddd&-&长的日名称(Monday-Sunday)。使用QDate.longDayName()。
l&&M&-&没有前置0的数字的月(1-12)
l&&MM&-&前置0的数字的月(01-12)
l&&MMM&-&缩写的月名称(Jan-Dec)。使用QDate.shortMonthName()。
l&&MMMM&-&长的月名称(January-December)。使用QDate.longMonthName()。
l&&yy&-&两位数字的年(00-99)
l&&yyyy&-&四位数字的年()
这些是可能用到的时间表达式:
l&&h -&没有前置0的数字的小时(0-23或者如果显示AM/PM时,1-12)
l&&hh -&前置0的数字的小时(00-23或者如果显示AM/PM时,01-12)
l&&m -&没有前置0的数字的分钟(0-59)
l&&mm -&前置0的数字的分钟(00-59)
l&&s -&没有前置0的数字的秒(0-59)
l&&ss -&前置0的数字的秒(00-59)
l&&z -&没有前置0的数字的毫秒(0-999)
l&&zzz -&前置0的数字的毫秒(000-999)
l&&AP -&切换为AM/PM显示。AP将被“AM”或“PM”替换。
l&&ap -&切换为am/pm显示。ap将被“am”或“pm”替换。
如工具中使用的格式为:
setDisplayFormat(&yyyy-MM-dd hh:mm:ss&)
显示效果如下图所示:
弹出日期选择窗口
希望点击QDateTimeEdit可以弹出日期选择窗口,可以简单的通过setCalendarPopup(True)实现,非常的简单。
python常用的打包工具有py2exe、pyinstaller、cx_freeze,而且现在都开始支持python3,py2exe可以打包成单exe文件,一般简单的东西都是用它来打包供其他人使用。但是使用py2exe打包PyQt5时,碰到了不少错误,后面干脆使用cx_freeze打包一次成功(不足之处,就是不能打包成单个exe)。下面简单介绍编写setup.py几个关键的点,详细的参考官方文档()。
l&&默认只会打包代码文件,如果程序有非代码文件,如配置、资源文件需要打包,需要显示指定。如&include_files&: [&setting.ini&, &res&],打包时会将setting.ini文件、res资源目录拷贝到exe目录下。
l&&cx_freeze会自动检测依赖文件,但是有时候会抽风,可以通过&packages&: [&os&, &xlrd3&, &xlwt3&, &lxml&]显示包含。同时对不要的包,可以&excludes&: [&tkinter&]指定不要编译到最终的软件包中。
l&&指定文件名需要带exe后缀,cx_freeze是不会自动添加exe后缀的。
l&&如果需要一次编译多个exe,可以在executables数组中列出多个,例如:
executables = [&
Executable(&main.py&, base=base, targetName=&Joker3DAvatarMgr.exe&, compress=True, icon=&res/ico/icon.ico&),
Executable(&test.py&, base=base, targetName=&test.exe&, compress=True, icon=&res/ico/test.ico&)&
完整的setup.py文件如下所示:
import sys&
from cx_Freeze import setup, Executable&
# GUI applications require a different base on Windows (the default is for a&
# console application).&
base = None&
if sys.platform == &win32&:&
base = &Win32GUI&&
# Dependencies are automatically detected, but it might need fine tuning.&
build_exe_options = {&
&packages&: [&os&, &xlrd3&, &xlwt3&, &lxml&],&
&excludes&: [&tkinter&],&
&include_files&: [&setting.ini&, &res&]&
executables = [&
Executable(&main.py&, base=base, targetName=&Joker3DAvatarMgr.exe&, compress=True, icon=&res/ico/icon.ico&)&
setup( name = &setup&,&
version = &0.1&,&
description = &Joker3D prop manager tool!&,&
author = &tylerzhu&,&
author_email = &&,&
options = {&build_exe&: build_exe_options},&
executables = executables,&
编写好setup.py之后,可以通过python setup.py build打包。
网上有不少人反馈打包之后,放到没有按照PyQt的PC上执行,会报以下错误:“This application failed to start because it could not find or load the Qt platform plugin windows”
这个问题,我以前也碰到过,但是这次我用的Python3.4 + cx_freeze 4.3.4 + PyQt5-5.4-gpl-Py3.4-Qt5.4.0-x32.exe并没有出现这个问题。如果出现了这个问题也不要紧,通过以下方法可以解决:将PyQt5安装目录(Lib\site-packages\PyQt5)下的libGLESv2.dll拷到打包的exe目录下即可。
本文作者:
原文链接:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:135455次
积分:1690
积分:1690
排名:千里之外
原创:27篇
转载:42篇
评论:10条
(1)(2)(6)(2)(2)(1)(1)(3)(2)(1)(2)(2)(6)(5)(8)(1)(1)(1)(3)(3)(1)(5)(7)(1)(2)
(window.slotbydup = window.slotbydup || []).push({
id: '4740881',
container: s,
size: '200,200',
display: 'inlay-fix'}

我要回帖

更多关于 pyqt开发环境 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信