Pyqt5高级技巧2:Tab顺序、伙伴快捷键、各类常用控件的事件、可移动的卡片式布局(含基础Demo)

news2024/12/23 9:17:52

目录

一、编辑Tab顺序

 二、编辑伙伴

三、设置快捷键(仅MainWindow可用)

四、信号槽

【基本介绍】

【常用信号槽】控件对窗体(拖地)

【常用信号槽】控件对控件

【自定义信号槽】步骤

五、设计文件的转化

六、GUI的运行

1.main.py的建立(卡片式布局不适用)

2.生成代码中setupUI的更改

3.Dto.py的建立(全局变量库)

 【Dto.py】(和Event.py并列)

【Event.py】调用dto(ui转化来的)

4.BLL.py的建立

5.总结:运行一个GUI的步骤

七、可移动的卡片式布局demo

1.main.py的建立(卡片式布局)

2.生成代码setupUI的添加

3.预览效果

八、常见问题

Q1:如何给树添加子节点:

 Q2:坐标怎么看

 Q3:禁止放大怎么设置

一、编辑Tab顺序

        点击下面这个按钮后,按控件调整tab的顺序,设置好后,鼠标聚焦在输入框1中,按一下tab鼠标聚焦会跳到下一个输入框中

        编辑tab结束后,按下面这个按钮重新返回页面布局 

 二、编辑伙伴

 (删除伙伴的方法:框选-右键选择全部-删除)

三、设置快捷键(仅MainWindow可用)

        例如我菜单(MainWindow有菜单栏,Widget没有),有一个作者介绍的动作(action),我可在动作编辑器中加入快捷键

四、信号槽

【基本介绍】

        删除槽函数的方法:右键【控件】-点击【选择全部】-【删除】/【全部删除】

        编辑槽函数的方法:右下角

【常用信号槽】控件对窗体(拖地)

控件名称触发事件触发的槽函数说明
Buttonclicked()close()关闭窗体
Buttonclicked()showFullScreen()
showMaximized()
showMinimized()
showNormal()

全屏放大

放大

最小化

窗体大小恢复

TreeWidgetclicked(QModelIndex)自定义信号槽树组件被点击时触发自定义信号槽
各大输入框textChanged()自定义信号槽输入框输入发生改变时触发自定义信号槽
ComboboxcurrentIndexChanged()自定义信号槽选择框选项发生改变时触发自定义信号槽
Checkbox/radioBoxtoggled(bool)自定义信号槽选择选项发生改变时触发自定义信号槽

【常用信号槽】控件对控件

主控件从控件触发事件触发结果说明
Button任意输入框clicked()clear()清空输入
Button任意输入框clicked()

【双箭头】selectall()+copy()

复制输入框的所有内容

Button任意输入框clicked()

【双箭头】selectall()+cut()

剪切输入框的所有内容

Button任意输入框clicked()paste() 将粘贴板的内容到输入框 
Button任意输入框clicked()setfocus()鼠标聚焦输入框
Button任意输入框clicked()undo()将输入框的输入内容撤销
Button任意输入框clicked()redo()+undo()将输入框的输入内容反撤销
Checkbox/radioBox任意输入框toggled(bool)setDisabled(bool)

按一下禁用

再按一下启用

Checkbox/radioBox任意输入框toggled(bool)setHidden(bool)

按一下可见

再按一下不可见

【备注】不建议用 undo() / redo()+undo(),只要输入框的undoRedoEnabled设置为true支持用户CTRL+Z撤销,用按钮反而麻烦。

【自定义信号槽】步骤

以创建plainTextEdit的textchanged()事件为例,创建一个信号槽(事件触发方法)

生成的代码如下:

self.plainTextEdit.textChanged.connect(Form.executechanged)

需要做两件事情:

①改代码

self.plainTextEdit.textChanged.connect(self.executechanged)

②加信号槽-----事件触发方法(在生成的class Ui_Form(object)类下加即可)

