Python开发GUI常用库PyQt6和PySide6介绍之二:设计师(Designer)

Python开发GUI常用库PyQt6PySide6介绍之二:设计师(Designer

PySide6和PyQt6都有自己的设计师(Designer),用于可视化地设计和布局GUI应用程序的界面。这些设计师提供了丰富的工具和功能,使开发者能够更轻松地创建用户友好的界面。Qt Designer的主要作用是为Qt应用程序创建和编辑用户界面。使用Qt Designer,你可以通过拖放操作来设计和构建用户界面,而无需编写代码。你可以使用Qt Designer创建各种复杂的用户界面,包括有多个窗口、菜单和工具栏的应用程序。

在使用PyQt6或PySide6开发应用程序时,都可以使用Qt Designer创建.ui文件来设计和布局应用程序的界面。.ui文件是一个纯粹的描述文件,用于描述应用程序的用户界面的结构和外观——主要用于描述应用程序的用户界面的结构和外观,包括窗口、控件、布局等,而不包含任何程序逻辑。它是设计界面的工具,需要与代码相结合才能实现完整的应用程序功能。

【特别提示:PyQt6和PySide6中的Qt Designer与C++版本的Qt Designer是相同的工具,它们产生的.ui文件是通用的,由Qt Designer生成的.ui文件是XML格式的,它描述了用户界面的结构和布局。这些文件是跨平台和跨语言的,可以在任何支持Qt的环境中使用,不论是C++、Python或其他支持Qt的编程语言。因此,无论是使用PyQt6、PySide6还是C++版本的Qt,.ui文件都可以被相应工具转换为相应的编程语言极其API支持的用户界面代码文件。】

.ui文件通常需要将其转换为.py文件,以便在Python代码中加载和使用。

使用相应的工具将.ui文件转换为.py文件。在PyQt6中,可以使用pyuic6命令,而在PySide6中,可以使用pyside6-uic命令。

PyQt6和PySide6都使用Qt Designer(designer.exe)作为界面设计工具,所以它们的 Designer 打开的界面是一样的,但是需要注意,生成的 .ui 文件需要使用各自库的工具(pyuic 对于PyQt6,pyside2-uic 对于PySide6)来转换为Python代码。

要想用好PyQt6和PySide6的设计师(Designer),了解信号和槽的概念非常重要。

在PyQt6和PySide6中,信号(Signal)和槽(Slot)是用于实现部件之间通信的机制。信号是由部件(例如按钮、滑块、文本框等)发出的事件,而槽是与信号关联的函数,用于响应信号并执行相应的操作。对于新手来说,学习使用PySide6和PyQt6的Qt Designer可能会有一些挑战,尤其是涉及信号和槽的使用时。查找和学习一些好的示例代码是很有帮助的,这些示例可以展示不同的GUI元素的用法,以及如何使用信号和槽进行交互。你可以跟着练习。也可以尝试创建一些小的GUI项目,如简单的窗口,这样可以更好地理解如何使用Qt Designer设计界面,以及如何在代码中添加自定义的信号和槽。

PySide6的设计师的启动

安装了PySide6,就已经安装了可视化界面设计工具设计师(Designer。在Windows上,您通常可以在Python的安装路径【查看Python安装路径方法,在cmd中使用命令:py -0p ,其中0是零】下的 python310\Lib\site-packages\PySide6 (Windows中)目录中找到 designer.exe 文件,双击打开。

【为方便使用,可以创建桌面快捷方式:右击designer.exe 文件,使用右键菜单建立桌面快捷方式,参见下图:

打开designer.exe显示如下图:

“新建窗体”对话框中,列出了几种不同的用户界面模板。这些模板是用于快速开始设计图形用户界面(GUI)的预定义布局。

:下面是每个选项的简要说明:

1.Dialog with Buttons Bottom - 这个模板提供了一个对话框,其中包含了在底部排列的按钮。这种类型的对话框通常用于“确定”、“取消”或其他类似的操作按钮。

2.Dialog with Buttons Right - 类似于上一个模板,但是按钮是在对话框的右侧。这种布局可能用于某些应用程序中,以提供与内容并列的操作选项。

3.Dialog without Buttons - 这是一个没有预定义按钮的对话框模板。它可以用于当你需要一个简单的对话框来显示信息或者自定义内容和控件时。

4.Main Window - 这个模板是为主窗口设计的,它通常包括菜单栏、工具栏、状态栏和中心窗口区域。这是一个复杂的应用程序的起点,可以包含多个内部窗口或视图。

5.Widget - 这个模板提供了一个基本的小部件,没有预定义的菜单或按钮。这适用于创建简单的GUI组件,或者作为更大界面中的一个元素。

用户可以根据自己的需求选择一个模板作为起点,然后在Qt Designer中进一步定制和添加所需的控件和布局。】

PyQt6的设计师的启动

安装PyQt6并不会安装可视化界面设计工具设计师(Designer),要用 Designer还需要安装Pyqt6-tools。安装Pyqt6-tools时,有时可能发生与最新的Python的版本中有一些不兼容的问题,安装不了或安装不全(例如在Python安装路径的\Lib\site-packages中找不到qt6_applications目录),这时需要考虑降级Python版本,或等待PyQt6及pyqt6-tools更新。

安装Pyqt6-tools使用如下命令:

pip install pyqt6-tools

我的电脑中,安装有了多个Python版本,需要指定版本号安装,我的电脑中,安装有了多个Python版本,需要指定版本号安装,也可以添加 -i https://mirrors.aliyun.com/pypi/simple/加速,我这里用:

py -3.10 -m pip install -i https://mirrors.aliyun.com/pypi/simple/ pyqt6-tools

pyqt6-tools安装之后,在Windows上,在Python的安装路径的python310\Lib\site-packages\qt6_applications\Qt\bin(Windows中)目录中找到 designer.exe 文件。

【为方便使用,可以创建桌面快捷方式:右击designer.exe 文件,使用右键菜单建立桌面快捷方式】

打开designer.exe显示如下图:

“新建窗体”对话框中,列出了几种不同的用户界面模板。这些模板是用于快速开始设计图形用户界面(GUI)的预定义布局。【细节见前面的 注】

PySide6和PyQt6的转换工具

PySide6的转换工具是pyside6-uic,PyQt6中的转换工具是pyuic6。

PyQt6和PySide6都使用Qt Designer来设计用户界面,并生成与框架无关的.ui文件。这些文件可以使用pyuic6(针对PyQt6)或pyside6-uic(针对PySide6)工具转换为.py文件。由于PyQt6和PySide6在API方面存在一些差异(例如信号和槽的连接方式、某些方法的命名等),因此需要使用不同的代码生成工具来确保生成的Python代码与相应的库正确地工作——用pyuic6转换为.py文件只能用于PyQt6项目,用pyside6-uic转换为.py文件只能用于PySide6项目。

pyside6-uic和pyuic6是用于将Qt Designer生成的UI文件转换为Python代码的工具。这些工具的主要作用是将UI设计文件(.ui)转换为Python代码文件(.py),以便您可以在Python程序中使用它们。

当您使用Qt Designer设计UI时,它会生成一个包含UI元素的XML文件。pyside6-uic和pyuic6工具可以将这个XML文件转换为Python代码,这样您可以在Python程序中更轻松地使用UI元素,例如按钮、文本框等。

pyside6-uic命令会被自动安装到Python的可执行文件目录中——Python安装目录的Scripts目录中。pyside6-uic的 -h参数查看命令的帮助信息,例如:pyside6-uic –h。

pyside6-uic 命令中的.ui文件 和.py文件都可带路径,例如:

pyside6-uic D:\Path\myform.ui -o D:\Path\myform.py

Pyuic6命令会被自动安装到Python的可执行文件目录中——Python安装目录的Scripts目录中。需要注意,要运行pyuic6命令可能需要添加 PyQt6 的路径到你的 PATH 环境变量中。在命令行中输入 pyuic6 -h 或 pyuic6 --help 应该可以查看 pyuic6 的帮助信息。

pyuic6 -x mydesign.ui -o mydesign.py

pyuic6命令中的.ui文件 和.py文件都可带路径,例如:

pyuic6 -x D:\Path\myform.ui -o D:\Path\ mydesign.py

其中,-x可选参数,用则生成的 Python 代码会包含一个主函数(if __name__ == "__main__":),即得到可执行代码。不用则生成的 Python 代码是一个模块级别的代码,包含了类的定义和界面的初始化,你需要手动导入并实例化这个类才能使用生成的代码。

注意:你可能遇到一种现象:

用PySide6的Qt Designer生成的.ui,用pyside6-uic生成.py文件,用python打开运行不报错,但不见窗体。

PyQt6为什么不这样,用PyQt6的Qt Designer生成的.ui,用pyside6-uic生成.py文件,用python打开运行正常出现窗体。

为什么?

解释:

PySide6的转换工具pyside6-uic 不能直接生成可执行脚本。【PySide6的转换工具pyside6-uic没有类似于PyQt6的转换工具pyuic6的可选参数-x】

PyQt6的转换工具pyuic6有-x可选参数,用则生成的 Python 代码会包含一个主函数(if __name__ == "__main__":),即得到可执行代码。不用则生成的 Python 代码是一个模块级别的代码,包含了类的定义和界面的初始化,你需要手动导入并实例化这个类才能使用生成的代码。

PyQt6中的转换工具pyuic6,若使用-x可选参数,.ui转换成.py文件后,通常会包含一个主函数,这个主函数会创建一个QApplication实例,加载UI并显示窗口,因此直接运行这个.py文件能够看到窗口。你可以在该.py文件的后面看到如下部分:

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Qt Designer的设计理念是将界面与逻辑代码分离,因此一般不用- x参数。如果不用- x参数,.ui转换成.py文件后生成的 Python 代码是一个模块级别的代码,包含了类的定义和界面的初始化,你需要手动导入并实例化这个类才能使用生成的代码。通常只会包含一个表示UI的类,且不含主函数:

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        ...

因此直接运行这个.py文件不会看到窗口,需要自己写代码来加载并显示窗口。也就是说,您还需要写一个.py文件,作为调用文件,在其中导入生成的.py文件中的Ui类,并创建一个Ui类的应用实例。例如,基本内容如下:

from PyQt6.QtWidgets import QApplication, QMainWindow
from my_ui import Ui_MainWindow #请将这里的my_ui替换成你生成的.py文件的名称

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)        

    # 自定义槽函数
    def on_button_clicked(self):
        print("Button clicked!")

if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

PySide6中的转换工具pyside6-uic, 不能直接生成可执行脚本,.ui转换成.py文件后,通常只会包含一个表示UI的类:

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        ...

因此直接运行这个.py文件不会看到窗口,需要自己写代码来加载并显示窗口。也就是说,在生成.py文件后,您还需要写一个.py文件,作为调用文件,在其中导入生成的.py文件中的Ui类,并创建一个Ui类的应用实例。例如,基本内容如下:

from PySide6.QtWidgets import QMainWindow, QApplication
from my_ui import Ui_MainWindow  # 请将这里的my_ui替换成你生成的.py文件的名称

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)        

    # 自定义槽函数
    def on_button_clicked(self):
        print("Button clicked!")

