PyQt5 布局管理、事件、信号以及对话框

news2024/11/27 22:24:44

布局管理

绝对定位

每个程序都是以像素为单位区分元素的位置,衡量元素的⼤⼩。所以我们完全可以使⽤绝对定位搞定每个元素和窗⼜的位置。

局限性:

  • 元素不会随着我们更改窗⼜的位置和⼤⼩⽽变化
  • 不能适⽤于不同的平台和不同分辨率的显⽰器
  • 更改应⽤字体⼤⼩会破坏布局
  • 如果我们决定重构这个应⽤,需要全部计算⼀下每个元素的位置和⼤⼩
import sys
from PyQt5.QtWidgets import QWidget, QLabel, QApplication

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
	    # 使⽤move()⽅法定位了每⼀个元素,使⽤x、y坐标。x、y坐标的原点是程序的左上⾓
        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()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

在这里插入图片描述

盒布局

使⽤盒布局能让程序具有更强的适应性。这个才是布局⼀个应⽤的更合适的⽅式。 QHBoxLayout 和QVBoxLayout 是基本的布局类,分别是⽔平布局和垂直布局。

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()
        # stretch函数在两个按钮前⾯增加了⼀些弹性空间
        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()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())


在这里插入图片描述

栅格布局

最常⽤的还是栅格布局了。这种布局是把窗⼜分为⾏和列。创建和使⽤栅格布局,需要使⽤QGridLayout模块。

import sys
from PyQt5.QtWidgets import QWidget, QPushButton, QGridLayout, QApplication

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
    	# 创建栅格化的按钮
        grid = QGridLayout()
        self.setLayout(grid)
        # 创建⼀个QGridLayout实例,并把放到程序窗口⾥
        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)
            # 创建按钮,并使⽤ addWidget() ⽅法把按钮放到布局⾥⾯
            grid.addWidget(button, *position)
            self.move(300, 150)
            self.setWindowTitle('Calculator')
            self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

在这里插入图片描述

制作提交反馈信息的布局

组件能跨列和跨⾏展⽰

import sys
from PyQt5.QtWidgets import QWidget, QLabel, QLineEdit, QGridLayout,QTextEdit, 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()  # QLineEdit 只有⼀⾏
        authorEdit = QLineEdit()
        reviewEdit = QTextEdit()  # 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)
        # 指定这个元素跨5⾏显⽰
        grid.addWidget(reviewEdit, 3, 1, 5, 1)
        self.setLayout(grid)
        self.setGeometry(300, 300, 350, 300)
        self.setWindowTitle('Review')
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

在这里插入图片描述

事件和信号

事件

所有的应⽤都是事件驱动的

在事件模型中,有三个⾓⾊:

  • 事件源 — 是发⽣了状态改变的对象
  • 事件 — 是这个对象状态改变的内容
  • 事件⽬标 —事件想作⽤的⽬标

事件源绑定事件处理函数,然后作⽤于事件⽬标⾝上。

PyQt5处理事件⽅⾯有个signal and slot机制。Signals and slots⽤于对象间的通讯。事件触发的时候,发⽣⼀个signal,slot是⽤来被Python调⽤的slot只有在事件触发的时候才能调⽤。

Signals & slots

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QLCDNumber, QSlider, QVBoxLayout, QApplication

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        lcd = QLCDNumber(self)
        sld = QSlider(Qt.Horizontal, self)
        vbox = QVBoxLayout()
        vbox.addWidget(lcd)
        vbox.addWidget(sld)
        self.setLayout(vbox)
        # 把滑块的变化和数字的变化绑定在⼀起
        sld.valueChanged.connect(lcd.display)
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Signal and slot')
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

在这里插入图片描述

重构事件处理器

在PyQt5中,事件处理器经常被重写。
替换事件处理器函数 keyPressEvent() ,实现按下ESC键程序就会退出。

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QApplication