def executechanged(self):
       pass#实现你的逻辑

【举个之前的例子】  

五、设计文件的转化

添加好pyqt5的外部工具后(如果不会添加,参考这篇文章),转换方法如下:

①找到xxx.ui文件,右键External Tools,选择PyUIC,自动生成一个xxx.py文件

②找到yyy.qrc文件,右键External Tools,选择Pyrcc,自动生成一个yyy.py文件

六、GUI的运行

1.main.py的建立(卡片式布局不适用)

新建一个【main.py】粘贴以下代码进去,这个是启动文件

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

if __name__ == '__main__':
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = untitled.Ui_Form() #①untitled是你ui转换后的py文件   ②根据ui设计的窗体类型,看是:Ui_Form 还是 Ui_MainWindow  不知道可以去untitled.py看看类名
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

运行【main.py】,即可运行我们的GUI! 

2.生成代码中setupUI的更改

        如果有自定义信号槽,connect处 类名=>self 即可(参考上面)。

3.Dto.py的建立(全局变量库)

        建立这个类是为了更容易地获取变量和设置变量,我们在获取变量的时候可以给变量设置别名,Dto是一个模板,需要根据实际情况去修改。这步是非必要的。

 【Dto.py】(和Event.py并列)

import os

from PyQt5.QtWidgets import QWidget, QApplication, QFileDialog


class Store:
    # 初始化变量,你可以【自主命名】,例如将【BookTree】替换掉【treeselect】
    # 按照这个模板灵活修改
    treeselect = ""
    isradio = False
    ischeck = False
    Comboxtext = ""
    Linetext =""
    Plaintext =""

    # 获取前端的值存进Store类
    def UpdateVar(self,Form):  #下面的self是传入的Form
        """ 调用示例: Dto.Store.UpdateVar(self,Ui_Form) 获取变量前调用"""
        try:
            #---- 打印控件列表,从控件列表中选择控件赋值 ----
            L=[]
            for attr_name in dir(self):
                attr = getattr(self, attr_name)
                if isinstance(attr, QWidget):
                    L.append(attr_name)
            print(L)
            #---- 打印控件列表,从控件列表中选择控件赋值 ----

            # ------- 变量赋值 -------
            Store.treeselect= self.treeWidget.currentItem().text(0)   #树选中的节点名称
            Store.isradio = True if self.radioButton.isChecked() else False  #radiobutton是否被选择
            Store.ischeck = True if self.checkBox.isChecked() else False  #checkBox是否被选择
            Store.Comboxtext = self.comboBox.currentText()  #获取Combobox选中的选项文本
            Store.Linetext = self.lineEdit.text()  #获取lineEdit输入
            Store.Plaintext  = self.plainTextEdit.toPlainText()  #获取plainTextEdit输入
            # ------- 变量赋值 -------

            # ------- 通过反射打印Store的值 -------
            class_attributes = Store.__dict__
            for attr, value in class_attributes.items():
                if not attr.startswith('__'):  # 过滤掉特殊属性
                    print(f"【反射】变量:{attr},值:{value}")
            # ------- 通过反射打印Store的值 -------

        except Exception as ex:
            print(f"更新变量时发生错误:{ex}")

    # 获取前端的输入框控件和值,设置好输入框的值
    def Settext(widget, text):
        """调用示例: Dto.Store.Settext(self.plainTextEdit,"我设置的内容")"""
        try:
            if hasattr(widget, 'setPlainText'):
                widget.setPlainText(text)
            elif hasattr(widget, 'setText'):
                widget.setText(text)
            else:
                raise TypeError("不支持设置该输入框的值")
        except Exception as ex:
            print(f"设置输入框的值时发生错误:{ex}")

    def EnableChange(widget):
        """调用示例:Dto.Store.EnableChange(self.radioButton)"""
        try:
            if hasattr(widget, 'isEnabled') and hasattr(widget, 'setEnabled'):
                current_state = widget.isEnabled()
                widget.setEnabled(not current_state)
            else:
                raise TypeError("不支持转化")
        except Exception as ex:
            print(f"控件可用性转化时发生错误:{ex}")