if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

特别提示:Qt Designer的设计理念是将界面与逻辑代码分离。这种分离界面和逻辑的方式有助于提高团队的协作效率。通过将界面设计和逻辑代码分开,可以实现更好的代码组织和可维护性。

设计师(Designer)使用

前面提到过,在PyQt6和PySide6中,信号(Signal)和槽(Slot)是用于实现部件之间通信的机制。通过使用设计师(Designer),你可以直观地设置信号与槽的关联。在使用Qt设计师(Qt Designer)时,你可以在图形界面下进行信号-槽的连接。

如何在Qt Designer中关联信号和槽?

方式1、拖拽的方式,具体步骤:

1.     打开你想编辑的.ui文件。

2.     选择"编辑信号/槽"模式。你可以在工具栏上点击"编辑信号/槽"图标,或者在菜单栏选择"编辑→编辑信号/槽",或者直接按快捷键F4。

3.     现在你将鼠标移动到部件上时,其外围有红色的轮廓线,这表示你已经进入了"编辑信号/槽"模式。

4.     在发出信号的部件上单击并拖动到接收信号的部件(通常是窗口或另一个部件)。例如,如果你想在点击一个按钮时执行某个操作,你就需要从这个按钮拖动到要接收这个信号的部件,通常是这个按钮所在的窗口。此时出现红色连接线,类似如下图:

5.     释放鼠标右键。这时会弹出一个对话框,类似如下图:

列出了你可以连接的信号和槽。

6.     在左侧“信号”列表中选择你想要的信号,比如clicked()。然后在右侧“槽”列表中选择你想响应的槽。点击“槽”列表下面的“编辑”按钮,弹窗出槽函数编辑界面,类似如下图:

在此,你可以直接选择连接“库”提供的槽,点击+号连接一个自定义的槽函数。

槽可以分为两类:系统默认提供的槽和自定义的槽。详见上一讲有关部分。

7.     点击“确定”按钮。现在,只要发出信号的部件触发了这个信号(例如,用户点击了这个按钮),接收信号的部件就会执行对应的槽(即执行相应的操作)。

8.     要退出信号/槽编辑模式,你可以进入"编辑窗口部件"模式:你可以在工具栏上点击"编辑窗口部件"图标,或者在菜单栏选择"编辑→编辑窗口部件",或者直接按快捷键F3。

9.     保存你的.ui文件。

方式2、使用"信号/槽编辑器":

"信号/槽编辑器"通常位于Qt Designer主窗口的下方,如果你看不到这个编辑器,可以在菜单栏选择"视图"->"信号/槽编辑器"来打开它。参见下图:

使用"信号/槽编辑器"关联信号和槽的步骤如下:

  1. 在Qt Designer的"信号/槽编辑器"中,点击加号按钮来添加一个新的信号和槽的连接。
  2. 在"发送者"一列,输入发送信号的部件的对象名。这通常是你在部件的"属性编辑器"中设定的"objectName"属性的值。例如,如果你的按钮的"objectName"是"myButton",那么在这里就填写"myButton"。
  3. 在"信号"一列,输入部件发出的信号名。例如,对于一个按钮,你可能会输入"clicked()"。
  4. 在"接收者"一列,输入接收信号的部件的对象名。通常这就是你的主窗口或另一个部件的"objectName"。
  5. 在"槽"一列,输入应对信号进行响应的槽的名称。如果你已经在代码中定义了一个槽,你可以在这里输入它的名称。如果你还没有定义槽,你可以在这里输入一个新的槽的名称,然后在你的代码中定义一个同名的函数。
  6. 点击空白区域或按Enter键,完成该信号-槽的编辑。