class Example(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(300, 300, 250, 150)
        self.setWindowTitle('Event handler')
        self.show()

    def keyPressEvent(self, e):  # 键盘按下事件
        if e.key() == Qt.Key_Escape:  # 按下ESC键
            self.close()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

事件对象

事件对象是⽤python来描述⼀系列的事件⾃⾝属性的对象

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
        # 显⽰⿏标的X和Y坐标
        self.text = "x: {0}, y: {1}".format(x, y)
        self.label = QLabel(self.text, self)
        grid.addWidget(self.label, 0, 0, Qt.AlignTop)  # Qt.AlignTop 居顶
        self.setMouseTracking(True)
        self.setLayout(grid)
        self.setGeometry(300, 300, 350, 200)
        self.setWindowTitle('Event object')
        self.show()

    def mouseMoveEvent(self, e):
        # 事件追踪默认没有开启,当开启后才会追踪⿏标的点击事件
        # e 代表了事件对象,x() 和 y() ⽅法得到⿏标的x和y
        # 坐标点,然后拼成字符串输出到 QLabel 组件⾥
        x = e.x()
        y = e.y()
        text = "x: {0}, y: {1}".format(x, y)
        self.label.setText(text)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

X和Y的值代表当前鼠标的位置
在这里插入图片描述

事件发送

import sys
from PyQt5.QtWidgets import QMainWindow, QPushButton, QApplication

class Example(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        btn1 = QPushButton("Button 1", self)
        btn1.move(30, 50)
        btn2 = QPushButton("Button 2", self)
        btn2.move(150, 50)
        # 两个按钮都和同⼀个slot绑定
        btn1.clicked.connect(self.buttonClicked)
        btn2.clicked.connect(self.buttonClicked)
        self.statusBar()
        self.setGeometry(300, 300, 290, 150)
        self.setWindowTitle('Event sender')
        self.show()
	
	# buttonClicked() ⽅法决定了是哪个按钮能调⽤ sender() ⽅法
    def buttonClicked(self):
        sender = self.sender()
        self.statusBar().showMessage(sender.text() + ' was pressed')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

⽤调⽤ sender() ⽅法的⽅式决定了事件源。状态栏显⽰了被点击的按钮
在这里插入图片描述

信号发送

QObject 实例能发送事件信号

import sys
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets import QMainWindow, QApplication

class Communicate(QObject):
    # 创建⼀个叫closeApp的信号,这个信号会在⿏标按下的时候触发,事件与 QMainWindow 绑定
    # 创建⼀个 pyqtSignal() 属性的信号
    closeApp = pyqtSignal()

class Example(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.c = Communicate()
        # closeApp 信号 QMainWindow 的 close() ⽅法绑定
        self.c.closeApp.connect(self.close)
        self.setGeometry(300, 300, 290, 150)
        self.setWindowTitle('Emit signal')
        self.show()

    def mousePressEvent(self, event):
        # 点击窗⼜的时候,发送closeApp信号,程序终⽌
        self.c.closeApp.emit()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

点击窗口对话框便会消失,不展示

对话框

输⼊⽂字

QInputDialog 提供了⼀个简单⽅便的对话框,可以输⼊字符串,数字或列表

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):
        # 第⼀个参数是输⼊框的标题,第⼆个参数是输⼊框的占位符。对话框
        # 返回输⼊内容和⼀个布尔值,如果点击的是OK按钮,布尔值就返回True
        text, ok = QInputDialog.getText(self, 'Input Dialog', 'Enter your name:')
        if ok:
            self.le.setText(str(text))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_()

该⽰例生成⼀个按钮和⼀个输⼊框,可以直接在输入框输入内容
在这里插入图片描述
也可以点击按钮(Dialog)弹出对话框,输入。点击ok后,内容会替换输入框的内容
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2206793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

老板的“神助攻”:公司电脑监控软件

在当今的商业世界中,企业管理者都希望员工能全身心投入工作,为企业创造更多价值。然而,员工上班摸鱼的现象却让许多老板头疼不已。公司电脑监控软件的出现,为解决这一问题提供了可能。接下来,我们将详细介绍几款优质的…

新160个crackme - 079-DueList.5

运行分析 提示需要注册 PE分析 32位程序,PE Diminisher壳 手动脱壳 x32dbg打开程序,按一下F8,根据ESP定律,在此处下断点按一下F9,两下F8,来到OEP处00401000打开Scylla,点击转储保存文件点击IAT自…

深入理解Dubbo源码核心原理-Part3

到此开始讲解Dubbo消费端的源码 在消费一端,需要关注两件事情。第一,接口的proxy如何生成。第二,请求如何发送。 首先看到启动类 接下来看真正inject方法 现在需要思考,待注入的Bean从哪儿来,这个Bean必然注入的是一…

Basic penetration_1靶机渗透

项目地址 plain https://download.vulnhub.com/basicpentesting/basic_pentesting_1.ova 实验过程 开启靶机虚拟机 ![](https://img-blog.csdnimg.cn/img_convert/4135d3c176bdca1f661f756b8321c97a.png) 使用nmap进行主机发现,获取靶机IP地址 plain nmap 192.1…

如何删除不需要的右键菜单

比如要删除以下右键菜单: 1. 打开“命令提示符”,并输入“regedit”以打开注册表编辑器。或使用快捷键“WinR”打开“运行”窗口,输入“regedit”以打开注册表编辑器。 2. 在注册表编辑器中,找到路径“计算机HKEY_CLASSES_ROOT/Di…

IterComp: 从模型图库中迭代合成感知反馈学习,用于文本到图像的生成

我们从多个模型中收集组成感知模型偏好,并采用迭代反馈学习方法,使基础扩散模型和奖励模型都能逐步自我完善。 我们提出了一种迭代反馈学习方法,通过多次迭代,使基础扩散模型和奖励模型逐步自我完善,从而以闭环方式增…

智能化叉车作业安全高效监控管理系统方案

在物流作业中,智能叉车管理系统的引入,不仅极大地提升了作业效率,还显著增强了作业安全性,为物流行业的现代化转型注入了强劲动力。 1、产品简介 2023A智能叉车管理系统是用于工业车辆安全监控管理的车载终端,具有快…

1.4 使用Vite创建Vue 3项目

文章目录 什么是 ViteVite 的优点注意事项 创建 Vue 3 项目手动创建项目通过模板自动创建项目启动项目 Vue 3 项目目录结构Vue 3 项目运行过程项目运行过程项目关键文件 大家好,今天我们将一起学习如何使用 Vite 创建一个 Vue 3 项目。Vite 是一个现代的前端构建工具…

使用差分来测试开关模式电源

在从墙壁插座到被供电设备的过程中,电力通常通过开关模式电源,其中交流信号在到达设备之前被整流为直流。之后,直流信号(通常为 5 V)被传递到设备 PC 板上的 DC-DC 转换器,以将各种电压馈送到设备供电网络的…

2021年华为杯数学建模竞赛B题论文和代码

空气质量预报二次建模 尽管目前已有WRF-CMAQ模拟体系对空气质量进行预报,但由于部分污染物生成机理不完全明晰以及排放清单不确定等因素,空气质量的预报结果并不理想。因此,在WRF-CMAQ 模型一次预报的基础上进行更加准确的二次预报对提前获知…

MySQL-02.概述-安装配置

一.MySQL的安装 网址:MySQL :: Download MySQL Community Server 二.解压 三.配置 四.初始化MySQL 五.注册MySQL服务 六.启动MySQL服务 七.修改默认账户密码 八.登录MySQL 如果不想显示密码,安全访问,那么就不要输入密码,-p…

英特尔新旗舰 CPU 将运行更凉爽、更高效,适合 PC 游戏

英特尔终于解决了台式机 CPU 发热和耗电的问题。英特尔的新旗舰 Core Ultra 200S 系列处理器将于 10 月 24 日上市,该系列专注于每瓦性能,比之前的第 14 代芯片运行更凉爽、更高效。这些代号为 Arrow Lake S 的处理器也是英特尔首款内置 NPU(…

好玩的大数据之05:MySQL安装方法一(下载文件安装,mysql-server_8.0.21)

一、简介 MySQL 是最流行的关系型数据库管理系统,在 WEB 应用方面 MySQL 是最好的 RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。 二、下载 下载地址:https://www.mysql.com/ 选MySQL Community download…

图片怎么修改成圆角?5分钟将图片改成圆角方法

图片怎么修改成圆角?在数字化时代,图片已成为我们传递信息和表达创意的重要媒介。无论是社交媒体上的分享,还是专业设计中的应用,一张美观的图片总能迅速吸引人们的注意。为了进一步提升图片的视觉吸引力,让其在众多内…

Java通过RAG构建专属知识问答机器人_超详细

RAG:融合检索与生成的文本精准生成技术 检索增强生成(RAG)是一种技术,它通过结合检索模型和生成模型来提高文本生成的准确性。具体来说,RAG首先利用检索模型从私有或专有的数据源中搜索相关信息,然后将这些…

day-63 优质数对的总数 II

思路 nums1[i] 可以被 nums2[j] * k 整除,所以nums[i]/k的所有因子都符合条件,问题转换为遍历nums1,统计nums[i]/k的因子出现次数,然后遍历nums2,如果nums2[i]是某一个因子,将其出现次数加入答案中即可 解题过程 利用哈希表统计出…

2024年第三季度Sui DeFi总结

受益于Sui上一系列基础性发展的推动,DeFi流动性和网络性能在2024年Q3得到了显著提升。Sui新的共识引擎Mysticeti开始在网络上推广,极大地降低了延迟,并使交易得以快速确认。新的原生桥接工具Sui Bridge也在测试后正式上线,使得Sui…

睿考网:2025年中级会计师考试备考

有准备的人已经开始备考25年中级会计师考试了,关于25年中会考试,这些信息提前了解一下! 25年中级会计报名条件和报考关键时间 一、报考条件: 1.具备大学专科学历,从事会计工作满5年。 2.具备大学本科学历或学士学位&#xff0…

我的2023,一个创业者的自述与思考(3)

前言 计划是每年都会写一篇总结,但是很遗憾去年因为不可控的原因没有写,今年正常的对2023年做一个总结,总结的目的是为了给自己一个时间节点,告诉自己一年结束了,新的一年又要开始,同时也是向关心我的亲人、…

VMware vCenter Server 8.0U3c 发布下载,修复 U3b 更新停止响应的问题

VMware vCenter Server 8.0U3c 发布下载 - 集中式管理 vSphere 环境 Server Management Software | vCenter 请访问原文链接:https://sysin.org/blog/vmware-vcenter-8-u3/ 查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org VMw…