class Common:
    def Openfile(self,path):#打开指定路径
        """调用示例:returnstring=Dto.Common.Openfile(self,"F:\Autogenerate")"""
        import os
        try:
            os.startfile(path)
            return "已打开路径:"+path
        except Exception as ex:
            return "出错了:"+str(ex)

    def PopWindow(self,num,string):#弹窗提示
        """调用示例:returnstring=Dto.Common.PopWindow(self,2,"您确定吗")"""
        #调用示例:
        # if(Dto.Common.PopWindow(self,2,"您确定吗")):
        #     print("yes!")
        from PyQt5.QtWidgets import QMessageBox
        if (num==1):
            return QMessageBox.information(None, "温馨提示", string, QMessageBox.Yes)== QMessageBox.Yes
        elif (num==2):
            return QMessageBox.question(None, "询问", string, QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)== QMessageBox.Yes
        elif (num==3):
            return QMessageBox.warning(None, "警告", string, QMessageBox.Yes)== QMessageBox.Yes
        else:
            return QMessageBox.warning(None, "出错", string, QMessageBox.Yes)== QMessageBox.Yes

    def WriteFile(self,path,data):#写txt文件
        """调用示例:returnstring=Dto.Common.WriteFile(self, "D:\Autogenerate", "测试测试")"""
        import os
        from datetime import datetime
        try:
            os.makedirs(path, exist_ok=True)#不存在则创建路径
            timestamp = datetime.now().strftime("%Y-%m-%d   %H-%M-%S")# 获取当前时间戳
            file_path = os.path.join(path, f"{timestamp}.txt")# 创建文件路径和文件名
            with open(file_path, 'w') as file:
                file.write(f"""执行时间: {datetime.now().strftime("%Y-%m-%d   %H-%M-%S")}\n""")
                file.write(data)
            return f"""创建成功,时间:{datetime.now().strftime("%Y-%m-%d   %H-%M-%S")}"""
        except Exception as ex:
            return "出错了:"+str(ex)

    def Patse(self,data):
        """调用示例:returnstring=Dto.Common.Patse(self, "测试测试")"""
        try:
            clipboard = QApplication.clipboard()
            clipboard.setText(data)
            return "复制成功"
        except Exception as ex:
            return "复制失败:" + str(ex)

    def GetFileurl(self):#弹窗让用户选文件,选完返回一个url
        """调用示例:url = Dto.Common.GetFileurl(self)"""
        return QFileDialog.getOpenFileName()[0]

    def GetFolderurl(self):#弹窗让用户选文件夹,选完返回一个url
        """调用示例:url = Dto.Common.GetFolderurl(self)"""
        return QFileDialog.getExistingDirectory()

    def GetFolderByFileUrl(self,fileurl):#传入文件路径,传出文件夹路径
        """调用示例:url = Dto.Common.GetFolderByFileUrl(self,"C:\\Users\\ASUS\\Desktop\\temp\\01.pdf")"""
        return os.path.dirname(fileurl)

【Event.py】调用dto(ui转化来的)

from PyQt5 import QtCore, QtGui, QtWidgets
import Dto  # 1.引入全局变量库,文件头部import Dto 