这样,你就成功使用"信号/槽编辑器"关联了一个信号和槽。你可以在"信号/槽编辑器"中看到你的所有信号和槽的连接,如果需要,你也可以随时修改或删除它们。

最后,保存你的.ui文件。当你把.ui文件转换为Python代码并运行你的应用程序时,你就可以看到信号和槽的效果了。

一)PySide6的设计师(Designer)的设计流程

1)启动Qt Designer,选择 "创建新窗体",然后选择您需要的窗体类型,这里选择 "Main Window"(主窗口)模板,建立一个空白的窗口,现在设计界面:调整窗口的大小和位置。可以使用geometry属性设置位置坐标(x,y)、大小(width,height);设置窗口属性:在属性编辑器中设置窗口windowTitle属性为"PySide6示例"。

还可以用font属性设置字体和字体大小等。

2)添加按钮控件:您可以从左侧的 "工具箱" 中拖动控件到窗口中。这里选择"PushButton" 拖动到窗口中合适位置。设置按钮属性:在属性编辑器中设置按钮的Text属性为"Click me!"

3)连接信号与槽:参加下图,具体操作参见“如何在Qt Designer中关联信号和槽?”部分。

我这里添加自定义槽函数名on_button_clicked()
 

4)当您设计过程中,可以随时保存您的成果,保存为 .ui 文件。我这里文件名保存为:demoA.ui。保存路径:D:\path。

顺便提示:.ui 文件是一个文本文件。Qt Designer中打开的.ui 文件,可以使用组合键Ctrl + r预览效果。

5)将 .ui 文件转换为 .py 文件,在命令行中执行以下命令:

pyside6-uic D:\Path\demoA.ui -o D:\Path\demoA.py

转换得到的demoA.py内容如下图(请留意图中箭头红线标识处):

6)将.ui转换成.py文件后,通常只会包含一个表示UI的类,且不含主函数,因此直接运行这个.py文件不会看到窗口,需要自己写代码来加载并显示窗口。需要写一个.py文件,作为调用文件,在其中导入生成的.py文件中的Ui类,并创建一个Ui类的应用实例。在这个文件中可以添加自定义槽函数(槽方法),基本内容如下:

from PySide6.QtWidgets import QMainWindow, QApplication
from demoA import Ui_MainWindow  # 注意这里的demoA不带扩展名

# 自定义槽函数
def on_button_clicked():
    print("Button clicked!")
    
if __name__ == "__main__":
    app = QApplication([])
    main_win = QMainWindow()
    ui = Ui_MainWindow()
    ui.pushButton.clicked.connect(on_button_clicked) # 连接自定义槽函数
    ui.setupUi(main_win)
    main_win.show()
    app.exec()

为方便起见,你可以将调用文件和换成.py文件放在同一目录中。保存文件名我这里设为:call_demoA.py。

7)现在可以运行试试了,用python启动作为调用文件。参见下图:

二)PyQt6的设计师(Designer)的设计流程

1)启动PyQt6Qt Designer,选择 "创建新窗体",然后选择您需要的窗体类型,这里选择 "Main Window"(主窗口)模板,建立一个空白的窗口,现在设计界面:调整窗口的大小和位置。可以使用geometry属性设置位置坐标(x,y)、大小(width,height);设置窗口属性:在属性编辑器中设置窗口windowTitle属性为"PyQt6示例"。

还可以用font属性设置字体和字体大小等。

2)添加按钮控件:您可以从左侧的 "工具箱" 中拖动控件到窗口中。这里选择"PushButton" 拖动到窗口中合适位置。设置按钮属性:在属性编辑器中设置按钮的Text属性为"Click me!"

3)连接信号与槽:参加下图,具体操作参见“如何在Qt Designer中关联信号和槽?”部分。

我这里添加自定义槽函数名on_button_clicked()

4)当您设计过程中,可以随时保存您的成果,保存为 .ui 文件。我这里文件名保存为:demoA.ui。保存路径:D:\path。

顺便提示:.ui 文件是一个文本文件。Qt Designer中打开的.ui 文件,可以使用组合键Ctrl + r预览效果。

5)使用pyuic6命令将 .ui 文件转换为 .py 文件,在命令行中执行以下命令:

pyuic6   D:\Path\demoB.ui -o D:\Path\demoB.py

转换得到的demoB.py内容(请留意图中箭头红线标识处):

6)将.ui转换成.py文件后,通常只会包含一个表示UI的类,且不含主函数,因此直接运行这个.py文件不会看到窗口,需要自己写代码来加载并显示窗口。需要写一个.py文件,作为调用文件,在其中导入生成的.py文件中的Ui类,并创建一个Ui类的应用实例。在这个文件中可以添加自定义槽函数(槽方法),基本内容如下:

from PyQt6.QtWidgets import QApplication, QMainWindow
from demoB import Ui_MainWindow # 注意这里的demoB不带扩展名

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)        

    # 自定义槽函数
    def on_button_clicked(self):
        print("Button clicked!")

if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

为方便起见,你可以将调用文件和换成.py文件放在同一目录中。保存文件名我这里设为:call_demoB.py

7)现在可以运行试试了,用python启动作为调用文件。参见下图:

提示:Qt Designer主要用于设计和布局应用程序的用户界面,它创建的是一个描述用户界面布局和元素的XML文件。虽然它允许用户在不同的界面元素之间定义信号和槽的连接,但是它不支持创建更复杂的逻辑,例如:在菜单项和自定义Python函数之间创建连接,这些需要你在代码中手动连接信号到你的自定义槽函数。
 

PySide6 通过两种方式加信号和槽(通过代码和通过界面设计器)视频https://www.bilibili.com/video/BV1fP411Z77f/?spm_id_from=333.788

Qt Designer添加菜单

以建立一个简单记事本为例介绍

在此,用PySide6实现

用Qt Designer创建一个GUI窗口,注意,在“新建窗体”窗口中选择“Main Window”来创建一个空白的主窗口。修改了窗口的大小。

可以很方便地创建菜单和子菜单。

windowTitle 属性设置为: 记事本

在窗体放置一个Text Edit 小部件(Widget)

“文件”菜单项子项设置为:

子项名      shortcut属性         objectName属性值

打开        Ctrl+O                open_action

保存        Ctrl+S                 save_action

清除        Ctrl+Shift+C            clear_action

退出        Ctrl+Q                close_action

注意:shortcut属性的输入是按相应的键

下图是设计好的样子:

在设计过程中,可以使用快捷键Ctrl+R对窗口进行预览:

前面提到过,Qt Designer虽然允许用户在不同的界面元素之间定义信号和槽的连接,但是它不支持创建更复杂的逻辑,例如:在菜单项和自定义Python函数之间创建连接,这些需要你在代码中手动连接信号到你的自定义槽函数。

至此ui文件设计完成,我这里保存文件名为:Notepad_UI.ui,保存到D:\Path中。

将 .ui 文件转换为 .py 文件,在命令行中执行以下命令:

pyside6-uic D:\Path\Notepad_UI.ui -o D:\Path\Notepad_UI.py

编写 Python 代码:在 Python 代码中,导入生成的 UI 类,并在你的主窗口类中创建一个实例。其中,需要引入Notepad_UI,连接菜单项信号到自定义槽函数(如:self.open_action.triggered.connect(self.open_file))和自定义槽函数等。

