精华内容
参与话题
问答
  • PyQt5(designer)入门教程

    万次阅读 多人点赞 2019-05-19 08:39:36
    PyQt5入门教程 注:这是当时闲着无聊写到github page的,在CSDN上也看了大佬们各种各样的教程跟疑难杂症解答,感觉我这个不放出来也有点可惜,希望各位能够从中收益吧。 在网上看了不少关于PyQt5的中文教程,但是无...

    PyQt5入门教程

    2019/12/11更新:我平时不看CSDN的,之前一时兴起发了过来,没想到反响还不错。这次就顺便把后来新增的一个小节放上来,并且在文末增加了我的GitHub(一看GitHub就知道我是个菜鸡,大家都是互相学习啦~)

    注:这是当时闲着无聊写到github page的,在CSDN上也看了大佬们各种各样的教程跟疑难杂症解答,感觉我这个不放出来也有点可惜,希望各位能够从中收益吧。

    在网上看了不少关于PyQt5的中文教程,但是无外乎是过时了,讲解不清晰易懂,或者资料不完整。Youtube上面倒是有不少视频,但是不少Youtuber居然还在手写ui而不是利用方便快捷的Qt Designer。仅有的几个视频虽然利用了Qt Designer来设计UI,但是他们并没有将UI跟逻辑分离,这种行为并不是我期望的。

    为此,我花费了不少时间在网上寻找各种资料。于是乎,我最终还是下定决心把自己的学习过程给记录下来。记录下来是给我自己复习跟参考的,如果有人能够从中受益,那也挺好,不用浪费时间去到处找答案。

    0x00 安装环境清单

    我使用的环境如下:

    • Windows 10 (Build 17763)
    • Python 3.7.2
    • VSCode 1.33.0
    • PyQt5
    • Qt Designer

    如果你使用的是OSX或者Linux,请自行替换教程中的一些操作。

    本文并不讨论Python和VSCode的安装,如果没有VSCode,你可以用各种同类IDE替代或者安装它。

    本文不讨论多Python共存,毕竟Python2.7在2020年就要退役了,而且我本人也没这需求。

    0x01 安装PyQt5

    下面直接使用pip来安装PyQt5,此处可能是pip/pip3,或者两者皆可,后面不再重复

    直接pip安装PyQt5

    pip install PyQt5
    

    由于Qt Designer已经在Python3.5版本从PyQt5转移到了tools,因此我们还需要安装pyqt5-tools

    pip install pyqt5-tools
    

    到这一步,PyQt5就安装完成了,你可以通过下面若干可选的操作来检查是否已经安装成功:

    • Win+S呼出Cornata主面板(搜索框),输入designer,如果看到跟下图类似的结果说明PyQt Designer已经被安装

    designer_install

    • 在cmd中输入pyuic5,如果返回“Error: one input ui-file must be specified”说明安装成功。

    0x02 初识Qt Designer

    注:Qt Designer的界面是全英文的,幸运的是有汉化方法,不过因为我本人用不上,所以如果有这方面需求可以自行搜索。

    我比较习惯用Win+S呼出Cornata主面板(搜索框)来启动各种应用,那么这里就是在搜索框中输入designer并敲回车,就能够启动Qt Designer了。

    初次启动会弹出这个“New Form”窗口,一般来说选择“Main Window”然后点击“Create”就可以了。下方有个“Show this Dialogue on Startup”的checkbox,如果不想每次启动都看到这个“New Form”窗口,可以取消勾选。

    new_form
    创建“Main Window”之后,我们会看到如下画面

    designer_ui
    下面就来简单介绍下整个画面的构成:

    • 左侧的“Widget Box”就是各种可以自由拖动的组件

    • 中间的“MainWindow - untitled”窗体就是画布

    • 右上方的"Object Inspector"可以查看当前ui的结构

    • 右侧中部的"Property Editor"可以设置当前选中组件的属性

    • 右下方的"Resource Browser"可以添加各种素材,比如图片,背景等等,目前可以不管

    大致了解了每个板块之后,就可以正式开始编写第一个UI了

    0x03 HelloWorld!

    注:从这里开始,相关代码可以在/assets/code/pyqt5中找到

    注:本文用到的代码都在我github,就不在CSDN这里上传了

    通常来说,编写GUI有两种方法:第一种就是直接使用方便快捷的Qt Designer,第二种就是写代码。在有Qt Designer的情况下,是完全不推荐费时费力去手写GUI代码的。Qt Designer可以所见即所得,并且可以方便的修改并做出各种调整。

    按照惯例,我们先来实现一个能够显示HelloWorld的窗口。

    1)添加文本

    在左侧的“Widget Box”栏目中找到“Display Widgets”分类,将“Label”拖拽到屏幕中间的“MainWindow”画布上,你就获得了一个仅用于显示文字的文本框,如下图所示。

    designer_create_label

    2)编辑文本

    双击上图中的“TextLabel”,就可以对文本进行编辑,这里我们将其改成“HelloWorld!”,如下图所示。如果文字没有完全展示出来,可以自行拖拽空间改变尺寸。

    特别提醒,编辑完文本之后记得敲击回车令其生效!

    designer_change_label_text

    3)添加按钮

    使用同样的方法添加一个按钮(PushButton)并将其显示的文本改成“HelloWorld!”,如下图所示。

    designer_create_pushbutton

    4)修改窗口标题

    下面修改窗口标题。选中右上方的"Object Inspector"中的“MainWindow”,然后在右侧中部的"Property Editor"中找到“windowTitle”这个属性,在Value这一栏进行修改,修改完记得敲击回车。

    5)编辑菜单栏

    注意到画布的左上方有个“Type Here”,双击它即可开始编辑菜单栏。菜单栏支持创建多级菜单以及分割线(separator)。我随意创建了一些菜单项目,如下图所示。

    designer_create_menu

    6)预览

    使用快捷键Ctrl+R预览当前编写的GUI(或者从菜单栏的Form > Preview / Preview in进入)

    designer_preview

    7)保存

    如果觉得完成了,那就可以保存成*.ui的文件,这里我们保存为HelloWorld.ui。为了方便演示,我将文件保存到D盘。

    8)生成Python代码

    使用cmd将目录切到D盘并执行下面的命令。请自行将下面命令中的name替换成文件名,比如本例中的“HelloWorld.ui”

    pyuic5 -o name.py name.ui
    

    生成的代码应该类似下图所示

    designer_code_helloworld

    9)运行Python代码

    此时尝试运行刚刚生成的“HelloWorld.py”是没用的,因为生成的文件并没有程序入口。因此我们在同一个目录下另外创建一个程序叫做“main.py”,并输入如下内容。在本例中,gui_file_name就是HelloWorld,请自行替换。

    import sys
    from PyQt5.QtWidgets import QApplication, QMainWindow
    
    import gui_file_name
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        MainWindow = QMainWindow()
        ui = gui_file_name.Ui_MainWindow()
        ui.setupUi(MainWindow)
        MainWindow.show()
        sys.exit(app.exec_())
    

    然后运行“main.py”,你就能看到刚刚编写的GUI了!

    designer_run_helloworld

    10)组件自适应

    如果你刚刚尝试去缩放窗口,会发现组件并不会自适应缩放,因此我们需要回到Qt Designer中进行一些额外的设置。

    点击画布空白处,然后在上方工具栏找到grid layout或者form layout,在本例中我们使用grid layout。两种layout的图标如下图所示。

    designer_layout_helloworld

    顺带一提,上图中layout的左边有三条横线以及三条竖线的图标,这两个是用于对齐组件,非常实用。

    设置grid layout后,我们使用Ctrl+R预览,这次组件可以自适应了!因为我们已经将UI(HelloWorld.py/HelloWorld.ui)跟逻辑(main.py)分离,因此直接重复步骤7-8即可完成UI的更新,无需改动逻辑(main.py)部分。

    0x04 Interaction

    刚刚写的HelloWorld中,我们设置的按钮(PushButton)是没有实际作用的,因为我们并没有告诉这个按钮应该做什么。实际上,要让这个按钮做点什么只需要增加一行代码就可以了。

    1)获取按钮id

    打开HelloWorld.ui,在designer中选中对应的按钮,从“Property Editor”中可以得知这个按钮的“objectName”叫做“pushButton”,如下图所示。

    designer_pushbutton_id

    2)设置触发

    Qt中有“信号和槽(signal and slot)”这个概念,不过目前无需深究,也无需在Designer中去设置对应按钮的“信号和槽”,直接在“main.py”中“MainWindow.show()”的后面加入下面这样的一行代码

    ui.pushButton.clicked.connect(click_success)
    

    下面简单解释下这行代码

    • pushButton就是刚刚获取的按钮id
    • clicked就是信号,因为是点击,所以我们这里用clicked
    • click_success就是对应要调用的槽,注意这里函数并不写成click_success()

    3)设置函数

    既然刚刚设置了按钮的触发并绑定了一个函数click_success,我们就要在“main.py”中实现它。示例如下

    def click_success():
        print("啊哈哈哈我终于成功了!")
    

    4)运行!

    UI跟逻辑分离的好处就在这里,我们这次不用去管“HelloWorld.py”了,直接运行修改完的“main.py”。点击按钮,这次你会发现在控制台中有了我们预设的输出。

    0x05 Conversion

    这次我们来进行实战演练,编写一个带GUI的汇率转换器。

    1)设计UI

    conversion_ui

    通过上面的讲解,你应该能够毫无压力的设计上面这样的UI并获得对应的代码。如果不行,那么不建议继续往下阅读,应当回头复习。

    2)传参

    现在我们有了GUI的代码以及上一节中使用的“main.py”,我们可以开始编写这个汇率转换器的逻辑部分。

    在上一节,我们介绍了如何让按钮响应点击操作,但是并没有接受任何参数,而且只是在控制台输出。但是,上一节中说明了并不能通过正常的方式进行传参。因此,对于传参,有两种解决方案,一种是使用lambda,还有一种是使用functool.partial。在接下来的环节中我们会使用partial。

    partial的用法如下所示:

    partial(function, arg1, arg2, ......)
    

    既然使用partial传参,那么我们就要在程序(main.py)的头部加上下面这行。

    from functools import partial
    

    然后我们把上一节中的按钮触发那行代码修改成下面这样。

    ui.pushButton.clicked.connect(partial(convert, ui))
    

    3)编写convert函数

    首先,我们要获取用户输入的数字。为了使得教程简洁易懂,我们这次只讲解单向的汇率转换。既然是单项的转换,那么我们只需要获取左侧的文本框id。在本例中,左侧的文本框id为lineEdit。如果你对此感到一头雾水,请停下并回头复习。

    获取文本使用的是text()方法,因此读取用户输入的代码如下

    input = ui.lineEdit.text()
    

    接着我们进行汇率转换,注意这里要进行类型转换

    result = float(input) * 6.7
    

    最后我们让右边的文本框显示结果

    ui.lineEdit_2.setText(str(result))
    

    下面是convert函数的代码

    def convert(ui):
        input = ui.lineEdit.text()
        result = float(input) * 6.7
        ui.lineEdit_2.setText(str(result))
    

    一个简单的汇率转换器就这样诞生了!

    那么,如何知道一个组件都有什么方法呢?直接去Qt官方文档查看就可以了。本节使用到的lineEdit的相关方法在这里

    0x06 threading

    1)前言

    这几天在用PyQt5写东西的时候遇到这样一个问题,网上资料也特别少,我感觉值得拿出来说一说。

    我的程序中使用了threading模块,GUI作为主线程去启动负责逻辑处理的子线程。其中,我设计的GUI里头有一个日志框,用来代替终端显示各种日志输出。既然子线程是负责逻辑处理,那么想当然的就会直接在子线程操作GUI的显示。

    都说了想当然,那当然不行咯,在子线程对GUI操作的时候,终端会出现下面这个错误,但是程序又不会马上闪退。

    QObject::connect: Cannot queue arguments of type 'QTextCursor'
    (Make sure 'QTextCursor' is registered using qRegisterMetaType().)
    

    更让人摸不着头脑的是,过一阵子闪退的时候,会出现下面这句话:

    段错误,核心已转储
    

    这啥玩意儿?能说人话么?一番搜索之后,发现这个原来英语叫做“Segmentation fault (core dumped)”。

    "Segmentation fault"用人话来说大概就是“你尝试访问你无法访问的内存”。

    然后我把上面的报错信息搜索了下,发现之前有人在StackOverflow问过,但是答案牛头不对马嘴,不过倒是在评论区发现了大佬的留言。

    It is likely that the asker was not actually directly using QTextCursor, but rather using GUI code from a thread that was not the GUI thread. Attempting this seems to result in this error arising from Qt-internal code, e.g. for QTextEdit.append()
    

    简而言之,就是说虽然报错显示QTextCursor,但是实际上是在其它线程通过Qt内部的方法间接调用了这个东西。

    热心大佬还留了个链接,我跟过去看了,收获不少。

    It appears you're trying to access QtGui classes from a thread other than the main thread. Like in some other GUI toolkits (e.g. Java Swing), that's not allowed.
    
    Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread.
    

    这个终于说到点子上了,一句话总结就是子线程不能调用主线程的QtGui类。

    所以大佬给出的方案如下:

    A solution is to use signals and slots for communication between the main thread (where the GUI objects live) and your secondary thread(s). Basically, you emit signals in one thread that get delivered to the QObjects via the other thread.
    

    大概翻译下,就是说可以通过信号和槽来完成子线程跟GUI所在的主线程的通信,就是通过在子线程释放信号,传递到主线程的槽来完成。

    可惜的是,大佬并没有给出示例代码,那接下来就是动手实践了。

    2)实践

    首先我们在子线程的代码中创建一个对象,并且继承QObject(因为需要释放信号)。

    class UpdateLog(QObject):
        update_signal = pyqtSignal()
     
        def __init__(self):
            QObject.__init__(self)
     
        def update(self):
            self.update_signal.emit()
    

    update_signal = pyqtSignal()就是使用Signal类来创建一个自定义的信号。

    self.update_signal.emit()就是当条件满足的时候,子线程可以调用UpdateLog类的update方法,就会发出信号。

    做完这些之后,主线程中别忘了连击信号和槽,比如self.afk.utils.logger.update_signal.connect(self.write_log)。然后现在再尝试运行程序,就没有任何问题了。

    不仅如此,其实其它需要共享的信息,也可以通过自定义信号和槽来传递。

    那么,现在就可以愉快的在PyQt程序中使用threading模块了。

    0x0? 小结

    本文只是抛砖引玉,上面这些只是PyQt5的入门内容。不过学会了简单的交互方法,其它的也差不多能依葫芦画瓢做出来。

    本文中设计的程序在/assets/code/pyqt5中。

    那么,就先写到这里了!

    0xff Info

    我不是大佬,不是CS专业的,水平相对比较菜,只是一个对计算机感兴趣的业余爱好者,在这方面基本上是自学成才,毕竟兴趣是第一生产力嘛~

    我的GitHub

    其中这个tree项目的GitHub Page就放了些乱七八糟的自学笔记,有到处搜刮的也有原创的。有帮助的话不如给我这个tree项目点个星呗(手动滑稽)。

    展开全文
  • PyQt5案例汇总(完整版)

    千次阅读 多人点赞 2019-11-03 23:47:42
    PyQt5案例汇总(完整版) 起步 PyQt5是一套绑定Qt5的应用程序框架。他在Python 2.x和3.x中都是可用的。该教程使用的是Python3.x。 Qt库是一套最有用的GUI库。 PyQt5是作为一套Python模块实现的。他已经超过620个类和...

    个人博客点这里

    PyQt5案例汇总(完整版)

    起步

    PyQt5是一套绑定Qt5的应用程序框架。他在Python 2.x和3.x中都是可用的。该教程使用的是Python3.x。

    Qt库是一套最有用的GUI库。

    PyQt5是作为一套Python模块实现的。他已经超过620个类和6000个函数与方法。他是一个运行在所有主流操作系统上的多平台组件,包括Unix,Windows和Mac OS。

    说明

    下面小编就给大家提供一些简单的pyqt5的案例,如有需要拿走不谢!!!

    本文转载from:PyQt5-Chinese-tutorial

    菜单栏和工具栏

    01窗口居中

    
    # 导入需要的包和模块
    import sys
    from PyQt5.QtWidgets import QWidget
    from PyQt5.QtWidgets import QDesktopWidget
    # QDesktopWidget这个库提供了用户的桌面信息,包括屏幕的大小
    from PyQt5.QtWidgets import QApplication
    
    # 创建一个类
    class Ex(QWidget):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            self.resize(250,150)
            self.center()
            # 这个方法调用我们下面写的,实现对话框居中的方法
            self.setWindowTitle('chuangkou要居中')
            self.show()
    
        def center(self):
            qr = self.frameGeometry()
            # 得到了主窗口大小
            print('qr:',qr)
            cp = QDesktopWidget().availableGeometry().center()
            # 获取显示器的分辨率,然后得到中间点的位置
            print('cp:',cp)
            qr.moveCenter(cp)
            # 然后把自己的窗口的中心点放到qr的中心点
            self.move(qr.topLeft())
    
    app = QApplication(sys.argv)
    demo1 = Ex()
    sys.exit(app.exec_())
    

    02 状态栏

    
    # 导入需要的包和模块
    import sys
    # from PyQt5.QtWidgets import QWidget
    # from PyQt5.QtWidgets import QDesktopWidget
    # QDesktopWidget这个库提供了用户的桌面信息,包括屏幕的大小
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtWidgets import QMainWindow
    
    
    class Ex(QMainWindow):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            # 状态栏是由这个创建的
            self.statusBar().showMessage('准备')
            # 调用QtGui.QMainWindow 类的 statusBar()方法
            #3 创建状态栏.第一次调用创建一个状态栏,返回一个状态栏对象.
            #3 showMessage()方法在状态栏上显示一条信息
            self.setGeometry(300,300,250,150)
            self.setWindowTitle('标题还是要取的')
            #显示
            self.show()
    
    app = QApplication(sys.argv)
    demo1 = Ex()
    sys.exit(app.exec_())
    
    

    03菜单栏

    
    import sys
    from PyQt5.QtWidgets import QMainWindow
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtWidgets import QAction
    from PyQt5.QtWidgets import qApp
    from PyQt5.QtGui import QIcon
    
    class Ex(QMainWindow):
    
        def __init__(self):
            super(Ex, self).__init__()
            self.initUI()
    
        def initUI(self):
            exitAct = QAction(QIcon("exit.png"),'&Exit',self)
            print(exitAct)
            exitAct.setShortcut("ctrl+q")
            exitAct.setStatusTip('tuichu应用')
            exitAct.triggered.connect(qApp.quit)
    
            self.statusBar()
    
            menubar = self.menuBar()
            fileMenu = menubar.addMenu('&File')
            fileMenu.addAction(exitAct)
    
            self.setGeometry(300,300,399,200)
            self.setWindowTitle('决赛你电脑的')
            self.show()
    
    app = QApplication(sys.argv)
    demo1 = Ex()
    sys.exit(app.exec_())
    
    

    04子菜单

    
    import sys
    from PyQt5.QtWidgets import QMainWindow, QAction, QMenu, QApplication
    
    class Example(QMainWindow):
    
        def __init__(self):
            super().__init__()
            self.initUI()
    
    
        def initUI(self):
    
            menubar = self.menuBar()
            fileMenu = menubar.addMenu('File')
            impMenu = QMenu('Import', self)
            impAct = QAction('Import mail', self)
            impMenu.addAction(impAct)
    
            newAct = QAction('New', self)
    
            fileMenu.addAction(newAct)
            fileMenu.addMenu(impMenu)
    
            self.setGeometry(300, 300, 300, 200)
            self.setWindowTitle('Submenu')
            self.show()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    05 勾选菜单

    
    import sys
    from PyQt5.QtWidgets import QMainWindow, QAction, QApplication
    
    class Example(QMainWindow):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.statusbar = self.statusBar()
            self.statusbar.showMessage('Ready')
    
            menubar = self.menuBar()
            viewMenu = menubar.addMenu('View')
    
            # 本例创建了一个行为菜单。这个行为/动作能切换状态栏显示或者隐藏。
            viewStatAct = QAction('View statusbar', self, checkable=True)
            viewStatAct.setStatusTip('View statusbar')        # 用checkable选项创建一个能选中的菜单。
            viewStatAct.setChecked(True)        # 默认设置为选中状态
            viewStatAct.triggered.connect(self.toggleMenu)
    
            viewMenu.addAction(viewStatAct)
            # 依据选中状态切换状态栏的显示与否。
            self.setGeometry(300, 300, 300, 200)
            self.setWindowTitle('Check menu')
            self.show()
    
        def toggleMenu(self, state):
    
            if state:
                self.statusbar.show()
            else:
                self.statusbar.hide()
    
    app = QApplication(sys.argv)
    demo1 = Example()
    sys.exit(app.exec_())
    

    06 右键菜单

    
    import sys
    from PyQt5.QtWidgets import QMainWindow, qApp, QMenu, QApplication
    
    
    class Example(QMainWindow):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
        def initUI(self):
            self.setGeometry(300, 300, 300, 200)
            self.setWindowTitle('Context menu')
            self.show()
    
        def contextMenuEvent(self, event):
            cmenu = QMenu(self)
    
            newAct = cmenu.addAction("New")
            print(newAct)
            opnAct = cmenu.addAction("Open")
            print(opnAct)
            quitAct = cmenu.addAction("Quit")
            action = cmenu.exec_(self.mapToGlobal(event.pos()))
    
            if action == quitAct:
                qApp.quit()
            elif action == opnAct:
                print('打开就打开')
            elif action == newAct:
                print('新建就新建')
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    07工具栏

    
    # 菜单栏包含了所有的命令,工具栏就是常用的命令的集合。
    
    import sys
    from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication
    from PyQt5.QtGui import QIcon
    
    class Example(QMainWindow):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            exitAct = QAction(QIcon('logo.png'), 'Exit', self)
            exitAct.setShortcut('Ctrl+Q')
            exitAct.triggered.connect(qApp.quit)
            # 和上面的菜单栏差不多,这里使用了一个行为对象,
            # 这个对象绑定了一个标签,一个图标和一个快捷键。
            # 这些行为被触发的时候,会调用QtGui.QMainWindow的quit方法退出应用。
            self.toolbar = self.addToolBar('Exit')
            self.toolbar.addAction(exitAct)
    
            self.setGeometry(300, 300, 300, 200)
            self.setWindowTitle('Toolbar')
            self.show()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    # 上面的例子中,我们创建了一个工具栏这个工具栏只有一个退出应用的动作
    
    

    08主窗口(啥都有的呢)

    
    # 本模块的功能:<>
    import sys
    from PyQt5.QtWidgets import QMainWindow
    from PyQt5.QtWidgets import QTextEdit
    from PyQt5.QtWidgets import QAction
    from PyQt5.QtWidgets import QApplication
    from PyQt5.QtGui import QIcon
    
    
    class Example(QMainWindow):
    
        def __init__(self):
            super().__init__()
            self.initUI()
    
    
        def initUI(self):
    
            textEdit = QTextEdit()
            self.setCentralWidget(textEdit)
    
            exitAct = QAction(QIcon('logo.png'), '退退退', self)
            exitAct.setShortcut('Ctrl+Q')
            exitAct.setStatusTip('退出应用')
            exitAct.triggered.connect(self.close)
    
            self.statusBar()
    
            menubar = self.menuBar()
            fileMenu = menubar.addMenu('文件')
            fileMenu.addAction(exitAct)
    
            toolbar = self.addToolBar('退出')
            toolbar.addAction(exitAct)
    
            self.setGeometry(300, 300, 350, 250)
            self.setWindowTitle('代码编辑工具')
            self.show()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    布局管理

    09绝对定位的应用

    
    import sys
    from PyQt5.QtWidgets import QWidget, QLabel, QApplication
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            lbl1 = QLabel('Zetcode', self)
            lbl1.move(15, 10)
    
            lbl2 = QLabel('tutorials', self)
            lbl2.move(35, 40)
    
            lbl3 = QLabel('for programmers', self)
            lbl3.move(55, 70)
    
            self.setGeometry(300, 300, 250, 150)
            self.setWindowTitle('Absolute')
            self.show()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    
    # 绝对定位其实说白了就是使用相对于原点的像素来进行计算
    

    10 盒子布局

    
    import sys
    from PyQt5.QtWidgets import (QWidget, QPushButton,
        QHBoxLayout, QVBoxLayout, QApplication)
    
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            okButton = QPushButton("OK")
            cancelButton = QPushButton("Cancel")
    
            hbox = QHBoxLayout()
            hbox.addStretch(1)
            hbox.addWidget(okButton)
            hbox.addWidget(cancelButton)
    
            vbox = QVBoxLayout()
            vbox.addStretch(1)
            vbox.addLayout(hbox)
    
            self.setLayout(vbox)
    
            self.setGeometry(300, 300, 300, 150)
            self.setWindowTitle('Buttons')
            self.show()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    11 栅格布局(表格)

    
    import sys
    from PyQt5.QtWidgets import (QWidget, QGridLayout,
        QPushButton, QApplication)
    
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
            self.initUI()
    
    
        def initUI(self):
    
            grid = QGridLayout()
            self.setLayout(grid)
    
            names = ['Cls', 'Bck', '', 'Close',
                     '7', '8', '9', '/',
                    '4', '5', '6', '*',
                     '1', '2', '3', '-',
                    '0', '.', '=', '+']
    
            positions = [(i,j) for i in range(5) for j in range(4)]
    
            for position, name in zip(positions, names):
    
                if name == '':
                    continue
                button = QPushButton(name)
                grid.addWidget(button, *position)
    
            self.move(300, 150)
            self.setWindowTitle('Calculator')
            self.show()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    12 制作提交反馈信息的布局

    
    import sys
    from PyQt5.QtWidgets import \
        (QWidget, QLabel, QLineEdit, QTextEdit, QGridLayout, QApplication)
    
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
        def initUI(self):
            title = QLabel('Title')
            author = QLabel('Author')
            review = QLabel('Review')
    
            titleEdit = QLineEdit()
            authorEdit = QLineEdit()
            reviewEdit = QTextEdit()
    
            grid = QGridLayout()
            grid.setSpacing(10)
    
            grid.addWidget(title, 1, 0)
            grid.addWidget(titleEdit, 1, 1)
    
            grid.addWidget(author, 2, 0)
            grid.addWidget(authorEdit, 2, 1)
    
            grid.addWidget(review, 3, 0)
            grid.addWidget(reviewEdit, 3, 1, 5, 1)
    
            self.setLayout(grid)
    
            self.setGeometry(300, 300, 350, 300)
            self.setWindowTitle('Review')
            self.show()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    事件和信号

    13 信号和槽机制

    
    '''
    事件
    signals and slots 被其他人翻译成信号和槽机制,(⊙o⊙)…我这里还是不翻译好了。
    所有的应用都是事件驱动的。事件大部分都是由用户的行为产生的,当然也有其他的事件产生方式,
    比如网络的连接,窗口管理器或者定时器等。调用应用的exec_()方法时,应用会进入主循环,主循环会监听和分发事件。
    在事件模型中,有三个角色:
    事件源
    事件
    事件目标
    事件源就是发生了状态改变的对象。事件是这个对象状态改变的内容。
    事件目标是事件想作用的目标。事件源绑定事件处理函数,然后作用于事件目标身上。
    PyQt5处理事件方面有个signal and slot机制。Signals and slots用于对象间的通讯。
    事件触发的时候,发生一个signal,slot是用来被Python调用的
    (相当于一个句柄?这个词也好恶心,就是相当于事件的绑定函数)slot只有在事件触发的时候才能调用。
    '''
    
    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)
            print("lcd:",lcd)
            sld = QSlider(Qt.Horizontal, self)
            print("sld",sld)
            vbox = QVBoxLayout()
            print(vbox)
            vbox.addWidget(lcd)
            vbox.addWidget(sld)
    
            self.setLayout(vbox)
            print(lcd.display)
            sld.valueChanged.connect(lcd.display)
    
            self.setGeometry(300, 300, 250, 150)
            self.setWindowTitle('信号和槽机制的')
            self.show()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    14 重构事件处理器

    
    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('事件的手')
            self.show()
    
    
        def keyPressEvent(self, e):
    
            if e.key() == Qt.Key_Escape:
                self.close()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    15 事件对像

    
    import sys
    from PyQt5.QtCore import Qt
    from PyQt5.QtWidgets import QWidget, QApplication, QGridLayout, QLabel
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            grid = QGridLayout()
            grid.setSpacing(10)
    
            x = 0
            y = 0
    
            self.text = "x: {0},  y: {1}".format(x, y)
    
            self.label = QLabel(self.text, self)
            grid.addWidget(self.label, 0, 0, Qt.AlignTop)
    
            self.setMouseTracking(True)
    
            self.setLayout(grid)
    
            self.setGeometry(300, 300, 350, 200)
            self.setWindowTitle('Event object')
            self.show()
    
    
        def mouseMoveEvent(self, e):
    
            x = e.x()
            y = e.y()
    
            text = "x: {0},  y: {1}".format(x, y)
            self.label.setText(text)
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    16事件发送

    
    import sys
    from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication
    
    
    class Example(QMainWindow):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            btn1 = QPushButton("按钮老大", self)
            btn1.move(30, 50)
    
            btn2 = QPushButton("按钮老二", 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('事件发送')
            self.show()
    
    
        def buttonClicked(self):
    
            sender = self.sender()
            self.statusBar().showMessage(sender.text() + '被按那儿了')
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    17 信号发送

    
    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_())
    

    对话框

    18 对话框(能够输入文字呦呦)

    
    from PyQt5.QtWidgets import (QWidget, QPushButton, QLineEdit,
        QInputDialog, QApplication)
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.btn = QPushButton('Dialog', self)
            self.btn.move(20, 20)
            self.btn.clicked.connect(self.showDialog)
    
            self.le = QLineEdit(self)
            self.le.move(130, 22)
    
            self.setGeometry(300, 300, 290, 150)
            self.setWindowTitle('Input dialog')
            self.show()
    
    
        def showDialog(self):
    
            text, ok = QInputDialog.getText(self, 'Input Dialog',
                'Enter your name:')
    
            if ok:
                self.le.setText(str(text))
    
            print(text+"哈哈")
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    19 选取颜色(NB坏了)

    
    # 本模块的功能:<QColorDialog提供颜色的选择>
    # TODO 这个厉害,直接调用系统的颜色选择框
    # TODO 强,实在是强
    from PyQt5.QtWidgets import (QWidget, QPushButton, QFrame,
        QColorDialog, QApplication)
    from PyQt5.QtGui import QColor
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            col = QColor(0, 0, 0)
    
            self.btn = QPushButton('Dialog', self)
            self.btn.move(20, 20)
    
            self.btn.clicked.connect(self.showDialog)
    
            self.frm = QFrame(self)
            self.frm.setStyleSheet("QWidget { background-color: %s }"
                % col.name())
            self.frm.setGeometry(130, 22, 100, 100)
    
            self.setGeometry(300, 300, 250, 180)
            self.setWindowTitle('Color dialog')
            self.show()
    
    
        def showDialog(self):
    
            col = QColorDialog.getColor()
    
            if col.isValid():
                self.frm.setStyleSheet("QWidget { background-color: %s }"
                    % col.name())
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    
    

    加油,都看到一半了你!!!

    
    '''
    
           ┌─┐       ┌─┐ + +
        ┌──┘ ┴───────┘ ┴──┐++
        │                 │
        │       ───       │++ + + +
        ███████───███████ │+
        │                 │+
        │       ─┴─       │
        │                 │
        └───┐         ┌───┘
            │         │
            │         │   + +
            │         │
            │         └──────────────┐
            │                        │
            │                        ├─┐
            │                        ┌─┘
            │                        │
            └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +
              │ ─┤ ─┤       │ ─┤ ─┤
              └──┴──┘       └──┴──┘  + + + +
                     神兽保佑
                    代码无BUG!
    
    
    '''
    
    

    20 选择字体

    
    from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QPushButton,
        QSizePolicy, QLabel, QFontDialog, QApplication)
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            vbox = QVBoxLayout()
    
            btn = QPushButton('来来来', self)
            btn.setSizePolicy(QSizePolicy.Fixed,
                QSizePolicy.Fixed)
    
            btn.move(20, 20)
    
            vbox.addWidget(btn)
    
            btn.clicked.connect(self.showDialog)
    
            self.lbl = QLabel('Knowledge only matters', self)
            self.lbl.move(130, 20)
    
            vbox.addWidget(self.lbl)
            self.setLayout(vbox)
    
            self.setGeometry(300, 300, 250, 180)
            self.setWindowTitle('字体目录')
            self.show()
    
    
        def showDialog(self):
    
            font, ok = QFontDialog.getFont()
            if ok:
                self.lbl.setFont(font)
            print('选择的字体是',end="")
            print(font)
            print(type(font))
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    21 选择文件

    
    from PyQt5.QtWidgets import \
        (QMainWindow, QTextEdit, QAction, QFileDialog, QApplication)
    from PyQt5.QtGui import QIcon
    import sys
    
    class Example(QMainWindow):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.textEdit = QTextEdit()
            self.setCentralWidget(self.textEdit)
            self.statusBar()
    
            openFile = QAction(QIcon('images/open.png'), 'Open', self)
            openFile.setShortcut('Ctrl+O')
            openFile.setStatusTip('打开一个新的文件')
            openFile.triggered.connect(self.showDialog)
    
            menubar = self.menuBar()
            fileMenu = menubar.addMenu('&文件')
            fileMenu.addAction(openFile)
    
            self.setGeometry(300, 300, 350, 300)
            self.setWindowTitle('File dialog')
            self.show()
    
    
        def showDialog(self):
    
            fname = QFileDialog.getOpenFileName(self, 'Open file', '/home')
    
            if fname[0]:
                f = open(fname[0], 'r')
    
                with f:
                    data = f.read()
                    self.textEdit.setText(data)
                    print(data)
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    控件

    22 QCheckBox是啥玩意

    
    from PyQt5.QtWidgets import QWidget, QCheckBox, QApplication
    from PyQt5.QtCore import Qt
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            cb = QCheckBox('改改改', self)
            cb.move(20, 20)
            cb.toggle()
            cb.stateChanged.connect(self.changeTitle)
    
            self.setGeometry(300, 300, 250, 150)
            self.setWindowTitle('真正的标题')
            self.show()
    
    
        def changeTitle(self, state):
    
            if state == Qt.Checked:
                self.setWindowTitle('假装有标题')
            else:
                self.setWindowTitle('没了')
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    23 切换按钮

    
    from PyQt5.QtWidgets import (QWidget, QPushButton,
        QFrame, QApplication)
    from PyQt5.QtGui import QColor
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.col = QColor(0, 0, 0)
    
            redb = QPushButton('Red', self)
            redb.setCheckable(True)
            redb.move(10, 10)
    
            redb.clicked[bool].connect(self.setColor)
    
            greenb = QPushButton('Green', self)
            greenb.setCheckable(True)
            greenb.move(10, 60)
    
            greenb.clicked[bool].connect(self.setColor)
    
            blueb = QPushButton('Blue', self)
            blueb.setCheckable(True)
            blueb.move(10, 110)
    
            blueb.clicked[bool].connect(self.setColor)
    
            self.square = QFrame(self)
            self.square.setGeometry(150, 20, 100, 100)
            self.square.setStyleSheet("QWidget { background-color: %s }" %
                self.col.name())
    
            self.setGeometry(300, 300, 280, 170)
            self.setWindowTitle('Toggle button')
            self.show()
    
    
        def setColor(self, pressed):
    
            source = self.sender()
    
            if pressed:
                val = 255
            else:
                val = 0
    
            if source.text() == "Red":
                self.col.setRed(val)
            elif source.text() == "Green":
                self.col.setGreen(val)
            else:
                self.col.setBlue(val)
    
            self.square.setStyleSheet("QFrame { background-color: %s }" %
                self.col.name())
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    24 滑块是个好东西

    
    from PyQt5.QtWidgets import (QWidget, QSlider,
                                 QLabel, QApplication)
    from PyQt5.QtCore import Qt
    from PyQt5.QtGui import QPixmap
    import sys
    
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
        def initUI(self):
    
            sld = QSlider(Qt.Horizontal, self)
            sld.setFocusPolicy(Qt.NoFocus)
            sld.setGeometry(30, 40, 100, 30)
            sld.valueChanged[int].connect(self.changeValue)
    
            self.label = QLabel(self)
            self.label.setPixmap(QPixmap('images/logo.png'))
            self.label.setGeometry(160, 40, 80, 30)
    
            self.setGeometry(300, 300, 280, 170)
            self.setWindowTitle('s什么鸡儿玩意r')
            self.show()
    
        def changeValue(self, value):
    
            if value == 0:
                self.label.setPixmap(QPixmap('images/1.png'))
            elif value > 0 and value <= 30:
                self.label.setPixmap(QPixmap('images/2.png'))
            elif value > 30 and value < 80:
                self.label.setPixmap(QPixmap('images/3.png'))
            else:
                self.label.setPixmap(QPixmap('images/4.png'))
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    
    

    25 进度条

    
    from PyQt5.QtWidgets import (QWidget, QProgressBar,
        QPushButton, QApplication)
    from PyQt5.QtCore import QBasicTimer
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.pbar = QProgressBar(self)
            self.pbar.setGeometry(30, 40, 200, 25)
    
            self.btn = QPushButton('走你', self)
            self.btn.move(40, 80)
            self.btn.clicked.connect(self.doAction)
    
            self.timer = QBasicTimer()
            self.step = 0
    
            self.setGeometry(300, 300, 280, 170)
            self.setWindowTitle('进度条就比较强了')
            self.show()
    
    
        def timerEvent(self, e):
    
            if self.step >= 200:
                self.timer.stop()
                self.btn.setText('完成吧')
                return
    
            self.step = self.step + 1
            self.pbar.setValue(self.step)
    
        def doAction(self):
    
            if self.timer.isActive():
                self.timer.stop()
                self.btn.setText('走走走')
            else:
                self.timer.start(200, self)
                self.btn.setText('停,呗走了')
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    26 日历

    
    from PyQt5.QtWidgets import (QWidget, QCalendarWidget,
        QLabel, QApplication, QVBoxLayout)
    from PyQt5.QtCore import QDate
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            vbox = QVBoxLayout(self)
    
            cal = QCalendarWidget(self)
            cal.setGridVisible(True)
            cal.clicked[QDate].connect(self.showDate)
    
            vbox.addWidget(cal)
    
            self.lbl = QLabel(self)
            date = cal.selectedDate()
            self.lbl.setText(date.toString())
    
            vbox.addWidget(self.lbl)
    
            self.setLayout(vbox)
    
            self.setGeometry(300, 300, 350, 300)
            self.setWindowTitle('看日历,认准我')
            self.show()
    
    
        def showDate(self, date):
    
            self.lbl.setText(date.toString())
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    27 图片

    
    from PyQt5.QtWidgets import (QWidget, QHBoxLayout,
        QLabel, QApplication)
    from PyQt5.QtGui import QPixmap
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            hbox = QHBoxLayout(self)
            pixmap = QPixmap("images/09f04")
    
            lbl = QLabel(self)
            lbl.setPixmap(pixmap)
    
            hbox.addWidget(lbl)
            self.setLayout(hbox)
    
            self.move(300, 200)
            self.setWindowTitle('Red Rock')
            self.show()
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    28行编辑

    
    import sys
    from PyQt5.QtWidgets import \
        (QWidget, QLabel, QLineEdit, QApplication)
    
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
        def initUI(self):
            self.lbl = QLabel(self)
            qle = QLineEdit(self)
    
            qle.move(60, 100)
            self.lbl.move(60, 40)
    
            qle.textChanged[str].connect(self.onChanged)
    
            self.setGeometry(300, 300, 280, 170)
            self.setWindowTitle('QLineEdit')
            self.show()
    
        def onChanged(self, text):
            self.lbl.setText(text)
            self.lbl.adjustSize()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    29 QSplitter是啥玩意呢?

    
    from PyQt5.QtWidgets import (QWidget, QHBoxLayout, QFrame,
        QSplitter, QStyleFactory, QApplication)
    from PyQt5.QtCore import Qt
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            hbox = QHBoxLayout(self)
    
            topleft = QFrame(self)
            topleft.setFrameShape(QFrame.StyledPanel)
    
            topright = QFrame(self)
            topright.setFrameShape(QFrame.StyledPanel)
    
            bottom = QFrame(self)
            bottom.setFrameShape(QFrame.StyledPanel)
    
            splitter1 = QSplitter(Qt.Horizontal)
            splitter1.addWidget(topleft)
            splitter1.addWidget(topright)
    
            splitter2 = QSplitter(Qt.Vertical)
            splitter2.addWidget(splitter1)
            splitter2.addWidget(bottom)
    
            hbox.addWidget(splitter2)
            self.setLayout(hbox)
    
            self.setGeometry(300, 300, 400, 300)
            self.setWindowTitle('QSplitter')
            self.show()
    
    
        def onChanged(self, text):
    
            self.lbl.setText(text)
            self.lbl.adjustSize()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    
    

    30 下拉选框

    
    from PyQt5.QtWidgets import (QWidget, QLabel,
        QComboBox, QApplication)
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.lbl = QLabel("Ubuntu", self)
    
            combo = QComboBox(self)
            combo.addItem("Ubuntu")
            combo.addItem("Windows")
            combo.addItem("centos")
            combo.addItem("deepin")
            combo.addItem("redhat")
            combo.addItem("debain")
            combo.move(50, 50)
            self.lbl.move(50, 150)
    
            combo.activated[str].connect(self.onActivated)
    
            self.setGeometry(300, 300, 300, 200)
            self.setWindowTitle('下拉选框练习 ')
            self.show()
    
    
        def onActivated(self, text):
    
            self.lbl.setText(text)
            self.lbl.adjustSize()
    
    
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())
    

    拖拽

    31 简单的拖放

    from PyQt5.QtWidgets import (QPushButton, QWidget,
        QLineEdit, QApplication)
    import sys
    
    class Button(QPushButton):
    
        def __init__(self, title, parent):
            super().__init__(title, parent)
    
            self.setAcceptDrops(True)
    
    
        def dragEnterEvent(self, e):
    
            if e.mimeData().hasFormat('text/plain'):
                e.accept()
            else:
                e.ignore()
    
        def dropEvent(self, e):
    
            self.setText(e.mimeData().text())
    
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            edit = QLineEdit('', self)
            edit.setDragEnabled(True)
            edit.move(30, 65)
    
            button = Button("Button", self)
            button.move(190, 65)
    
            self.setWindowTitle('Simple drag and drop')
            self.setGeometry(300, 300, 300, 150)
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        ex.show()
        app.exec_()
    

    32 拖放按钮组件

    
    from PyQt5.QtWidgets import QPushButton, QWidget, QApplication
    from PyQt5.QtCore import Qt, QMimeData
    from PyQt5.QtGui import QDrag
    import sys
    
    class Button(QPushButton):
    
        def __init__(self, title, parent):
            super().__init__(title, parent)
    
    
        def mouseMoveEvent(self, e):
    
            if e.buttons() != Qt.RightButton:
                return
    
            mimeData = QMimeData()
    
            drag = QDrag(self)
            drag.setMimeData(mimeData)
            drag.setHotSpot(e.pos() - self.rect().topLeft())
    
            dropAction = drag.exec_(Qt.MoveAction)
    
    
        def mousePressEvent(self, e):
    
            super().mousePressEvent(e)
    
            if e.button() == Qt.LeftButton:
                print('按我嘎哈')
    
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.setAcceptDrops(True)
    
            self.button = Button('来吧!!!', self)
            self.button.move(100, 65)
    
            self.setWindowTitle('点击还能挪')
            self.setGeometry(300, 300, 280, 150)
    
    
        def dragEnterEvent(self, e):
    
            e.accept()
    
    
        def dropEvent(self, e):
    
            position = e.pos()
            self.button.move(position)
    
            e.setDropAction(Qt.MoveAction)
            e.accept()
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        ex.show()
        app.exec_()
    """
    拖拽
    在GUI里,拖放是指用户点击一个虚拟的对象,拖动,然后放置到另外一个对象上面的动作。
    一般情况下,需要调用很多动作和方法,创建很多变量。
    拖放能让用户很直观的操作很复杂的逻辑。
    一般情况下,我们可以拖放两种东西:数据和图形界面。
    把一个图像从一个应用拖放到另外一个应用上的实质是操作二进制数据。
    把一个表格从Firefox上拖放到另外一个位置 的实质是操作一个图形组。
    """
    

    绘图

    33 文本的涂鸦(这个好玩哈)

    
    import sys
    from PyQt5.QtWidgets import QWidget, QApplication
    from PyQt5.QtGui import QPainter, QColor, QFont
    from PyQt5.QtCore import Qt
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.text = "涂鸦要涂的有灵魂"
    
            self.setGeometry(300, 300, 280, 170)
            self.setWindowTitle('绘画板')
            self.show()
    
    
        def paintEvent(self, event):
    
            qp = QPainter()
            qp.begin(self)
            self.drawText(event, qp,168, 34, 243)
            qp.end()
    
            # qp1 = QPainter()
            # qp1.begin(self)
            # self.drawText(event, qp1,168, 34, 23)
            # qp1.end()
    
    
        def drawText(self, event, qp, r,g,b):
    
            qp.setPen(QColor(r,g,b))
            qp.setFont(QFont('微软雅黑', 15))
            qp.drawText(event.rect(), Qt.AlignCenter, self.text)
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    34 点的绘画

    
    from PyQt5.QtWidgets import QWidget, QApplication
    from PyQt5.QtGui import QPainter
    from PyQt5.QtCore import Qt
    import sys, random
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.setGeometry(300, 300, 300, 190)
            self.setWindowTitle('一大堆点点儿')
            self.show()
    
    
        def paintEvent(self, e):
    
            qp = QPainter()
            qp.begin(self)
            self.drawPoints(qp)
            qp.end()
    
    
        def drawPoints(self, qp):
    
            qp.setPen(Qt.red)
            size = self.size()
    
            for i in range(1000):
                x = random.randint(1, size.width()-1)
                y = random.randint(1, size.height()-1)
                qp.drawPoint(x, y)
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    35 颜色

    
    from PyQt5.QtWidgets import QWidget, QApplication
    from PyQt5.QtGui import QPainter, QColor, QBrush
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.setGeometry(300, 300, 350, 100)
            self.setWindowTitle('Colours')
            self.show()
    
    
        def paintEvent(self, e):
    
            qp = QPainter()
            qp.begin(self)
            self.drawRectangles(qp)
            qp.end()
    
    
        def drawRectangles(self, qp):
    
            col = QColor(0, 0, 0)
            col.setNamedColor('#d4d4d4')
            qp.setPen(col)
    
            qp.setBrush(QColor(200, 0, 0))
            qp.drawRect(10, 15, 90, 60)
    
            qp.setBrush(QColor(255, 80, 0, 160))
            qp.drawRect(130, 15, 90, 60)
    
            qp.setBrush(QColor(25, 0, 90, 200))
            qp.drawRect(250, 15, 90, 60)
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    36 QPen是笔么

    
    from PyQt5.QtWidgets import QWidget, QApplication
    from PyQt5.QtGui import QPainter, QPen
    from PyQt5.QtCore import Qt
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.setGeometry(300, 300, 280, 270)
            self.setWindowTitle('Pen styles')
            self.show()
    
    
        def paintEvent(self, e):
    
            qp = QPainter()
            qp.begin(self)
            self.drawLines(qp)
            qp.end()
    
    
        def drawLines(self, qp):
    
            pen = QPen(Qt.black, 2, Qt.SolidLine)
    
            qp.setPen(pen)
            qp.drawLine(20, 40, 250, 40)
    
            pen.setStyle(Qt.DashLine)
            qp.setPen(pen)
            qp.drawLine(20, 80, 250, 80)
    
            pen.setStyle(Qt.DashDotLine)
            qp.setPen(pen)
            qp.drawLine(20, 120, 250, 120)
    
            pen.setStyle(Qt.DotLine)
            qp.setPen(pen)
            qp.drawLine(20, 160, 250, 160)
    
            pen.setStyle(Qt.DashDotDotLine)
            qp.setPen(pen)
            qp.drawLine(20, 200, 250, 200)
    
            pen.setStyle(Qt.CustomDashLine)
            pen.setDashPattern([1, 4, 5, 4])
            qp.setPen(pen)
            qp.drawLine(20, 240, 250, 240)
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    37 QBrush是啥?

    
    from PyQt5.QtWidgets import QWidget, QApplication
    from PyQt5.QtGui import QPainter, QBrush
    from PyQt5.QtCore import Qt
    import sys
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.setGeometry(300, 300, 355, 280)
            self.setWindowTitle('Brushes')
            self.show()
    
    
        def paintEvent(self, e):
    
            qp = QPainter()
            qp.begin(self)
            self.drawBrushes(qp)
            qp.end()
    
    
        def drawBrushes(self, qp):
    
            brush = QBrush(Qt.SolidPattern)
            qp.setBrush(brush)
            qp.drawRect(10, 15, 90, 60)
    
            brush.setStyle(Qt.Dense1Pattern)
            qp.setBrush(brush)
            qp.drawRect(130, 15, 90, 60)
    
            brush.setStyle(Qt.Dense2Pattern)
            qp.setBrush(brush)
            qp.drawRect(250, 15, 90, 60)
    
            brush.setStyle(Qt.DiagCrossPattern)
            qp.setBrush(brush)
            qp.drawRect(10, 105, 90, 60)
    
            brush.setStyle(Qt.Dense5Pattern)
            qp.setBrush(brush)
            qp.drawRect(130, 105, 90, 60)
    
            brush.setStyle(Qt.Dense6Pattern)
            qp.setBrush(brush)
            qp.drawRect(250, 105, 90, 60)
    
            brush.setStyle(Qt.HorPattern)
            qp.setBrush(brush)
            qp.drawRect(10, 195, 90, 60)
    
            brush.setStyle(Qt.VerPattern)
            qp.setBrush(brush)
            qp.drawRect(130, 195, 90, 60)
    
            brush.setStyle(Qt.BDiagPattern)
            qp.setBrush(brush)
            qp.drawRect(250, 195, 90, 60)
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    38 贝赛尔曲线(这个学过PS的都知道)

    
    from PyQt5.QtWidgets import QWidget, QApplication
    from PyQt5.QtGui import QPainter, QPainterPath
    from PyQt5.QtCore import Qt
    import sys
    
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
        def initUI(self):
            # 用QPainterPath路径创建贝塞尔曲线。
            # 使用cubicTo()方法生成,分别需要三个点:起始点,控制点和终止点。
            self.setGeometry(300, 300, 380, 250)
            self.setWindowTitle('绘制贝塞尔曲线')
            self.show()
    
        def paintEvent(self, e):
            qp = QPainter()
            qp.begin(self)
            qp.setRenderHint(QPainter.Antialiasing)
            self.drawBezierCurve(qp)
            qp.end()
    
        def drawBezierCurve(self, qp):
            path = QPainterPath()
            path.moveTo(30, 30)
            path.cubicTo(30, 30, 350, 30, 200, 150)
    
            qp.drawPath(path)
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    
    

    自定义组件

    39

    
    from PyQt5.QtWidgets import (QWidget, QSlider, QApplication,
        QHBoxLayout, QVBoxLayout)
    from PyQt5.QtCore import QObject, Qt, pyqtSignal
    from PyQt5.QtGui import QPainter, QFont, QColor, QPen
    import sys
    
    class Communicate(QObject):
    
        updateBW = pyqtSignal(int)
    
    
    class BurningWidget(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            self.setMinimumSize(1, 30)
            self.value = 75
            self.num = [75, 150, 225, 300, 375, 450, 525, 600, 675]
    
    
        def setValue(self, value):
    
            self.value = value
    
    
        def paintEvent(self, e):
    
            qp = QPainter()
            qp.begin(self)
            self.drawWidget(qp)
            qp.end()
    
    
        def drawWidget(self, qp):
    
            MAX_CAPACITY = 700
            OVER_CAPACITY = 750
    
            font = QFont('Serif', 7, QFont.Light)
            qp.setFont(font)
    
            size = self.size()
            w = size.width()
            h = size.height()
    
            step = int(round(w / 10))
    
    
            till = int(((w / OVER_CAPACITY) * self.value))
            full = int(((w / OVER_CAPACITY) * MAX_CAPACITY))
    
            if self.value >= MAX_CAPACITY:
    
                qp.setPen(QColor(255, 255, 255))
                qp.setBrush(QColor(255, 255, 184))
                qp.drawRect(0, 0, full, h)
                qp.setPen(QColor(255, 175, 175))
                qp.setBrush(QColor(255, 175, 175))
                qp.drawRect(full, 0, till-full, h)
    
            else:
    
                qp.setPen(QColor(255, 255, 255))
                qp.setBrush(QColor(255, 255, 184))
                qp.drawRect(0, 0, till, h)
    
    
            pen = QPen(QColor(20, 20, 20), 1,
                Qt.SolidLine)
    
            qp.setPen(pen)
            qp.setBrush(Qt.NoBrush)
            qp.drawRect(0, 0, w-1, h-1)
    
            j = 0
    
            for i in range(step, 10*step, step):
    
                qp.drawLine(i, 0, i, 5)
                metrics = qp.fontMetrics()
                fw = metrics.width(str(self.num[j]))
                qp.drawText(i-fw/2, h/2, str(self.num[j]))
                j = j + 1
    
    
    class Example(QWidget):
    
        def __init__(self):
            super().__init__()
    
            self.initUI()
    
    
        def initUI(self):
    
            OVER_CAPACITY = 750
    
            sld = QSlider(Qt.Horizontal, self)
            sld.setFocusPolicy(Qt.NoFocus)
            sld.setRange(1, OVER_CAPACITY)
            sld.setValue(75)
            sld.setGeometry(30, 40, 150, 30)
    
            self.c = Communicate()
            self.wid = BurningWidget()
            self.c.updateBW[int].connect(self.wid.setValue)
    
            sld.valueChanged[int].connect(self.changeValue)
            hbox = QHBoxLayout()
            hbox.addWidget(self.wid)
            vbox = QVBoxLayout()
            vbox.addStretch(1)
            vbox.addLayout(hbox)
            self.setLayout(vbox)
    
            self.setGeometry(300, 300, 390, 210)
            self.setWindowTitle('Burning widget')
            self.show()
    
    
        def changeValue(self, value):
    
            self.c.updateBW.emit(value)
            self.wid.repaint()
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())
    

    终于翻到底部了,能看到这里,给你自己一个奖励吧!!!

    
    '''
    
           ┌─┐       ┌─┐ + +
        ┌──┘ ┴───────┘ ┴──┐++
        │                 │
        │       ───       │++ + + +
        ███████───███████ │+
        │                 │+
        │       ─┴─       │
        │                 │
        └───┐         ┌───┘
            │         │
            │         │   + +
            │         │
            │         └──────────────┐
            │                        │
            │                        ├─┐
            │                        ┌─┘
            │                        │
            └─┐  ┐  ┌───────┬──┐  ┌──┘  + + + +
              │ ─┤ ─┤       │ ─┤ ─┤
              └──┴──┘       └──┴──┘  + + + +
                     神兽保佑
                    代码无BUG!
    
    
    '''
    
    
    展开全文
  • PyQt5开发与实战视频教程

    万人学习 2018-10-23 12:11:15
    本课程属于《Python大讲堂》系列课程,全面深入讲解了PyQt5的核心API以及扩展应用。PyQt5视频培训课程的主要内容: 1. Qt Designer 2. PyQt5基本窗口控件 3. PyQt5高级组件 4. PyQt5布局管理 5. PyQt5信号与槽 ...
  • 从零开始 使用PyQt5

    万次阅读 多人点赞 2018-09-04 12:26:51
    PyQt5 是用来创建Python GUI应用程序的工具包。作为一个跨平台的工具包,PyQt可以在所有主流操作系统上运行(Unix,Windows,Mac)。 本文描述Windows系统下如何安装Python + PyCharm + PyQt5,并通过PyQt5 采用 两...

     PyQt5 是用来创建Python GUI应用程序的工具包。作为一个跨平台的工具包,PyQt可以在所有主流操作系统上运行(Unix,Windows,Mac)。

    本文描述Windows系统下如何安装Python + PyCharm + PyQt5,并通过PyQt5 采用 两种方式设计GUI界面。a.直接使用代码设计界面;b. 先使用QtDesigner进行可视化设计,然后将生成的.ui文件转换成.py文件。

     

    安装Python + PyCharm + PyQt5

    1、安装Python

    访问官网https://www.python.org/,下载并安装你的目标Python版本。

     

    2、安装PyQt5

    1)进入cmd界面。执行命令 pip install pyqt5 pyqt5-tools ,等待一会儿,命令执行完毕后PyQt5就安装好了。

    在安装过程中可能会报下面错误,找不到对应的pyqt5-tools版本。

      Collecting pyqt5-tools
      Could not find a version that satisfies the requirement pyqt5-tools (from versions: )
    No matching distribution found for pyqt5-tools

    由于作者电脑上原来安装了2016年某个版本的python3.5 ,幸运的把pip install pyqt5 pyqt5-tools 一次执行完毕,全部安装完了。不过后来更新到python3.5.4和python3.7时都遇到了这个问题。python3.5.4在更新PIP到最新版本后,问题貌似也消失了。python3.7没有再去解决。

    2)在python 自带的IDLE中试验一下pqyt5是否真的装好了。

    新建文件 firstPython.py 并输入如下代码

    #####################################

    import sys  
      
    from PyQt5 import QtWidgets, QtCore  
      
    app = QtWidgets.QApplication(sys.argv)  
    widget = QtWidgets.QWidget()  
    widget.resize(400, 100)  
    widget.setWindowTitle("This is a demo for PyQt Widget.")  
    widget.show()  
      
    exit(app.exec_()) 

    #####################################

    运行后弹出如下界面,表示PyQt已经正常工作啦。

    如果不幸没有弹出GUI窗口,而且提示错误:ImportError: DLL load failed: 找不到指定的模块。

    据说这是由于缺少了合适的python3.dll,可以通过去python.org 下载所需版本的python安装包并安装,然后从安装目录中拷贝python3.dll文件,和自己使用的python3x.dll放在同一级目录下即可。

    作者自己原来安装的python3.5就是挂在了这一步,然后直接删了重新安装python3.5.4,又遇到了上面1)的问题。升级pip版本后莫名过关。建议大家按照上面建议的解决方式操作。

    3、安装PyCharm

    1)访问官网http://www.jetbrains.com/pycharm/download/#section=windows  作者选择下载并安装Community版本 ——目前是PyCharm 2018.2.2 Community Edition。

     

    2)PyCharm 基本配置:

    a. 建立一个新项目:first。 

    b.设置默认PyCharm解析器

    选择File | Settings | Project: first | Project Interpreter,设置 Project Interpreter为你使用的python版本

    例如 C:\xxxx\AppData\Local\Programs\Python\Python35-32\python.exe

    c. 添加第三方库 

     停留在 Project Interpreter 界面,点击+,查找并安装 pyqt5,pyqt5-sip ,pyqt5-tools 。安装成功后返回,界面应该如下。

    d.配置PyQt

    PyCharm中选择File | Settings | Tools | External Tools,点击+ 新建工具, 建立QTdesigner 和 PyUIC工具

    QTdesigner:

    配置两个关键参数:

    Program:自己的designer.exe路径 例如 C:\xxxx\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\pyqt5-tools\designer.exe  

    Working directory:$ProjectFileDir$

     

    PyUIC:

    配置三个关键参数:

    Program:自己的python.exe路径 例如 C:\xxxx\AppData\Local\Programs\Python\Python35-32\python.exe

    Arguments:-m PyQt5.uic.pyuic $FileName$ -o $FileNameWithoutExtension$.py

    Working directory:$ProjectFileDir$

     

    工具建立成功后返回ExternalTools界面,如下:

    返回主界面,Tools->ExternalTools 中新增了QTdesigner 和 PyUIC两个工具

     

    4、PyCharm中通过PyQt5设计GUI界面

    1)利用代码创建GUI界面

    新建firstGUI.py,输入如下代码

    # -*- coding: utf-8 -*-
    """第一个程序"""
    
    from PyQt5 import QtWidgets   # 导入PyQt5部件
    
    import sys
    
    app = QtWidgets.QApplication(sys.argv)  # 建立application对象
    
    first_window = QtWidgets.QWidget()  # 建立窗体对象
    
    first_window.resize(400, 300)  # 设置窗体大小
    
    first_window.setWindowTitle("我的第一个pyqt程序")  # 设置窗体标题
    
    first_window.show()  # 显示窗体
    
    sys.exit(app.exec())  # 运行程序

    ###############################################################

    选择Run->Run firstGUI,结果显示如下界面就成功了。

     

    2)利用QT Designer代码生成一个GUI界面 ,并用PyUIC转换为.py文件。

    选择Tools->ExternalTools->QTdesigner,进入QT Designer界面,第一次会弹出一个GUI创建界面,点击creat 自动生成一个带下方按钮的GUI界面,如下图。

    另存该界面为Utitled.ui文件。

    返回PyCharm 项目界面,项目列表下多出了这个.ui文件

    右键单击Utitled.ui,弹出列表中选择ExternalTools->PyUIC 就会生成Utitled.ui对应的Utitled.py文件了。内容如下

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'untitled.ui'
    #
    # Created by: PyQt5 UI code generator 5.11.2
    #
    # WARNING! All changes made in this file will be lost!
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    class Ui_Dialog(object):
        def setupUi(self, Dialog):
            Dialog.setObjectName("Dialog")
            Dialog.resize(400, 300)
            self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
            self.buttonBox.setGeometry(QtCore.QRect(30, 240, 341, 32))
            self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
            self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
            self.buttonBox.setObjectName("buttonBox")
    
            self.retranslateUi(Dialog)
            self.buttonBox.accepted.connect(Dialog.accept)
            self.buttonBox.rejected.connect(Dialog.reject)
            QtCore.QMetaObject.connectSlotsByName(Dialog)
    
        def retranslateUi(self, Dialog):
            _translate = QtCore.QCoreApplication.translate
            Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
    #############################################################################

    That's All .Thankyou~

     

     

     

     

    展开全文
  • 06.PyQt5高级界面控------PyQt5编程开发

    万次阅读 多人点赞 2018-04-19 10:37:02
    一、表格与树 表格与树解决的问题是如何在一个控件中有规律地呈现更多的数据。解决该问题的两种控件类为表格结构的控件类,树形结构的控件类。1、QTableView 若一个应用和一批数据(如数组、列表)进行交互后要以...

    一、表格与树

        表格与树解决的问题是如何在一个控件中有规律地呈现更多的数据。解决该问题的两种控件类为表格结构的控件类,树形结构的控件类。

    1、QTableView

        若一个应用和一批数据(如数组、列表)进行交互后要以表格的形式输出这些信息的话,就用QTableView类。在QtableView中可以使用自定义的数据模型来显示内容,通过setModel来绑定数据源,可用的模式如下:

        QStringListModel:存储一组字符串

        QStandardItemModel:存储任意层次结构的数据

        QDirModel:对文件系统进行封装

        QSqlQueryModel:对SQL的查询结构集进行封装

        QSqlTableModel:对SQL中的表格进行封装

        QSqlRelationalTableModel:对带有foreign key的SQL表格进行封装

        QSortFilterProxyModel:对模型中的数据进行排序或过滤

        QTableView的使用例子:

    # -*- coding: utf-8 -*-
     '''
      【简介】
      PyQT5中QTableView表格视图控件的例子
     
     
     '''
      
     from PyQt5.QtWidgets import *
     from PyQt5.QtGui import *
     from PyQt5.QtCore import *
     import sys
      
     class Table(QWidget):
      
     def __init__(self, arg=None):
     super(Table, self).__init__(arg)
     self.setWindowTitle("QTableView表格视图控件的例子")
     self.resize(500,300);
     self.model=QStandardItemModel(4,4);
     self.model.setHorizontalHeaderLabels(['标题1','标题2','标题3','标题4'])
      
     for row in range(4):
     for column in range(4):
     item = QStandardItem("row %s, column %s"%(row,column))
     self.model.setItem(row, column, item)
      
     self.tableView=QTableView()
     self.tableView.setModel(self.model)
     #下面代码让表格100填满窗口
     #self.tableView.horizontalHeader().setStretchLastSection(True)
     #self.tableView.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
     dlgLayout=QVBoxLayout();
     dlgLayout.addWidget(self.tableView)
     self.setLayout(dlgLayout)
      
     if __name__ == '__main__':
     app = QApplication(sys.argv)
     table = Table()
     table.show()
     sys.exit(app.exec_())

    运行结果:

        

    2、QListView

        常用方法:setModel():用来设置View所关联的Model,可以使用Python原生的list作为数据源Model

                        selectedItem():选中Model中的条目

                        isSelected():判断Model中的某条条目是否被选中

        常用信号:clicked:当单击某项时,信号被发射

                        doubleClicked:当双击某项时,信号被发射

    使用QListView控件例子如下:

    # -*- coding: utf-8 -*-
      
     '''
      【简介】
      PyQt5中 QListView 例子
     
     '''
      
     from PyQt5.QtWidgets import QApplication, QWidget , QVBoxLayout , QListView, QMessageBox
     from PyQt5.QtCore import QStringListModel
     import sys
      
     class ListViewDemo(QWidget):
     def __init__(self, parent=None):
     super(ListViewDemo, self).__init__(parent)
     self.setWindowTitle("QListView 例子")
     self.resize(300, 270)
     layout = QVBoxLayout()
      
     listView = QListView()
     slm = QStringListModel();
     self.qList = ['Item 1','Item 2','Item 3','Item 4' ]
     slm.setStringList(self.qList)
     listView.setModel(slm )
     listView.clicked.connect(self.clicked)
     layout.addWidget( listView )
     self.setLayout(layout)
      
     def clicked(self, qModelIndex):
     QMessageBox.information(self, "QListView", "你选择了: "+ self.qList[qModelIndex.row()])
      
     if __name__ == "__main__":
     app = QApplication(sys.argv)
     win = ListViewDemo()
     win.show()
     sys.exit(app.exec_())

    运行结果:

    3、QListWidget

        它是一个基于条目的接口,用于从列表中添加或删除条目。列表中的每个条目都是一个QListWidgetItem对象。QListWidget可以设置为多重选择。

        QListWidget类中的常用方法为:

        addItem():在列表中添加QListWidgetItem对象或字符串

        addItems():添加列表中的每个条目

        insertItem():在指定的索引处插入条目

        clear():删除列表的内容

        setCurrentItem():设置当前所选条目

        sortItems():按升序重新排列条目

    常用信号为:currentItemChanged:当列表中的条目发生改变时发射此信号

                        itemClicked:当点击列表中的条目时发射此信号

    QListWidget使用例子:

    # -*- coding: utf-8 -*-
      
     '''
      【简介】
      PyQt5中 QListWidget 例子
     
     
     '''
      
     import sys
     from PyQt5.QtCore import *
     from PyQt5.QtGui import *
     from PyQt5.QtWidgets import *
      
     class ListWidget(QListWidget):
     def clicked(self,item):
     QMessageBox.information(self, "ListWidget", "你选择了: "+item.text())
      
     if __name__ == '__main__':
     app = QApplication(sys.argv)
     listWidget = ListWidget()
     listWidget.resize(300,120)
     listWidget.addItem("Item 1");
     listWidget.addItem("Item 2");
     listWidget.addItem("Item 3");
     listWidget.addItem("Item 4");
     listWidget.setWindowTitle('QListwidget 例子')
     listWidget.itemClicked.connect(listWidget.clicked)
     listWidget.show()
     sys.exit(app.exec_())

    运行结果:

    4、QTableWidget

        它是Qt程序中常用的显示数据表格的控件。



    QTableWidget基本用法例子:

        

    # -*- coding: utf-8 -*-
      
     '''
      【简介】
      PyQT5中单元格的基本例子
     
     '''
      
     import sys
     from PyQt5.QtWidgets import (QWidget, QTableWidget, QHBoxLayout, QApplication, QTableWidgetItem, QAbstractItemView )
      
     class Table(QWidget):
     def __init__(self):
     super().__init__()
     self.initUI()
      
     def initUI(self):
     self.setWindowTitle("QTableWidget 例子")
     self.resize(430,230);
     conLayout = QHBoxLayout()
     tableWidget = QTableWidget()
     tableWidget.setRowCount(4)
     tableWidget.setColumnCount(3)
     conLayout.addWidget(tableWidget )
      
     tableWidget.setHorizontalHeaderLabels(['姓名','性别','体重(kg)'])
      
     newItem = QTableWidgetItem("张三")
     tableWidget.setItem(0, 0, newItem)
      
     newItem = QTableWidgetItem("")
     tableWidget.setItem(0, 1, newItem)
      
     newItem = QTableWidgetItem("160")
     tableWidget.setItem(0, 2, newItem)
      
     # 将表格变为禁止编辑
     #tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers)
      
     # 设置表格为整行选择
     #tableWidget.setSelectionBehavior( QAbstractItemView.SelectRows)
      
     # 将行和列的大小设为与内容相匹配
     #tableWidget.resizeColumnsToContents()
     #tableWidget.resizeRowsToContents()
      
     #表格表头的显示与隐藏
     #tableWidget.verticalHeader().setVisible(False)
     #tableWidget.horizontalHeader().setVisible(False)
      
     # 不显示表格单元格的分割线
     #tableWidget.setShowGrid(False)
     # 不显示垂直表头
     tableWidget.verticalHeader().setVisible(False)
      
     self.setLayout(conLayout)
      
     if __name__ == '__main__':
     app = QApplication(sys.argv)
     example = Table()
     example.show()
     sys.exit(app.exec_())

    运行结果:

    5、QTreeView

        它实现了树形结构,其中QTreeWidget常用方法为:

        setColumnWidth(int column,int width):将指定列的宽度设置为给定的值

        insertTopLevelItems():在视图的顶层索引中插入项目列表

        expandAll():展开所有的树形节点

        invisibleRootItem():返回树形控件中不可见的根选项(Root Item)

        selectedItems():返回所有选定的非隐藏项目的列表

        QTreeWidgetItem类中的常用方法为:

        addChild():将子项追加到子列表中

        setText():设置显示的节点文本

        Text():返回显示的节点文本

        setCheckState(column,state):设置指定列的选中状态

        setIcon(column,icon):在指定的列中显示图标

    树形结构实现的例子:

        

    '''
      【简介】
      PyQT5中 QTreeWidget 例子
     
     
     '''
      
     import sys
     from PyQt5.QtWidgets import *
     from PyQt5.QtGui import QIcon , QBrush , QColor
     from PyQt5.QtCore import Qt
      
     class TreeWidgetDemo(QMainWindow):
     def __init__(self,parent=None):
     super(TreeWidgetDemo,self).__init__(parent)
     self.setWindowTitle('TreeWidget 例子')
     self.tree = QTreeWidget()
     # 设置列数
     self.tree.setColumnCount(2)
     # 设置头的标题
     self.tree.setHeaderLabels(['Key','Value'])
     # 设置根节点
     root= QTreeWidgetItem(self.tree)
     root.setText(0,'root')
     root.setIcon(0,QIcon("./images/root.png"))
     # 设置列宽
     self.tree.setColumnWidth(0, 160)
      
     ### 设置节点的背景颜色
     #brush_red = QBrush(Qt.red)
     #root.setBackground(0, brush_red)
     #brush_green = QBrush(Qt.green)
     #root.setBackground(1, brush_green)
      
     # 设置子节点1
     child1 = QTreeWidgetItem(root)
     child1.setText(0,'child1')
     child1.setText(1,'ios')
     child1.setIcon(0,QIcon("./images/IOS.png"))
     child1.setCheckState(0, Qt.Checked)
      
     # 设置子节点2
     child2 = QTreeWidgetItem(root)
     child2.setText(0,'child2')
     child2.setText(1,'')
     child2.setIcon(0,QIcon("./images/android.png"))
      
     # 设置子节点3
     child3 = QTreeWidgetItem(child2)
     child3.setText(0,'child3')
     child3.setText(1,'android')
     child3.setIcon(0,QIcon("./images/music.png"))
      
     self.tree.addTopLevelItem(root)
     # 结点全部展开
     self.tree.expandAll()
      
     self.setCentralWidget(self.tree)
      
      
     if __name__ == '__main__':
     app = QApplication(sys.argv)
     tree = TreeWidgetDemo()
     tree.show()
     sys.exit(app.exec_())

    运行结果:

    二、容器:装载更多的控件

    1、QTabWidget

        它提供了一个选项卡和一个页面区域,默认显示第一个选项卡的页面。通过单击各选项卡可以查看对应的页面。常用方法:

        addTab():将一个控件添加到Tab控件的选项卡中

        insertTab():将一个Tab控件的选项卡插入到指定的位置

        removeTab():根据指定的索引删除Tab控件

        setCurrentIndex():设置当前可见的选项卡所在的索引

        setCurrentWidget():设置当前可见的页面

        setTabBar():设置选项卡栏的小控件

        setTabPosition():设置选项卡的位置  QTabWidget.North 显示在页面上方  QTabWidget.South 显示在页面下方,左右同理

        setTabText():定义Tab选项卡的显示值

        例子:

    '''
      【简介】
      PyQt5中 QTabWidget 例子
     
     
     '''
      
     import sys
     from PyQt5.QtCore import *
     from PyQt5.QtGui import *
     from PyQt5.QtWidgets import *
      
     class TabDemo(QTabWidget):
     def __init__(self, parent=None):
     super(TabDemo, self).__init__(parent)
     self.tab1 = QWidget()
     self.tab2 = QWidget()
     self.tab3 = QWidget()
     self.addTab(self.tab1,"Tab 1")
     self.addTab(self.tab2,"Tab 2")
     self.addTab(self.tab3,"Tab 3")
     self.tab1UI()
     self.tab2UI()
     self.tab3UI()
     self.setWindowTitle("Tab 例子")
      
     def tab1UI(self):
     layout = QFormLayout()
     layout.addRow("姓名",QLineEdit())
     layout.addRow("地址",QLineEdit())
     self.setTabText(0,"联系方式")
     self.tab1.setLayout(layout)
      
     def tab2UI(self):
     layout = QFormLayout()
     sex = QHBoxLayout()
     sex.addWidget(QRadioButton(""))
     sex.addWidget(QRadioButton(""))
     layout.addRow(QLabel("性别"),sex)
     layout.addRow("生日",QLineEdit())
     self.setTabText(1,"个人详细信息")
     self.tab2.setLayout(layout)
      
     def tab3UI(self):
     layout=QHBoxLayout()
     layout.addWidget(QLabel("科目"))
     layout.addWidget(QCheckBox("物理"))
     layout.addWidget(QCheckBox("高数"))
     self.setTabText(2,"教育程度")
     self.tab3.setLayout(layout)
      
     if __name__ == '__main__':
     app = QApplication(sys.argv)
     demo = TabDemo()
     demo.show()
     sys.exit(app.exec_())

    运行结果:

    2、QStackedWidget

        它是一个堆栈窗口的控件,可以填充一些小的控件,但同一时间只有一个小控件可以显示。QStackedWidget使用QStackedLayout布局。QStackedWidget控件与QTabWidget类似,可以有效地显示窗口中的控件。

    例子:

    '''
      【简介】
      PyQt5中 QStackedWidget 例子
     
     
     '''
      
     import sys
     from PyQt5.QtCore import *
     from PyQt5.QtGui import *
     from PyQt5.QtWidgets import *
      
     class StackedExample(QWidget):
     def __init__(self):
     super(StackedExample, self).__init__()
     self.setGeometry(300, 50, 10,10)
     self.setWindowTitle('StackedWidget 例子')
      
     self.leftlist = QListWidget ()
     self.leftlist.insertItem (0, '联系方式' )
     self.leftlist.insertItem (1, '个人信息' )
     self.leftlist.insertItem (2, '教育程度' )
     self.stack1= QWidget()
     self.stack2= QWidget()
     self.stack3= QWidget()
     self.stack1UI()
     self.stack2UI()
     self.stack3UI()
     self.Stack = QStackedWidget (self)
     self.Stack.addWidget (self.stack1)
     self.Stack.addWidget (self.stack2)
     self.Stack.addWidget (self.stack3)
     hbox = QHBoxLayout(self)
     hbox.addWidget(self.leftlist)
     hbox.addWidget(self.Stack)
     self.setLayout(hbox)
     self.leftlist.currentRowChanged.connect(self.display)
      
     def stack1UI(self):
     layout=QFormLayout()
     layout.addRow("姓名",QLineEdit())
     layout.addRow("地址",QLineEdit())
     self.stack1.setLayout(layout)
      
     def stack2UI(self):
     layout=QFormLayout()
     sex=QHBoxLayout()
     sex.addWidget(QRadioButton(""))
     sex.addWidget(QRadioButton(""))
     layout.addRow(QLabel("性别"),sex)
     layout.addRow("生日",QLineEdit())
     self.stack2.setLayout(layout)
      
     def stack3UI(self):
     layout=QHBoxLayout()
     layout.addWidget(QLabel("科目"))
     layout.addWidget(QCheckBox("物理"))
     layout.addWidget(QCheckBox("高数"))
     self.stack3.setLayout(layout)
      
     def display(self,i):
     self.Stack.setCurrentIndex(i)
      
     if __name__ == '__main__':
     app = QApplication(sys.argv)
     demo = StackedExample()
     demo.show()
     sys.exit(app.exec_())

    运行结果:

    3、QDockWidget

        它是一个可以停靠在QMainWindow内的窗口控件,它可以保持在浮动状态或者在指定位置作为子窗口附加到主窗口中。QMainWindow类的主窗口对象保留一个用于停靠窗口的区域,这个区域在控件的中央周围,QDockWidget控件在主窗口内可以移动到新的区域。QDockWidget类中的常用方法为:

        setWidget():在Dock窗口区域设置QWidget

        setFloating():设置Dock窗口是否可以浮动,如果设置为true,则表示可以浮动

        setAllowedAreas():设置窗口可以停靠的区域: LeftDockWidgetArea 左边停靠区域

                                                                                  RightDockWidgetArea  右边停靠区域

                                                                                  TopDockWidgetArea  顶部停靠区域

                                                                                  BottomDockWidgetArea    底部停靠区域

                                                                                  NoDockWidgetArea      不显示Widget

        setFeatures():设置停靠窗口的功能属性:  DockWidgetClosable  可关闭

                                                                           DockWidgetMovable   可移动

                                                                           DockWidgetFloatable   可漂浮

                                                                           DockWidgetVerticalTitleBar  在左边显示垂直的标签栏

                                                                           AllDockWidgetFeatures    具有前三种属性的所有功能

                                                                           NoDockWidgetFeatures    无法关闭,不能移动,不能漂浮

    QDockWidget使用例子:

    '''
      【简介】
      PyQt5中 QDockWidget 例子
     
     
     '''
      
     import sys
     from PyQt5.QtCore import *
     from PyQt5.QtGui import *
     from PyQt5.QtWidgets import *
      
     class DockDemo(QMainWindow):
     def __init__(self, parent=None):
     super(DockDemo, self).__init__(parent)
     layout = QHBoxLayout()
     bar=self.menuBar()
     file=bar.addMenu("File")
     file.addAction("New")
     file.addAction("save")
     file.addAction("quit")
     self.items = QDockWidget("Dockable", self)
     self.listWidget = QListWidget()
     self.listWidget.addItem("item1")
     self.listWidget.addItem("item2")
     self.listWidget.addItem("item3")
     self.items.setWidget(self.listWidget)
     self.items.setFloating(False)
     self.setCentralWidget(QTextEdit())
     self.addDockWidget(Qt.RightDockWidgetArea, self.items)
     self.setLayout(layout)
     self.setWindowTitle("Dock 例子")
      
     if __name__ == '__main__':
     app = QApplication(sys.argv)
     demo = DockDemo()
     demo.show()
     sys.exit(app.exec_())
    运行结果:

    4、多文档界面

        MDI(Multiple Document Interface,多文档界面)应用程序占用较少的内存资源,子窗口都可以放在主窗口容器中,这个容器控件被称为QMdiArea。QMdiArea控件通常占据在QMainWindow对象的中间位置,子窗口在这个区域是QMdiSubWindow类的实例,可以设置任何QWidget作为子窗口对象的内部控件,QMdiArea类和QMdiSubWindow类中的常用方法如下:

        addSubWindow():将一个小控件添加在MDI区域作为一个新的子窗口

        removeSubWindow():删除一个子窗口的小控件

        setActiveSubWindow():激活一个子窗口

        cascadeSubWindows():安排子窗口在MDI区域级联显示

        tileSubWindows():安排子窗口在MDI区域平铺显示

        closeActiveSubWindow():关闭活动的子窗口

        subWindowList():返回MDI区域的子窗口列表

        setWidget():设置一个小控件作为QMdiSubwindow实例对象的内部控件

    例子:

    '''
      【简介】
      PyQt5中 QMdiArea 例子
     
     
     '''
      
     import sys
     from PyQt5.QtCore import *
     from PyQt5.QtGui import *
     from PyQt5.QtWidgets import *
      
     class MainWindow(QMainWindow):
     count=0
     def __init__(self, parent=None):
     super(MainWindow, self).__init__(parent)
     self.mdi = QMdiArea()
     self.setCentralWidget(self.mdi)
     bar=self.menuBar()
     file=bar.addMenu("File")
     file.addAction("New")
     file.addAction("cascade")
     file.addAction("Tiled")
     file.triggered[QAction].connect(self.windowaction)
     self.setWindowTitle("MDI demo")
      
     def windowaction(self, q):
     print( "triggered")
      
     if q.text()=="New":
     MainWindow.count=MainWindow.count+1
     sub=QMdiSubWindow()
     sub.setWidget(QTextEdit())
     sub.setWindowTitle("subwindow"+str(MainWindow.count))
     self.mdi.addSubWindow(sub)
     sub.show()
     if q.text()=="cascade":
     self.mdi.cascadeSubWindows()
     if q.text()=="Tiled":
     self.mdi.tileSubWindows()
      
     if __name__ == '__main__':
     app = QApplication(sys.argv)
     demo = MainWindow()
     demo.show()
     sys.exit(app.exec_())
     

    运行结果:

    5、QScrollBar

    提供了水平或者垂直的滚动条,这样可以扩大当前窗口的有效装载面积,从而装载更多的控件。常用方法:

        valueChanged:当滑动条的值改变时发射该信号

        sliderMoved:当用户拖动滑动条时发射此信号

    例子:

    '''
      【简介】
      PyQt5中 QScrollBar 例子
     
     
     '''
      
     import sys
     from PyQt5.QtCore import *
     from PyQt5.QtGui import *
     from PyQt5.QtWidgets import *
      
     class Example(QWidget):
     def __init__(self):
     super(Example, self).__init__()
     self.initUI()
      
     def initUI(self):
     hbox = QHBoxLayout( )
     self.l1 = QLabel("拖动滑动条去改变颜色")
     self.l1.setFont(QFont("Arial",16))
     hbox.addWidget(self.l1)
     self.s1 = QScrollBar()
     self.s1.setMaximum(255)
     self.s1.sliderMoved.connect(self.sliderval)
     self.s2 = QScrollBar()
     self.s2.setMaximum(255)
     self.s2.sliderMoved.connect(self.sliderval)
     self.s3 = QScrollBar()
     self.s3.setMaximum(255)
     self.s3.sliderMoved.connect(self.sliderval)
     hbox.addWidget(self.s1)
     hbox.addWidget(self.s2)
     hbox.addWidget(self.s3)
     self.setGeometry(300, 300, 300, 200)
     self.setWindowTitle('QScrollBar 例子')
     self.setLayout( hbox )
      
     def sliderval(self):
     print( self.s1.value(),self.s2.value(), self.s3.value() )
     palette = QPalette()
     c = QColor(self.s1.value(),self.s2.value(), self.s3.value(),255)
     palette.setColor(QPalette.Foreground,c)
     self.l1.setPalette(palette)
      
     if __name__ == '__main__':
     app = QApplication(sys.argv)
     demo = Example()
     demo.show()
     sys.exit(app.exec_())

    运行结果:


    三、多线程

        多线程技术涉及三种方法,一种是使用计时器模块QTimer;一种是使用多线程模块QThread;还有一种是使用事件处理的功能。

    1、QTimer

        如果要在应用程序中周期性地进行某项操作,比如周期性地检查主机的CPU值,则需要用到QTimer(定时器),QTimer类提供了重复的和单次的定时器。要使用定时器,需要创建一个QTimer实例,将其timeout信号连接到相应的槽,并调用start()。然后,定时器会以恒定的间隔发出timeout信号。当窗口控件收到timeout信号后,它就会停止这个定时器。这是在图形用户界面中实现复制工作的一个典型方法,随着技术的进步,多线程在越来越多的平台上被使用,最终QTimer对象会被线程所替代。

        QTimer类中的常用方法: start(milliseconds):启动或重启定时器,时间间隔为毫秒。如果定时器已经运行,它将被停止并重新启动。如果singleShot信号为真,定时器将仅被激活一次

                                             Stop():停止定时器

        QTimer类中的常用信号:singleShot:在给定的时间间隔后调用一个槽函数时发射此信号

        timeout:当定时器超时时发射此信号

    例子:

    '''
      【简介】
      PyQT5中 QTimer例子
     
     
     '''
      
     from PyQt5.QtWidgets import QWidget, QPushButton , QApplication ,QListWidget, QGridLayout , QLabel
     from PyQt5.QtCore import QTimer ,QDateTime
     import sys
      
     class WinForm(QWidget):
      
     def __init__(self,parent=None):
     super(WinForm,self).__init__(parent)
     self.setWindowTitle("QTimer demo")
     self.listFile= QListWidget()
     self.label = QLabel('显示当前时间')
     self.startBtn = QPushButton('开始')
     self.endBtn = QPushButton('结束')
     layout = QGridLayout(self)
      
     # 初始化一个定时器
     self.timer = QTimer(self)
     # showTime()方法
     self.timer.timeout.connect(self.showTime)
      
     layout.addWidget(self.label,0,0,1,2)
     layout.addWidget(self.startBtn,1,0)
     layout.addWidget(self.endBtn,1,1)
      
     self.startBtn.clicked.connect( self.startTimer)
     self.endBtn.clicked.connect( self.endTimer)
      
     self.setLayout(layout)
      
     def showTime(self):
     # 获取系统现在的时间
     time = QDateTime.currentDateTime()
     # 设置系统时间显示格式
     timeDisplay = time.toString("yyyy-MM-dd hh:mm:ss dddd");
     # 在标签上显示时间
     self.label.setText( timeDisplay )
      
     def startTimer(self):
     # 设置计时间隔并启动
     self.timer.start(1000)
     self.startBtn.setEnabled(False)
     self.endBtn.setEnabled(True)
      
     def endTimer(self):
     self.timer.stop()
     self.startBtn.setEnabled(True)
     self.endBtn.setEnabled(False)
      
     if __name__ == "__main__":
     app = QApplication(sys.argv)
     form = WinForm()
     form.show()
     sys.exit(app.exec_())

    运行结果:

    例二:

    '''
      【简介】
      PyQT5中关闭应用例子
     
     
     '''
      
     import sys
     from PyQt5.QtWidgets import *
     from PyQt5.QtGui import *
     from PyQt5.QtCore import *
      
     if __name__ == '__main__':
     app = QApplication(sys.argv)
     label = QLabel("<font color=red size=128><b>Hello PyQT,窗口会在10秒后消失!</b></font>")
     label.setWindowFlags(Qt.SplashScreen|Qt.FramelessWindowHint)
     label.show()
      
     # 设置10s后自动退出
     QTimer.singleShot(10000, app.quit)
     sys.exit(app.exec_())

    运行结果:

    2、QThread

        它是Qt线程类中最核心的底层类。要使用QThread开始一个线程,可以创建它的一个子类,然后覆盖其QThread.run()函数;PyQt的线程使用非常简单-------建立一个自定义的类(如Thread),使它继承自QThread,并实现其run()方法即可。

        在使用线程时可以直接得到Thread实例,调用其start()函数即可启动线程。线程启动之后,会自动调用其实现的run方法,该方法就是线程的执行函数。

        业务的线程任务就写在run()函数中,当run()推出之后线程基本就结束了。QThread有started和finished信号,可以为这两个信号指定槽函数,在线程启动和结束时执行一段代码进行资源的初始化和释放操作。更灵活的使用方法是,在自定义的QThread实例中自定义信号,并将信号连接到指定的槽函数,当满足一定条件后发射该信号。

        QThread类中的常用方法:

        start():启动线程

        wait():阻止线程

        sleep():强制当前线程睡眠

        QThread类中的常用信号:

        started:在开始执行run()函数之前,从相关线程发射该信号

        finished:当程序完成业务逻辑时,从相关线程发射该信号

        QThread实例:当在窗口中显示的数据比较简单时,可以把读取数据的业务逻辑放在窗口的初始化代码中;但如果读取数据的时间比较长,比如网络请求数据的时间比较长,则可以把这部分逻辑放在QThread线程中,实现界面的数据显示和数据读取的分离,以满足MVC(模型---视图---控制器)设计模式的要求。

        例子:

    '''
      【简介】
      PyQT5中 QThread 例子
     
     
     '''
      
     from PyQt5.QtCore import *
     from PyQt5.QtGui import *
     from PyQt5.QtWidgets import *
     import sys
      
     class MainWidget(QWidget):
     def __init__(self,parent=None):
     super(MainWidget,self).__init__(parent)
     self.setWindowTitle("QThread 例子")
     self.thread = Worker()
     self.listFile = QListWidget()
     self.btnStart = QPushButton('开始')
     layout = QGridLayout(self)
     layout.addWidget(self.listFile,0,0,1,2)
     layout.addWidget(self.btnStart,1,1)
     self.btnStart.clicked.connect( self.slotStart )
     self.thread.sinOut.connect(self.slotAdd)
      
     def slotAdd(self,file_inf):
     self.listFile.addItem(file_inf)
      
     def slotStart(self):
     self.btnStart.setEnabled(False)
     self.thread.start()
      
     class Worker(QThread):
     sinOut = pyqtSignal(str)
      
     def __init__(self,parent=None):
     super(Worker,self).__init__(parent)
     self.working = True
     self.num = 0
      
     def __del__(self):
     self.working = False
     self.wait()
      
     def run(self):
     while self.working == True:
     file_str = 'File index {0}'.format(self.num)
     self.num += 1
     # 发出信号
     self.sinOut.emit(file_str)
     # 线程休眠2秒
     self.sleep(2)
      
     if __name__ == "__main__":
     app = QApplication(sys.argv)
     demo = MainWidget()
     demo.show()
     sys.exit(app.exec_())

    运行结果:

    但是在PyQt中所有的窗口都在UI主线程中(就是执行了QApplication.exec()的线程),在这个线程中执行耗时操作会阻塞UI线程,从而让窗口停止响应。如果窗口长时间没有响应,则会影响用户体验,更严重的会导致程序崩溃。所以,为了避免出现这样的问题,要使用QThread开启一个新的线程,在这个线程中完成耗时的操作。例子如下:

    '''
      【简介】
      PyQT5中 QTimer例子
     
     
     '''
      
     import sys
     from PyQt5.QtCore import *
     from PyQt5.QtGui import *
     from PyQt5.QtWidgets import *
      
     global sec
     sec=0
      
     class WorkThread(QThread):
     trigger = pyqtSignal()
     def __int__(self):
     super(WorkThread,self).__init__()
      
     def run(self):
     for i in range(2000000000):
     pass
      
     # 循环完毕后发出信号
     self.trigger.emit()
      
     def countTime():
     global sec
     sec += 1
     # LED显示数字+1
     lcdNumber.display(sec)
      
     def work():
     # 计时器每秒计数
     timer.start(1000)
     # 计时开始
     workThread.start()
     # 当获得循环完毕的信号时,停止计数
     workThread.trigger.connect(timeStop)
      
     def timeStop():
     timer.stop()
     print("运行结束用时",lcdNumber.value())
     global sec
     sec=0
      
     if __name__ == "__main__":
     app = QApplication(sys.argv)
     top = QWidget()
     top.resize(300,120)
      
     # 垂直布局类QVBoxLayout
     layout = QVBoxLayout(top)
     # 加个显示屏
     lcdNumber = QLCDNumber()
     layout.addWidget(lcdNumber)
     button = QPushButton("测试")
     layout.addWidget(button)
      
     timer = QTimer()
     workThread = WorkThread()
      
     button.clicked.connect(work)
     # 每次计时结束,触发 countTime
     timer.timeout.connect(countTime)
      
     top.show()
     sys.exit(app.exec_())

    运行结果:

    3、事件处理

        PyQt为事件处理提供了两种机制:高级的信号与槽机制,以及低级的事件处理程序。今天就学低级的事件处理程序,也就是processEvents()函数的使用方法,它的作用是处理事件,简单地说,就是刷新页面。

        对应执行很耗时的程序来说,由于PyQt需要等待程序执行完毕才能进行下一步,这个过程表现在界面上就是卡顿;而如果在执行这个耗时程序时不断地运行QApplication.processEvents(),那么就可以实现一边执行耗时程序,一边刷新页面的功能,给人的感觉就是程序运行很流畅。因此QApplication.processEvents()的使用方法就是,在主函数执行耗时操作的地方,加入QApplication.processEvents().例子如下:

    '''
      【简介】
      PyQT5中实时刷新界面例子
     
     
     '''
      
     from PyQt5.QtWidgets import QWidget, QPushButton , QApplication ,QListWidget, QGridLayout
     import sys
     import time
      
     class WinForm(QWidget):
      
     def __init__(self,parent=None):
     super(WinForm,self).__init__(parent)
     self.setWindowTitle("实时刷新界面例子")
     self.listFile= QListWidget()
     self.btnStart = QPushButton('开始')
     layout = QGridLayout(self)
     layout.addWidget(self.listFile,0,0,1,2)
     layout.addWidget(self.btnStart,1,1)
     self.btnStart.clicked.connect( self.slotAdd)
     self.setLayout(layout)
      
     def slotAdd(self):
     for n in range(10):
     str_n='File index {0}'.format(n)
     self.listFile.addItem(str_n)
     QApplication.processEvents()
     time.sleep(1)
      
     if __name__ == "__main__":
     app = QApplication(sys.argv)
     form = WinForm()
     form.show()
     sys.exit(app.exec_())

    运行结果:

    四、网页交互

        略~

    展开全文
  • Anaconda+PyQt5+pycharm桌面GUI开发

    万次阅读 2018-11-23 17:09:18
    根据电脑环境,结合两篇博客内容整理笔记。 原文1连接:https://blog.csdn.net/weixin_41929524/article/details/81456308 ... 安装PyQt5与Qt Designer PyQt5 通常只要安装了Anoconda,就会默认装好Py...
  • PyQt5 多线程相关一些例子

    万次阅读 多人点赞 2019-06-14 13:44:11
    PyQt5 多线程相关一些例子 demo1 from https://www.cnblogs.com/hhh5460/p/5175322.html from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QGridLayout from PyQt5.QtCore import QThread, QObject, ...
  • PyQt5 教程 《绘画》

    千次阅读 2019-08-09 14:33:15
    PyQt5中绘画 QPainter的 paintEvent方法 绘图文字 绘图点 颜色 QPEN QBrush Bézier曲线 在PyQt5中绘画 PyQt5绘画系统能够渲染矢量图形,图像和轮廓基于字体的文本。当我们想要更改或增强现有小部件时,...
  • 『Python动手学』PyQt5入门教程

    万次阅读 2019-06-26 11:57:37
    PyQt5相关 PyQt5是一套来自Digia的Qt5应用框架和Python的粘合剂。支持Python2.x和Python3.x版本。本教程使用Pyhton 3。Qt库是最强大的GUI支持库的一种。PyQt5的官方主页是www.riverbankcomputing.co.uk/news。是...
  • PyQt5安装(一)

    万次阅读 多人点赞 2018-07-23 08:36:10
    PyQt5安装的各种坑 使用Python开发了几个小工具,真是被Python的开发效率惊叹到了,真是人生苦短,我用Python,但是开发的时候都没有制作界面,觉得不是很完美,所有想学习一下制作界面的工具,自身带的Tk工具界面...
  • Windows下python+pyqt5安装教程

    万次阅读 2018-05-13 21:53:51
    Windows下python3.6.4+pyqt5安装教程一、安装pythonpython下载地址:https://www.python.org/downloads/windows/选择适合自己电脑版本的python版本,我安装的是python3.6.4,下面都以python3.6.4为例说明安装过程。...
  • Pyqt5 入门教程例子

    2018-02-26 19:30:00
    pyqt5&python; Gui入门教程,本人的教程比较基础,所用方法不够亮骚,仅供新手入门,若大家有更好的方法不胜赐教!
  • PyQT5速成教程-2 Qt Designer介绍与入门

    万次阅读 2018-06-04 20:30:39
    PyQt中编写UI界面可以直接通过代码来实现,也可以通过Qt Designer来完成。Qt Designer的设计符合MVC的架构,其实现了视图和逻辑的分离,从而实现了开发的便捷。Qt Designer中的操作方式十分灵活,其通过拖拽的方式...
  • PyQt5自学攻略

    万次阅读 2018-09-03 12:42:42
    PyQt5简介 PyQt是QT框架的Python语言实现,存在有PyQt3,PyQt4,PyQt5三个版本。PyQt5已经于之前的版本有较大的区别,建议直接学习PyQt5就可以了。官方网站:...
  • pyqt5-python-Gui入门教程

    2018-09-08 22:42:05
    pyqt5-python-Gui的入门教材,讲的非常简单易懂,建议学QT的初学者学习!
  • PyQt5教程(一)

    万次阅读 多人点赞 2016-08-05 20:19:09
    在这部分教程中我们将学习PyQt5的一些基本功能一个简单的例子这是一个只显示一个小窗口的简单示例。但我们可以对这个窗口进行一些操作,如调整尺寸,最大化或最小化。这需要编写很多代码,但有人已经完成了这个功能...
  • python pyqt5 gui 入门教程 干货 ,新手必备,pyqt5 GUI开发教程,详细介绍了基本的程序结构和细小知识点。
  • PyQt5新手入门视频教程

    千次阅读 2019-04-14 16:39:36
    PyQt5新手入门视频教程 凭借“快速开发”这点优势,PyQt5越来越被大家所熟知,使用范围也越来越广。无论是工作项目还是作业要求,PyQt5都能让我们做到事半功倍。 笔者所写的《快速掌握PyQt5》系列文章就是带...
  • pyqt5中文教程,以图形和源代码的方式讲解基础技术。文档为PDF 格式。
  • 这篇博文通过图文详细介绍在PyCharm中如何完整优雅地安装配置PyQt5的所有工具包,主要内容包括PyQt5PyQt5-tools的依赖包安装和Qt Designer、PyUIC、PyRcc三个工具的设置。最后简单演示了PyQt5的调用方式及三个工具...

空空如也

1 2 3 4 5 ... 20
收藏数 50,695
精华内容 20,278
关键字:

pyqt5