class Ui_Form(object):
    def setupUi(self, Form):
        #省略自动生成的代码
        self.retranslateUi(Form)
        self.treeWidget.clicked['QModelIndex'].connect(self.executechanged) # 树被点击时触发自定义槽函数

    def retranslateUi(self, Form):
        #省略自动生成的代码


    def executechanged(self): #自定义槽函数
        Dto.Store.UpdateVar(self,Ui_Form) # 2.更新变量值(入参:self Ui_Form类)
        print("当前选中的树节点是:")
        print(Dto.Store.treeselect)# 3.【使用Dto】获取变量值
        Dto.Store.Settext(self.plainTextEdit,"888") # 4.【使用Dto】设置输入框(plainTextEdit Linetext)的值,如果是清空输入框,第二个入参可以是""
        Dto.Store.EnableChange(self.radioButton) # 5.【使用Dto】 使控件可用和不可用发生转化

        #还要Dto.Common方法自行探索

4.BLL.py的建立

        这里一般是写一些逻辑,例如我在里面写一个helloword方法,导入后(import BLL),调用时直接写BLL.helloword()即可调用。

【调用方法注意事项】调用窗体的方法,需要写成“self.MethodName()”,self就是窗体本身。

【说明】这步是非必要的。

5.总结:运行一个GUI的步骤

        1.转化好ui文件和qrc文件(转化成.py)

        2.完成ui.py中setupUI代码的更改

        3.建立main.py(程序的入口,其中下面这句代码,Event是ui文件转py后的名称,Ui_Form是ui生成的类名)

ui = Event.Ui_Form()

        4.建立Dto.py(建议,当然你在ui.py下堆代码也行,后期很难维护,下同),建立BLL.py

        5.运行main.py

七、可移动的卡片式布局demo

1.main.py的建立(卡片式布局)

【main.py】(卡片式布局,完整)

        注意:MainWindow的第2个入参根据实际情况而调整

import Event
import sys
from PyQt5.QtWidgets import QApplication
from PyQt5 import QtCore, QtWidgets

class MainWindow(QtWidgets.QWidget, Event.Ui_Form):#将这里的【Event.Ui_Form】修改为实际的【py文件名.类名】即可
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.is_moving = False
        self.old_pos = None

    def mousePressEvent(self, event):#重写鼠标移动事件
        if event.button() == QtCore.Qt.LeftButton:
            self.is_moving = True
            self.old_pos = event.globalPos()

    def mouseMoveEvent(self, event):
        if self.is_moving:
            delta = event.globalPos() - self.old_pos
            self.old_pos = event.globalPos()
            self.move(self.pos() + delta)

    def mouseReleaseEvent(self, event):
        if event.button() == QtCore.Qt.LeftButton:
            self.is_moving = False

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())


2.生成代码setupUI的添加

【Event.py】增加隐藏标题栏、主窗体背景设为透明的代码

Form.setWindowFlags(QtCore.Qt.FramelessWindowHint)  #加上,隐藏标题栏
Form.setAttribute(QtCore.Qt.WA_TranslucentBackground)  #加上,窗体透明化
class Ui_Form(object):
    def setupUi(self, Form):
        #自动生成的代码

        Form.setWindowFlags(QtCore.Qt.FramelessWindowHint)  #加上,隐藏标题栏
        Form.setAttribute(QtCore.Qt.WA_TranslucentBackground)  #加上,窗体透明化

    def retranslateUi(self, Form):
        #自动生成的代码

3.预览效果

        如图,以下窗体是可拖动的

八、常见控件的用法

1.通用

self.控件名称.clicked.connect(self.方法名) #点击事件

self.控件名称.textChanged.connect(self.方法名) #值变化事件

self.comboBox.currentIndexChanged.connect(self.方法名) #下拉框值改变事件

2.stackedWideget

print(self.stackedWidget.currentIndex())#打印当前页面索引
print( self.stackedWidget.currentWidget().objectName())#打印当前页面名称
print(self.stackedWidget.count())#打印总页数
self.stackedWidget.setCurrentIndex(2)#跳转到索引=2的页面

九、常见问题

Q1:如何给树添加子节点:

【需要添加两个地方】

注意item_0是父节点,item_1是子节点,一一对应的

 Q2:坐标怎么看

含义:起始坐标+宽高

QRect(260, 10, 101, 31)

- 值越大越往右:260