完整代码如下:

import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog
from Notepad_UI import Ui_MainWindow #引入Notepad_UI

class NotepadWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        #连接菜单项信号到自定义槽函数
        self.open_action.triggered.connect(self.open_file)
        self.save_action.triggered.connect(self.save_file)
        self.clear_action.triggered.connect(self.clear_text)
        self.close_action.triggered.connect(self.close)

    #自定义的槽函数
    def open_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "打开文件")
        if file_path:
            with open(file_path, "r", encoding="utf-8") as file:
                content = file.read()
                self.textEdit.setPlainText(content)

    def save_file(self):
        file_path, _ = QFileDialog.getSaveFileName(self, "保存文件")
        if file_path:
            content = self.textEdit.toPlainText()
            with open(file_path, "w", encoding="utf-8") as file:
                file.write(content)

    def clear_text(self):
        self.textEdit.clear()

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

在这个示例中,我们创建了一个 NotepadWindow 类,它继承自 QMainWindow 和 Ui_MainWindow,并在构造函数中调用了 setupUi() 方法来设置界面。

然后,我们连接了菜单项的触发信号与槽函数。在槽函数中,我们实现了打开文件、保存文件和清除文本的功能。

其中,file_path, _ = QFileDialog.getOpenFileName(self, "打开文件") 中“file_path, _ ”的意思:file_path, _ 是一个元组解包(tuple unpacking)的语法。QFileDialog.getOpenFileName() 方法返回一个元组,其中包含用户选择的文件路径和文件类型过滤器。

确保将 Notepad_UI.py 文件与新的 Python 文件(我这里命名为Notepad.py)放在同一个目录下,并运行新的 Python 文件来启动记事本应用程序。

运行效果:

对上面实现的简单记事本的改进:为 TextEdit添加右键菜单以实现复制和粘贴功能。

代码如下:

import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog, QMenu ##添加QMenu
from PySide6.QtGui import QAction  ##添加这句
from PySide6.QtCore import Qt  ##添加这句

from Notepad_UI import Ui_MainWindow  #引入Notepad_UI

class NotepadWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        #连接菜单项信号到自定义槽函数
        self.open_action.triggered.connect(self.open_file)
        self.save_action.triggered.connect(self.save_file)
        self.clear_action.triggered.connect(self.clear_text)
        self.close_action.triggered.connect(self.close)

        #为TextEdit 添加右键菜单,实现复制和粘贴功能
        self.create_context_menu()

    ##添加从这里↓       
    def create_context_menu(self):
        self.textEdit.setContextMenuPolicy(Qt.CustomContextMenu)
        self.textEdit.customContextMenuRequested.connect(self.show_context_menu)

    def show_context_menu(self, pos):
        context_menu = QMenu(self.textEdit)
        copy_action = QAction("复制", self.textEdit)
        copy_action.setShortcut("Ctrl+C")
        copy_action.triggered.connect(self.textEdit.copy)
        context_menu.addAction(copy_action)

        paste_action = QAction("粘贴", self.textEdit)
        paste_action.setShortcut("Ctrl+V")
        paste_action.triggered.connect(self.textEdit.paste)
        context_menu.addAction(paste_action)

        context_menu.exec(self.textEdit.mapToGlobal(pos))
     ##到这里↑ 
        

    #自定义的槽函数
    def open_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "打开文件")
        if file_path:
            with open(file_path, "r", encoding="utf-8") as file:
                content = file.read()
                self.textEdit.setPlainText(content)

    def save_file(self):
        file_path, _ = QFileDialog.getSaveFileName(self, "保存文件")
        if file_path:
            content = self.textEdit.toPlainText()
            with open(file_path, "w", encoding="utf-8") as file:
                file.write(content)

    def clear_text(self):
        self.textEdit.clear()

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

为添加右键菜单,修改的代码中,我们定义了 create_context_menu 方法来设置TextEdit 的上下文菜单策略,并连接了 customContextMenuRequested 信号到 show_context_menu 方法。

在 show_context_menu 方法中,我们创建了一个 QMenu 对象,并添加了复制和粘贴的 QAction。每个 QAction 的触发信号都连接到TextEdit 的相应复制和粘贴方法。然后,我们使用 exec() 方法在鼠标点击的位置显示上下文菜单。

运行效果:

Python Qt GUI设计:菜单栏、工具栏和状态栏的使用方法 https://cloud.tencent.com/developer/article/1893307

OK!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习&实践爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值