- 值越小越往下:10

- 宽度:101

- 高度:31

 Q3:禁止放大怎么设置

Form.setMaximumSize(Form.width(), Form.height())

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

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

相关文章

【研发日记】吃透新能源充电协议(一)——GB27930实例报文解析

文章目录 前言 背景介绍 充电协议框架 充电握手阶段 充电准备阶段 充电传输阶段 充电结束阶段 错误处理阶段 总结 参考资料 前言 近期在一个嵌入式开发项目中,用到了新能源充电协议,期间在翻阅各种资料文件时,一些地方还是容易理解…

包装和类练习 Stack的使用

目录 1.最小栈 2.有效的括号 3.栈的压入、弹出序列 4.逆波兰表达式求值 5.链栈与顺序栈相比&#xff0c;比较明显的优点是&#xff08; &#xff09; 1.最小栈 2.有效的括号 class Solution {public boolean isValid(String s) {Stack<Character> st new Stack<&g…

I/O方式

目录 一、程序查询方式 1.程序查询方式的特点 2.程序查询方式可分类 ①独占查询 ②定时查询 二、中断方式 1.中断I/O流程 2.例题 三、DMA方式 1.DMA控制器 2.特点 3. DMA的传送方式 ①停止CPU ②周期挪用 ③DMA和CPU交替访存 4.传送流程 ①预处理 ②数据传…

AIGC时代算法工程师的面试秘籍(第二十一式2024.8.19-9.1) |【三年面试五年模拟】

写在前面 【三年面试五年模拟】旨在整理&挖掘AI算法工程师在实习/校招/社招时所需的干货知识点与面试经验&#xff0c;力求让读者在获得心仪offer的同时&#xff0c;增强技术基本面。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&#x1f4aa; 欢迎大家关注Rocky…

海外云服务器安装 JDK8 (Ubuntu 18.04 记录篇)

本文首发于 秋码记录 曾几何时&#xff0c;我可是国内云厂商的忠实用户啊。 而今&#xff0c;却不再为云服务器&#xff08;尤指国内云厂商&#xff09;续费了&#xff0c;作为我的个人网站 秋码记录 选择了托管在 gitlab.com Pages服务上。 国内云厂商对新老用户持有两种截…

Linux网络编程入门及OSI七层模型

目录 OSI七层模型 TCP/IP五层(或四层)模型 ​编辑 协议报头 局域网 以太网 令牌环网 无线LAN OSI七层模型 TCP/IP五层(或四层)模型 物理层: 负责光/电信号的传递方式. 比如现在以太网通用的网线(双绞 线)、早期以太网采用的的同轴电缆 (现在主要用于有线电视)、光纤, 现…

全能型AI与专业型AI:未来的选择与挑战

引言 随着人工智能技术的飞速发展&#xff0c;市场上出现了多种类型的AI产品&#xff0c;其中全能型AI与专业型AI是两大主要类别。近期&#xff0c;OpenAI预计推出的代号为“草莓”的新AI引起了广泛关注&#xff0c;这一全能型AI的推出引发了关于未来AI趋势的热烈讨论。在这个…

学会自定义LayoutManager

最开始我在学习自定义LayoutManager的时候&#xff0c;也是网上搜文章&#xff0c;看博客&#xff0c;以及一些公众号的推文。刚开始看的时候觉得还是那么回事&#xff0c;但是在慢慢的深入LayoutManager源码才发现很多的文章其实都是不合格&#xff0c;乃至可以说是很误导人的…

vue3+elementplus的表格展示和分页实战

文章目录 一、Element Plus的安装使用二、el-table 表格组件三、el-pagination 分页组件四、全部代码五、效果 Element Plus 是一个基于 Vue 3 的现代化 UI 组件库&#xff0c;旨在帮助开发者快速构建美观且功能丰富的 Web 应用程序。它提供了大量的 UI 组件&#xff0c;如按钮…

leetcode3 无重复字符的最长子串

思路 双指针 易错点 什么时候更新长度 除了每次有重复的要更新 &#xff0c;如果abc这种&#xff0c;本身就不会重复&#xff0c;那maxLength就永远不会更新了。 思路不对 left不应该是1&#xff0c;对于abca&#xff0c;是1 对于 abcc,应该直接加3&#xff0c;所以需要记…

Python 从入门到实战4(序列的操作)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;通过熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 上篇文章我们通过举例学习了python 中列表的简单操作&#xff0c;…

Codeforces Round 107 (Div. 1) A. Win or Freeze (博弈论 + 数论*1400)

如果一个数是质数或者是1&#xff0c;那么一定是先手获胜&#xff0c;因为不能操作。 我们知道&#xff0c;一个数一定可以由 p 1 k 1 ∗ p 2 k 2 ∗ p 3 k 3 … p_{1}^{k_1}*p_{2}^{k_2}*p_3^{k_3}\dots p1k1​​∗p2k2​​∗p3k3​​…来唯一表示&#xff0c;那么我们就可以…

从入门到精通:掌握 CMD 与 PowerShell 之间的秘密

在日常使用 Windows 系统时&#xff0c;很多人都习惯于打开 CMD&#xff08;命令提示符&#xff09;来执行各种操作&#xff0c;从简单的文件管理到复杂的脚本编写&#xff0c;CMD 作为一个经典的工具确实陪伴我们走过了漫长的岁月。然而&#xff0c;随着系统管理需求的提升和自…

什么是EDR、NDR、MDR、XDR?他们之间什么区别?

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 概述 EDR是什…

opencv之图像平滑处理

文章目录 前言1.什么是平滑处理2.均值滤波2.1基本原理2.1 函数语法 3.方框滤波3.1基本原理3.2函数语法 4.高斯滤波4.1基本原理4.2函数语法 5.中值滤波5.1基本原理5.2 函数语法 6.双边滤波6.1基本原理 温馨提示 前言 **图像平滑处理是图像处理和计算机视觉领域中的一个核心技术…

yolov8改进策略,有可以直接用的代码,80余种改进策略,有讲解

YOLOv8改进策略介绍 YOLOv8是在YOLOv7的基础上进一步发展的目标检测模型&#xff0c;继承了YOLO系列模型的优点&#xff0c;如实时性、准确性和灵活性。然而&#xff0c;任何模型都有进一步改进的空间&#xff0c;以提高其性能、准确性和鲁棒性。下面是针对YOLOv8的一些改进策…

电容的分类

电容作为电子产品中不可或缺的元件&#xff0c;其种类繁多&#xff0c;各具特色。以下是电容的主要分类、作用及优缺点概述&#xff1a; 一、电容的分类 电容的分类方式多样&#xff0c;常见的分类方式包括按结构、用途、电解质类型及制造材料等。 按结构分类&#xff1a; 固…

搞懂奇偶校验

当我们有一串二进制的数据时&#xff0c;如何在这串二进制数据的最前面&#xff0c;或者最后面&#xff0c;添加一位的奇检验位或者偶校验位呢&#xff1f; &#xff08;1&#xff09;首先要明确使用什么校验&#xff1a;你使用奇校验&#xff0c;还是偶检验&#xff1f; &am…

使用 EasyExcel 高效读取大文件 Excel

使用 EasyExcel 高效读取大文件 Excel 的最佳实践 在现代应用中&#xff0c;数据处理经常涉及到大规模数据集的处理&#xff0c;Excel 作为一种常见的文件格式&#xff0c;经常用于数据导入和导出。然而&#xff0c;传统的 Excel 处理库如 Apache POI 在处理大文件时可能会面临…

基于Java+SpringBoot+Vue的植物健康系统

基于JavaSpringBootVue的植物健康系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345; 某信 gzh 搜索【智能编程小助手】获取项…