当前位置: 代码网 > it编程>前端脚本>Python > PyQt5新手教程(五万字)

PyQt5新手教程(五万字)

2024年08月02日 Python 我要评论
PyQt是Python编程语言的一个GUI(图形用户界面)工具包,它允许开发人员使用Python语言创建桌面应用程序。PyQt是基于Qt库的Python封装,Qt是一个流行的C++框架,用于开发跨平台的应用程序。

文章目录


pyqt界面开发的两种方式:可视化ui + 编程式ui


一、pyqt 简介

pyqt官网首页:https://www.riverbankcomputing.com/software/pyqt/
通过 pip 安装 pyqt:pip install pyqt5

二、pyqt 与 qt 的蒙娜丽莎

三、pyqt 布局管理器(layout manager)

3.1、简介

3.1.1、布局管理器的定义

布局管理器(layout manager):用于在图形用户界面(gui)中管理窗口中部件(widget)布局的工具。通过容器的方式来布置和管理部件的位置和大小,而无需手动计算和设置每个部件的位置(但支持)。

3.1.2、布局管理器的类型

3.1.3、布局管理器的使用方法

(1)将部件添加到布局管理器中
(2)将布局管理器设置为窗口或部件(widget)的主要布局(即可实现自动布局)

"""###################################
(1)管理子部件
(2)将子部件给到主部件
(3)窗口显示主部件
###################################"""

layout = qvboxlayout()  				# 创建一个垂直布局管理器对象(用于管理垂直排列的子部件)
layout.addwidget(container_widget)  	# 将名为container_widget的部件添加到垂直布局中

central_widget = qwidget()  			# 创建一个qwidget对象(用作主窗口的中央部件)
central_widget.setlayout(layout)  		# 将布局设置为central_widget的布局管理器,使布局成为central_widget的主要布局
self.setcentralwidget(central_widget)  	# 将central_widget设置为主窗口(通常是qmainwindow)的中央部件,以便显示在窗口中

3.2、项目实战

3.2.0、添加伸缩项 layout.addstretch:控制部件之间的间距

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qhboxlayout, qpushbutton, qlabel, qwidget, qslider

class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        vbox_layout = qvboxlayout()
        hbox_layout = qhboxlayout()

        slider = qslider()
        slider.setfixedheight(500)
        label1 = qlabel("label 1")
        label2 = qlabel("label 2")
        label3 = qlabel("label 3")
        # (1)若在部件之前添加伸缩项,部件跟在伸缩项的后面,从而实现将部件布局到底部
        vbox_layout.addstretch(8)
        
        hbox_layout.addwidget(slider)
        vbox_layout.addwidget(label1)
        vbox_layout.addwidget(label2)
        vbox_layout.addwidget(label3)
        hbox_layout.addlayout(vbox_layout)
        
        vbox_layout.addstretch(1)
        # (2)若在部件之后添加伸缩项,部件被伸缩项顶在前面,从而实现将部件布局到顶部
        # (3)若在部件之前及之后分别添加伸缩项:将部件布局到中间

        central_widget = qwidget()
        central_widget.setlayout(hbox_layout)
        self.setcentralwidget(central_widget)

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

"""##########################################################################
函数简介:在布局中创建一个弹性空间,用于调整布局中各个部件的间距,以实现更好的分布和对齐效果。
函数说明:layout.addstretch()
输入参数:
        伸缩项的权重为0(默认),这意味着它不会占用任何额外的空间。
        伸缩项的权重为1(常用),将会根据权重在布局中占据一部分空间,从而将其他部件推向布局的边缘。
        备注:若为其余数字,则权重值越大,伸缩空间越大。
##########################################################################"""

3.2.1、垂直布局管理器 qvboxlayout:按照从上到下的顺序排列部件

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qwidget, qpushbutton

class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        vbox = qvboxlayout()
        button1 = qpushbutton("button 1")
        button2 = qpushbutton("button 2")
        button3 = qpushbutton("button 3")
        vbox.addwidget(button1)
        vbox.addwidget(button2)
        vbox.addwidget(button3)

        central_widget = qwidget()
        central_widget.setlayout(vbox)
        self.setcentralwidget(central_widget)

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

3.2.2、水平布局管理器 qhboxlayout:按照从左到右的顺序排列部件

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qwidget, qhboxlayout, qpushbutton

class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        hbox = qhboxlayout()
        button1 = qpushbutton("button 1")
        button2 = qpushbutton("button 2")
        button3 = qpushbutton("button 3")
        hbox.addwidget(button1)
        hbox.addwidget(button2)
        hbox.addwidget(button3)

        central_widget = qwidget()
        central_widget.setlayout(hbox)
        self.setcentralwidget(central_widget)

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

3.2.3、网格布局管理器 qgridlayout:指定每个部件的位置(行 + 列)

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qwidget, qgridlayout, qpushbutton

class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        grid_layout = qgridlayout()
        button1 = qpushbutton("button 1")
        button2 = qpushbutton("button 2")
        button3 = qpushbutton("button 3")
        button4 = qpushbutton("button 4")
        button5 = qpushbutton("button 5")
        grid_layout.addwidget(button1, 0, 0)        # 第一行第一列
        grid_layout.addwidget(button2, 0, 1)        # 第一行第二列
        grid_layout.addwidget(button3, 1, 0)        # 第二行第一列
        grid_layout.addwidget(button4, 1, 1)        # 第二行第二列
        grid_layout.addwidget(button5, 1, 2, 1, 2)  # 第二行的第三和第四列

        central_widget = qwidget()
        central_widget.setlayout(grid_layout)
        self.setcentralwidget(central_widget)

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

3.2.4、表单布局管理器 qformlayout:对齐标签和输入框

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qwidget, qformlayout, qlineedit, qlabel

class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        form_layout = qformlayout()
        label1 = qlabel("name:")
        name_input = qlineedit()
        label2 = qlabel("email:")
        email_input = qlineedit()
        label3 = qlabel("phone:")
        phone_input = qlineedit()
        form_layout.addrow(label1, name_input)
        form_layout.addrow(label2, email_input)
        form_layout.addrow(label3, phone_input)

        central_widget = qwidget()
        central_widget.setlayout(form_layout)
        self.setcentralwidget(central_widget)

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

3.2.5、堆叠布局管理器 qstackedlayout:在一个窗口中,管理多个窗口,但同一时刻只能显示一个窗口(如:选项卡界面)

在这里插入图片描述
在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qwidget, qpushbutton, qlabel, qvboxlayout, qstackedlayout

class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        self.setwindowtitle("stacked layout example")
        
        self.stacked_layout = qstackedlayout()
        page1 = self.create_page("page 1 content", "switch to page 2")
        page2 = self.create_page("page 2 content", "switch to page 1")
        self.stacked_layout.addwidget(page1)
        self.stacked_layout.addwidget(page2)

        central_widget = qwidget()
        central_widget.setlayout(self.stacked_layout)
        self.setcentralwidget(central_widget)

    def create_page(self, content_text, switch_button_text):
        layout = qvboxlayout()
        content_label = qlabel(content_text)
        switch_button = qpushbutton(switch_button_text)
        switch_button.clicked.connect(self.switch_page)
        layout.addwidget(content_label)
        layout.addwidget(switch_button)

        page = qwidget()
        page.setlayout(layout)
        return page

    def switch_page(self):
        # 切换页面
        current_index = self.stacked_layout.currentindex()
        next_index = (current_index + 1) % 2  # 切换到下一页(循环切换)
        self.stacked_layout.setcurrentindex(next_index)

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

四、pyqt 常用组件

在 gui 编程中,术语"组件"、"部件"和"控件"通常用于指代用户界面的基本构建块。术语在不同的 gui 框架和文档中会略有不同,但可以互换使用。

4.1、简介

pyqt提供了丰富的组件(也称为控件或部件),用于构建图形用户界面。

组件(widget)简介
窗口组件qwidget所有用户界面对象的基类,用于创建窗口和部件。
qmainwindow主窗口的类,通常用作应用程序的主界面。
基础组件qlabel显示文本或图像。
qlineedit输入单行文本。
qtextedit输入多行文本。
qspinbox(数字)整数输入框。
qdoublespinbox(数字)浮点数输入框。
qpushbutton按钮。
qradiobutton单选按钮。在多个选项中进行单选。
qcheckbox复选框。在多个选项中进行多选
qgroupbox分组框。将其他小部件放置在其中
qslider滑动条。
qtabwidget选项卡界面。
qcombobox下拉列表框。
对话框类 - 组件qdialog自定义对话框
qinputdialog获取用户输入对话框
qfontdialog字体对话框。
qcolordialog颜色对话框。
qprogressdialog进度对话框。
qfiledialog打开文件/文件夹对话框。
qmessagebox消息提示框。
菜单类 - 组件qmenu菜单。
qmenubar菜单栏。
qtoolbar工具栏。
qstatusbar状态栏。
qprogressbar进度条。
绘图类 - 组件qgraphicsscene管理2d图形项的场景。
qgraphicsview显示二维图形和图像。
qgraphicsitem在qgraphicsscene中显示图形项。
qtableview显示表格数据。
qtreewidget显示树形数据。
qlistwidget显示列表数据。
qcalendarwidget显示日历。
qdockwidget创建可停靠的面板。
qsplitter在界面中创建可调整大小的分割区域。
qscrollarea显示超过容器尺寸的内容,并支持滚动查看。

4.2、项目实战

【菜单类 - 组件】菜单+菜单栏+工具栏+状态栏 qmenubar + qmenu + qtoolbar + qstatusbar

qaction用于表示用户界面上的动作或操作。常与菜单、工具栏和快捷键等用户界面组件连用,以便用户可以执行各种操作。

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qmenu, qmenubar, qtoolbar, qstatusbar, qaction, qtextedit, qfiledialog

class mywindow(qmainwindow):
    def __init__(self):
        super().__init__()
        ###################################################
        # 创建菜单栏
        menubar = self.menubar()
        # 创建文件菜单
        file_menu = menubar.addmenu('file')
        # 创建文件菜单项
        new_action = qaction('new', self)
        open_action = qaction('open', self)
        save_action = qaction('save', self)
        exit_action = qaction('exit', self)
        # 添加文件菜单项到文件菜单
        file_menu.addaction(new_action)
        file_menu.addaction(open_action)
        file_menu.addaction(save_action)
        file_menu.addseparator()  # 分隔线
        file_menu.addaction(exit_action)
        # 连接菜单项和工具按钮的槽函数
        new_action.triggered.connect(self.newfile)
        open_action.triggered.connect(self.openfile)
        save_action.triggered.connect(self.savefile)
        exit_action.triggered.connect(self.exitapp)
        ###################################################
        # 创建工具栏
        toolbar = self.addtoolbar('toolbar')
        # 在工具栏中添加工具按钮
        new_button = toolbar.addaction('new')       # 清空(当前)文本编辑框
        open_button = toolbar.addaction('open')     # 打开txt文本并添加到文本编辑框
        save_button = toolbar.addaction('save')     # 保存文本编辑框到txt文本
        # 连接菜单项和工具按钮的槽函数
        new_button.triggered.connect(self.newfile)
        open_button.triggered.connect(self.openfile)
        save_button.triggered.connect(self.savefile)
        ###################################################
        # 创建状态栏
        statusbar = self.statusbar()
        # 在状态栏中显示消息: 'ready' 是要显示的文本消息,30000 是消息显示的时间(以毫秒为单位),即30秒。
        statusbar.showmessage('ready', 30000)
        ###################################################
        # 创建文本编辑框
        self.text_edit = qtextedit(self)
        self.setcentralwidget(self.text_edit)  # 将文本编辑框设置为主窗口的中心组件

    def newfile(self):
        self.text_edit.clear()  # 清空文本编辑框

    def openfile(self):
        try:
            # 打开文件对话框,选择txt文件并读取内容,然后显示在文本编辑框中
            file_dialog = qfiledialog(self)
            file_path, _ = file_dialog.getopenfilename()
            if file_path:
                with open(file_path, 'r', encoding='utf-8') as file:
                    file_contents = file.read()
                    self.text_edit.setplaintext(file_contents)
        except exception as e:
            # 处理异常,例如显示错误消息
            print(f"error opening file: {str(e)}")

    def savefile(self):
        try:
            # 保存文件对话框,将文本编辑框中的内容保存到txt文件中
            file_dialog = qfiledialog(self)
            file_path, _ = file_dialog.getsavefilename()
            if file_path:
                with open(file_path, 'w') as file:
                    file_contents = self.text_edit.toplaintext()
                    file.write(file_contents)
        except exception as e:
            # 处理异常,例如显示错误消息
            print(f"error saving file: {str(e)}")

    def exitapp(self):
        self.close()

if __name__ == '__main__':
    app = qapplication(sys.argv)
    window = mywindow()
    window.setwindowtitle('pyqt text editor')
    window.setgeometry(100, 100, 800, 300)
    window.show()
    sys.exit(app.exec_())

【对话框类 - 组件】输入对话框+颜色对话框+字体对话框+文件选择对话框+进度对话框+消息对话框:qinputdialog + qcolordialog + qfontdialog + qfiledialog + qprogressdialog + qmessagebox

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qwidget, qpushbutton, qlabel, qinputdialog, qcolordialog, qfontdialog, qfiledialog, qprogressdialog, qmessagebox
from pyqt5.qtcore import qt
from pyqt5.qtgui import qcolor


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        self.initui()

    def initui(self):
        self.setwindowtitle("dialogs example")
        self.setgeometry(100, 100, 400, 300)

        layout = qvboxlayout()

        # 显示输入对话框按钮
        input_btn = qpushbutton("input dialog")
        input_btn.clicked.connect(self.show_input_dialog)
        layout.addwidget(input_btn)

        # 颜色对话框按钮
        color_btn = qpushbutton("color dialog")
        color_btn.clicked.connect(self.show_color_dialog)
        layout.addwidget(color_btn)

        # 字体对话框按钮
        font_btn = qpushbutton("font dialog")
        font_btn.clicked.connect(self.show_font_dialog)
        layout.addwidget(font_btn)

        # 打开文件对话框按钮
        open_file_btn = qpushbutton("open file dialog")
        open_file_btn.clicked.connect(self.show_file_dialog)
        layout.addwidget(open_file_btn)

        # 进度对话框按钮
        progress_btn = qpushbutton("progress dialog")
        progress_btn.clicked.connect(self.show_progress_dialog)
        layout.addwidget(progress_btn)

        # 消息框按钮
        message_btn = qpushbutton("message box")
        message_btn.clicked.connect(self.show_message_box)
        layout.addwidget(message_btn)

        # 标签用于显示结果
        self.result_label = qlabel()
        layout.addwidget(self.result_label)

        central_widget = qwidget()
        central_widget.setlayout(layout)
        self.setcentralwidget(central_widget)

    def show_input_dialog(self):
        text, ok = qinputdialog.gettext(self, "input dialog", "enter something:")
        if ok and text:
            self.result_label.settext(f"input: {text}")
        else:
            self.result_label.settext("input dialog canceled")

    def show_color_dialog(self):
        color = qcolordialog.getcolor(qcolor(255, 0, 0), self, "color dialog")
        if color.isvalid():
            self.result_label.setstylesheet(f"background-color: {color.name()}")
            self.result_label.settext(f"selected color: {color.name()}")

    def show_font_dialog(self):
        font, ok = qfontdialog.getfont(self)
        if ok:
            self.result_label.setfont(font)
            self.result_label.settext(f"selected font: {font.family()}, {font.pointsize()}pt")

    def show_file_dialog(self):
        file_name, _ = qfiledialog.getopenfilename(self, "open file dialog", "", "all files (*);;text files (*.txt)")
        if file_name:
            self.result_label.settext(f"selected file: {file_name}")

    def show_progress_dialog(self):
        progress_dialog = qprogressdialog("processing...", "cancel", 0, 100, self)
        progress_dialog.setwindowmodality(qt.windowmodal)
        progress_dialog.setwindowtitle("progress dialog")

        for i in range(100):
            progress_dialog.setvalue(i)
            if progress_dialog.wascanceled():
                break

        self.result_label.settext("progress dialog completed")

    def show_message_box(self):
        msg_box = qmessagebox()
        msg_box.seticon(qmessagebox.information)
        msg_box.setwindowtitle("message box")
        msg_box.settext("this is an information message box.")
        msg_box.setstandardbuttons(qmessagebox.ok | qmessagebox.cancel)
        result = msg_box.exec_()

        if result == qmessagebox.ok:
            self.result_label.settext("message box: ok button clicked")
        else:
            self.result_label.settext("message box: cancel button clicked")


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

4.2.0、设置组件属性:尺寸 + 颜色 + 连接到槽(状态变化)

# 设置按钮尺度
button.setfixedsize(100, 35)  	# 设置组件的尺寸
button.setfixedwidth(35)		# 设置组件的宽度
button.setfixedheight(100)		# 设置组件的高度

# 设置按钮颜色(背景 + 字体) ———— 可以分别设置
button.setstylesheet("background-color: green; color: white;")

button.setchecked(true)  	# 设置默认选择
button.setenabled(true)		# 是否启用按钮
checkbox.ischecked()		# 判断按钮是否被选中

# (状态变化)信号连接到槽
self.checkbox.statechanged.connect(self.function)   # 将(复选框)信号连接到槽
self.slider.valuechanged.connect(self.function)     # 将(滑动条)信号连接到槽
self.lineedit.returnpressed.connect(self.function)  # 将(输入框)信号连接到槽
self.button.clicked.connect(self.function)  		# 将(按钮)信号连接到槽
self.text_edit.textchanged.connect(self.function)   # 将(输入框)信号连接到槽

4.2.1、显示文本 qlabel:hello, pyqt!

在这里插入图片描述

from pyqt5.qtwidgets import qapplication, qwidget, qlabel, qvboxlayout

class myapp(qwidget):
    def __init__(self):
        super().__init__()  # 调用父类的构造函数

        # 创建垂直布局管理器
        self.layout = qvboxlayout()
        # 创建标签对象并添加到布局中
        self.label = qlabel('hello, pyqt!')
        self.layout.addwidget(self.label)
        
        self.setlayout(self.layout)  # 设置布局到当前窗口
        self.show()  # 显示窗口

if __name__ == '__main__':
    import sys
    app = qapplication(sys.argv)  # 创建应用程序对象
    widget = myapp()               # 创建窗口对象
    sys.exit(app.exec_())          # 运行应用程序

4.2.2、按钮 qpushbutton:用户登录界面

在这里插入图片描述
在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qwidget, qlabel, qlineedit, qpushbutton, qvboxlayout, qhboxlayout


class loginwindow(qwidget):
    def __init__(self):
        super().__init__()
        self.setwindowtitle("login window")
        # 创建控件
        self.username_label = qlabel("username:")
        self.username_edit = qlineedit()

        self.password_label = qlabel("password:")
        self.password_edit = qlineedit()

        self.login_button = qpushbutton("login")
        self.login_button.clicked.connect(self.login)  # 连接按钮点击事件到槽函数
        self.result_label = qlabel("")

        # 将容器部件添加到主布局中
        layout = qvboxlayout()  # 垂直布局管理器

        self.username_layout = qhboxlayout()  # 水平布局管理器
        self.username_layout.addwidget(self.username_label)  # 将文本框添加到水平布局管理器中
        self.username_layout.addwidget(self.username_edit)  # 将按钮添加到水平布局管理器中
        layout.addlayout(self.username_layout)  # layout.addlayout

        self.password_layout = qhboxlayout()  # 水平布局管理器
        self.password_layout.addwidget(self.password_label)  # 将文本框添加到水平布局管理器中
        self.password_layout.addwidget(self.password_edit)  # 将按钮添加到水平布局管理器中
        layout.addlayout(self.password_layout)  # layout.addlayout

        # 将登录按钮和结果标签添加到垂直布局中
        layout.addwidget(self.login_button)  # layout.addwidget
        layout.addwidget(self.result_label)  # layout.addwidget

        # 设置窗口的主布局
        self.setlayout(layout)

    def login(self):
        username = self.username_edit.text()
        password = self.password_edit.text()

        # 在这里可以编写登录验证逻辑,这里只是简单地判断用户名和密码是否为空
        if username == 'you' and password == '66':
            self.result_label.settext("login successful!")
        else:
            self.result_label.settext("please check username and password.")


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

4.2.3、文本框 qlineedit + qtextedit(单行 + 多行) —— 文本改变

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qwidget, qlabel, qlineedit, qtextedit


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        layout = qvboxlayout()

        # qlineedit 示例
        self.line_edit = qlineedit(self)
        self.line_edit.setplaceholdertext("enter a number")
        self.line_edit.textchanged.connect(self.show_line_edit_text)

        # qtextedit 示例
        self.text_edit = qtextedit(self)
        self.text_edit.setplaceholdertext("enter a number")
        self.text_edit.textchanged.connect(self.show_text_edit_text)

        layout.addwidget(qlabel("single line input:"))
        layout.addwidget(self.line_edit)
        layout.addwidget(qlabel("multi-line text input:"))
        layout.addwidget(self.text_edit)

        central_widget = qwidget()
        central_widget.setlayout(layout)
        self.setcentralwidget(central_widget)

    def show_line_edit_text(self, text):
        print("line edit text:", text)

    def show_text_edit_text(self):
        text = self.text_edit.toplaintext()  # 获取 qtextedit 的文本
        print("text edit text:", text)


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

(1)输入框2将根据输入框1的值,自动计算;
(2)若输入框2的值自定义,则自动计算功能不启用。
在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qlineedit, qvboxlayout, qwidget


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        self.setwindowtitle("qlineedit 信号示例")

        self.line_edit_1 = qlineedit(self)
        self.line_edit_2 = qlineedit(self)

        self.is_programmatic_change = false
        self.line_edit_1.textchanged.connect(self.on_text_changed)
        self.line_edit_2.textchanged.connect(self.on_text_2_changed)

        layout = qvboxlayout()
        layout.addwidget(self.line_edit_1)
        layout.addwidget(self.line_edit_2)

        container = qwidget()
        container.setlayout(layout)
        self.setcentralwidget(container)

    def on_text_changed(self, text):
        try:
            value = int(text) + 1
            self.is_programmatic_change = true
            self.line_edit_2.settext(str(value))
            self.is_programmatic_change = false
        except valueerror:
            # 如果转换失败(例如输入的不是数字),则清空第二个文本框
            self.line_edit_2.clear()

    def on_text_2_changed(self, text):
        if self.is_programmatic_change:
            self.line_edit_2.setstylesheet("color: grey;")
            print(f"输入框的值变化是由程序设置的,状态为{self.is_programmatic_change}")
        else:
            self.line_edit_2.setstylesheet("color: black;")
            print(f"输入框的值变化是由用户手动输入的,状态为{self.is_programmatic_change}")


if __name__ == '__main__':
    app = qapplication(sys.argv)
    window = mainwindow()
    window.show()
    sys.exit(app.exec_())

4.2.4、校验器 qregexpvalidator :用于限制用户在 qlineedit 中输入的文本(英文 / 数字)

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qwidget, qlineedit
from pyqt5.qtcore import qregexp
from pyqt5.qtgui import qregexpvalidator


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        layout = qvboxlayout()

        self.line_edit = qlineedit(self)
        self.line_edit.setplaceholdertext("enter english and numbers only")

        # english_only = qregexp("[a-za-z]+")  # 创建一个正则表达式,用于匹配只包含英文字符的文本
        # numbers_only = qregexp("[0-9]+")  # 创建一个正则表达式,用于匹配只包含数字的文本
        regex = qregexp("[a-za-z0-9]+")  # 创建一个正则表达式,只允许输入英文和数字

        validator = qregexpvalidator(regex)
        self.line_edit.setvalidator(validator)

        layout.addwidget(self.line_edit)

        central_widget = qwidget()
        central_widget.setlayout(layout)
        self.setcentralwidget(central_widget)


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

"""##########################################################################
函数功能:qregexp 类是 qt 中用于处理正则表达式的类。
函数说明:qregexp(pattern: str, 
                casesensitivity: qt.casesensitivity = qt.casesensitive, 
                syntax: qregexp.patternsyntax = qregexp.regexp)
输入参数:
        pattern             构造一个 qregexp 对象,使用给定的正则表达式 pattern。
        casesensitivity     指定是否区分大小写,默认为区分大小写。
        syntax              指定正则表达式的语法,默认为正则表达式语法。
"""

"""
函数功能:qregexpvalidator 类是 qt 中用于输入验证的工具之一。它允许您使用正则表达式来限制用户在 qlineedit 等控件中输入的文本。
函数说明:qregexpvalidator(regexp: qregexp, 
                         parent: qobject = none)
输入参数:
        regexp              构造一个 qregexpvalidator 对象,使用给定的正则表达式 regexp 进行验证。
        parent              用于设置对象的父级。
##########################################################################"""

4.2.5、校验器 qintvalidator + qdoublevalidator(整数 + 浮点数):用于限制用户在 qlineedit 中输入的文本必须为数字。

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qhboxlayout, qwidget, qlabel, qlineedit
from pyqt5.qtgui import qintvalidator, qdoublevalidator


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        int_label = qlabel("enter an int between [0, 100]:")
        int_label.setfixedwidth(350)  # 设置固定的宽度
        int_validator = qintvalidator(0, 100)       # 创建qintvalidator,设置范围:[0, 100]
        int_lineedit = qlineedit()                  # 创建一个 qlineedit 控件
        int_lineedit.setvalidator(int_validator)    # 设置校验器
        # 将校验器应用到qlineedit控件中,用于限制用户只能输入 0 到 100 之间的整数。

        double_label = qlabel("enter an double between [0.0, 100.0]:")
        double_label.setfixedwidth(350)  # 设置固定的宽度
        double_validator = qdoublevalidator(0.0, 100.0, 2)       # 创建qdoublevalidator,设置范围:[0.0, 100.0],保留两位小数
        double_lineedit = qlineedit()                         # 创建一个 qlineedit 控件
        double_lineedit.setvalidator(double_validator)           # 设置校验器
        # 将校验器应用到qdoublevalidator控件中,用于限制用户只能输入 0.0 到 100.0 之间的浮点数。

        # 布局管理器
        v_layout = qvboxlayout()
        h1_layout = qhboxlayout()
        h2_layout = qhboxlayout()

        h1_layout.addwidget(int_label)
        h1_layout.addwidget(int_lineedit)
        h2_layout.addwidget(double_label)
        h2_layout.addwidget(double_lineedit)
        v_layout.addlayout(h1_layout)
        v_layout.addlayout(h2_layout)

        # 将布局应用于主窗口的中心区域
        central_widget = qwidget()
        central_widget.setlayout(v_layout)
        self.setcentralwidget(central_widget)


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

"""##########################################################################
from pyqt5.qtgui import qintvalidator

函数简介:在输入框中,限制用户输入的内容必须是符合一定范围的整数。
函数说明:qintvalidator(bottom, top, parent=none)
输入参数:
        bottom:         校验的最小值。
        top:            校验的最大值。
        parent:         可选,父对象。

属性:   bottom():               获取校验的最小值。
        top():                  获取校验的最大值。
方法:   setbottom(bottom):      设置校验的最小值。
        settop(top):            设置校验的最大值。
##########################################################################"""

"""##########################################################################
from pyqt5.qtgui import qdoublevalidator

函数简介:在输入框中,限制用户输入的内容必须是符合一定范围的整数。
函数说明:qdoublevalidator(bottom, top, decimals, parent=none)
输入参数:
        bottom:         浮点数的最小值,用户输入的浮点数不能小于该值。
        top:            浮点数的最大值,用户输入的浮点数不能大于该值。
        decimals:       小数位数,表示允许的小数点后的位数。
        parent:         可选参数,父级 qobject。

方法:   bottom():                       返回校验器设置的最小值。
        top():                          返回校验器设置的最大值。
        decimals():                     返回校验器设置的小数位数。
        setbottom(bottom: float):       设置校验器的最小值。
        settop(top: float):             设置校验器的最大值。
        setdecimals(decimals: int):     设置校验器的小数位数。
##########################################################################"""

4.2.6、输入框 qspinbox + qdoublespinbox(整数 + 浮点数):支持上下按钮调节

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qhboxlayout, qwidget, qspinbox, qdoublespinbox, qlabel


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        # 使用 qspinbox 限制整数范围
        qspinbox_label = qlabel("int input:")
        int_spinbox = qspinbox()
        int_spinbox.setrange(0, 100)  # 限制范围:[0, 100]

        # 使用 qdoublespinbox 限制浮点数范围
        qdoublespinbox_label = qlabel("double input:")
        double_spinbox = qdoublespinbox()
        double_spinbox.setrange(0.0, 100.0)  	# 限制范围:[0.0, 100.0]
        double_spinbox.setdecimals(2)  			# 保留2位小数

        # 布局管理器
        v_layout = qvboxlayout()  	# 垂直布局
        h1_layout = qhboxlayout()  	# 水平布局
        h2_layout = qhboxlayout()  	# 水平布局
        
        h1_layout.addwidget(qspinbox_label)
        h1_layout.addwidget(int_spinbox)
        v_layout.addlayout(h1_layout)
        h2_layout.addwidget(qdoublespinbox_label)
        h2_layout.addwidget(double_spinbox)
        v_layout.addlayout(h2_layout)

        # 将布局应用于主窗口的中心区域
        central_widget = qwidget()
        central_widget.setlayout(v_layout)
        self.setcentralwidget(central_widget)


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

4.2.7、滑动条 qslider:获取滑动条点击前后的值

在这里插入图片描述

from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qwidget, qslider, qlabel
from pyqt5.qtcore import qt


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        layout = qvboxlayout()

        self.slider = qslider()
        self.slider.setorientation(qt.horizontal)
        self.slider.setrange(0, 100)
        layout.addwidget(self.slider)

        self.label = qlabel("previous value: 0, current value: 0")
        layout.addwidget(self.label)

        self.previous_value = 0
        self.slider.valuechanged.connect(self.slider_value_changed)

        central_widget = qwidget()
        central_widget.setlayout(layout)
        self.setcentralwidget(central_widget)

    def slider_value_changed(self, new_value):
        self.label.settext(f"previous value: {self.previous_value}, current value: {new_value}")
        self.previous_value = self.slider.value()  
        # self.slider.value():获取的是点击slider之后的值,而不是当前slider显示的值


if __name__ == "__main__":
    app = qapplication([])
    window = mainwindow()
    window.show()
    app.exec_()

4.2.8、进度条 qprogressbar:创建一个进度条窗口(0~100%)

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qpushbutton, qprogressbar
from pyqt5.qtcore import qtimer

class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        
        # 设置窗口的几何属性
        self.setgeometry(100, 100, 600, 200)

        # 创建一个进度条并设置其几何属性
        self.progress_bar = qprogressbar(self)
        self.progress_bar.setgeometry(30, 40, 500, 25)

        # 创建一个 "start progress" 按钮
        start_button = qpushbutton('start progress', self)
        # 连接按钮的点击事件到 startprogress 函数
        start_button.clicked.connect(self.startprogress)
        # 设置按钮的固定宽度和位置
        start_button.setfixedwidth(200)
        start_button.move(30, 80)

    def startprogress(self):
        # 初始化进度为0
        self.progress = 0
        # 创建一个定时器
        self.timer = qtimer(self)
        # 连接定时器的超时事件到 updateprogress 函数
        self.timer.timeout.connect(self.updateprogress)
        # 每0.1秒触发一次定时器
        self.timer.start(100)

    def updateprogress(self):
        # 增加进度
        self.progress += 1
        # 设置进度条的值
        self.progress_bar.setvalue(self.progress)
        # 当进度达到100%时,停止定时器
        if self.progress >= 100:
            self.timer.stop()

if __name__ == '__main__':
    app = qapplication(sys.argv)
    window = mainwindow()
    window.show()
    sys.exit(app.exec_())

4.2.9、下拉框 qcombobox:创建一个下拉框并添加选项

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qwidget, qlabel, qcombobox


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        label = qlabel("select an option:")
        combo_box = qcombobox()
        combo_box.additem("option 1")
        combo_box.additem("option 2")
        combo_box.additem("option 3")
        combo_box.currentindexchanged.connect(self.selection_changed)  # 连接选项变更事件
        self.result_label = qlabel("", self)

        layout = qvboxlayout()
        layout.addwidget(combo_box)
        layout.addwidget(label)
        layout.addwidget(self.result_label)

        central_widget = qwidget()
        central_widget.setlayout(layout)
        self.setcentralwidget(central_widget)

    def selection_changed(self, index):
        selected_option = self.sender().currenttext()
        self.result_label.settext(f"selected: {selected_option}")


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

4.2.10、复选框 qcheckbox:获取勾选状态

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qlabel, qcheckbox, qvboxlayout, qwidget


class checkboxexample(qwidget):
    def __init__(self):
        super().__init__()

        self.initui()

    def initui(self):
        self.setwindowtitle('qcheckbox')

        self.label = qlabel("")
        self.checkbox = qcheckbox("option")

        layout = qvboxlayout()
        layout.addwidget(self.checkbox)
        layout.addwidget(self.label)

        self.setlayout(layout)
        self.checkbox.clicked.connect(self.on_checkbox_clicked)

    def on_checkbox_clicked(self):
        if self.checkbox.ischecked():
            self.label.settext("checkbox is checked")
        else:
            self.label.settext("checkbox is unchecked")


if __name__ == '__main__':
    app = qapplication(sys.argv)
    window = checkboxexample()
    window.show()
    sys.exit(app.exec_())

4.2.11、单选按钮 qradiobutton:获取勾选状态

在这里插入图片描述

import sys
from pyqt5.qtwidgets import qapplication, qlabel, qradiobutton, qvboxlayout, qwidget


class radiobuttonexample(qwidget):
    def __init__(self):
        super().__init__()

        self.initui()

    def initui(self):
        self.setwindowtitle('qradiobutton')

        # 创建标签
        self.label = qlabel("")

        # 创建单选按钮
        self.radiobutton1 = qradiobutton("option 1")
        self.radiobutton2 = qradiobutton("option 2")
        self.radiobutton3 = qradiobutton("option 3")

        # 将单选按钮和标签添加到布局
        layout = qvboxlayout()
        layout.addwidget(self.radiobutton1)
        layout.addwidget(self.radiobutton2)
        layout.addwidget(self.radiobutton3)
        layout.addwidget(self.label)

        # 将布局设置为窗口的主布局
        self.setlayout(layout)

        # 连接单选按钮的点击事件到槽函数
        self.radiobutton1.clicked.connect(self.on_radio_button_clicked)
        self.radiobutton2.clicked.connect(self.on_radio_button_clicked)
        self.radiobutton3.clicked.connect(self.on_radio_button_clicked)

    def on_radio_button_clicked(self):
        sender = self.sender()  # 获取点击的单选按钮
        self.label.settext("you selected: " + sender.text())  # 更新标签文本


if __name__ == '__main__':
    app = qapplication(sys.argv)
    window = radiobuttonexample()
    window.show()
    sys.exit(app.exec_())

4.2.12、分组框 qgroupbox:将其他小部件放置在其中

在这里插入图片描述

from pyqt5.qtwidgets import qapplication, qgroupbox, qhboxlayout, qradiobutton, qvboxlayout, qwidget

app = qapplication([])

widget = qwidget()

# 创建布局
main_layout = qvboxlayout()
group_box = qgroupbox("options")
group_box_layout = qvboxlayout()

# 创建组件
button1 = qradiobutton("option 1")
button2 = qradiobutton("option 2")
button3 = qradiobutton("option 3")
button4 = qradiobutton("option 4")

# 将组件添加到布局
layout1 = qhboxlayout()
layout1.addwidget(button1)
layout1.addwidget(button2)

layout2 = qhboxlayout()
layout2.addwidget(button3)
layout2.addwidget(button4)

group_box_layout.addlayout(layout1)
group_box_layout.addlayout(layout2)
group_box.setlayout(group_box_layout)

# 添加组件到主布局
main_layout.addwidget(group_box)
widget.setlayout(main_layout)
widget.show()

app.exec_()

4.2.12、打印日志 qtextedit:获取当前时间 + 设置文本颜色

在这里插入图片描述

from pyqt5.qtwidgets import qapplication, qtextedit, qvboxlayout, qpushbutton, qmainwindow, qwidget
from pyqt5.qtcore import qt, qdatetime

class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        self.log_text_edit = qtextedit()
        self.button = qpushbutton("print current time")
        self.button.clicked.connect(self.print_current_time)
        
        layout = qvboxlayout()
        layout.addwidget(self.log_text_edit)
        layout.addwidget(self.button)

        widget = qwidget()
        widget.setlayout(layout)
        self.setcentralwidget(widget)

    def print_current_time(self):
        current_time1 = qdatetime.currentdatetime().tostring(qt.defaultlocalelongdate)  # 指定默认格式
        current_time2 = qdatetime.currentdatetime().tostring("yyyy-m-d hh:mm:ss")  # 指定日期格式

        message = current_time1 + r'<font color="red"> + {}</font>'.format(current_time2)
        self.log_text_edit.append(message)

if __name__ == '__main__':
    app = qapplication([])
    window = mainwindow()
    window.show()
    app.exec()

from datetime import datetime

current_time = datetime.now()  # 获取当前时间
formatted_time = current_time.strftime("%y-%m-%d %h:%m:%s")
print("time:", formatted_time)  # 打印格式化后的时间
# time: 2023-08-08 14:25:29

4.2.13、消息提示框 qmessagebox:信息 / 询问 / 警告 / 错误

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qpushbutton, qvboxlayout, qwidget, qmessagebox


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        info_button = qpushbutton("information")
        question_button = qpushbutton("question")
        warning_button = qpushbutton("warning")
        critical_button = qpushbutton("critical")
        info_button.clicked.connect(self.show_information)
        question_button.clicked.connect(self.show_question)
        warning_button.clicked.connect(self.show_warning)
        critical_button.clicked.connect(self.show_critical)

        layout = qvboxlayout()
        layout.addwidget(info_button)
        layout.addwidget(question_button)
        layout.addwidget(warning_button)
        layout.addwidget(critical_button)

        widget = qwidget()
        widget.setlayout(layout)
        self.setcentralwidget(widget)

    def show_information(self):
        qmessagebox.information(self, "information", "this is an information message.", qmessagebox.ok, qmessagebox.ok)

    def show_question(self):
        result = qmessagebox.question(self, "question", "do you want to proceed?", qmessagebox.yes | qmessagebox.no, qmessagebox.no)
        if result == qmessagebox.yes:
            print("user clicked yes")
        else:
            print("user clicked no")

    def show_warning(self):
        qmessagebox.warning(self, "warning", "this is a warning message.", qmessagebox.ok, qmessagebox.ok)

    def show_critical(self):
        qmessagebox.critical(self, "critical", "this is a critical message.", qmessagebox.ok, qmessagebox.ok)


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

"""##########################################################################
from pyqt5.qtwidgets import qmessagebox

函数简介:用于显示消息框、询问框、警告框等用户交互提示框的类。
函数说明:
        信息消息框        qmessagebox.information(parent, title, message, buttons, defaultbutton)
        询问消息框        qmessagebox.question(parent, title, message, buttons, defaultbutton)
        警告消息框        qmessagebox.warning(parent, title, message, buttons, defaultbutton)
        严重错误消息框     qmessagebox.critical(parent, title, message, buttons, defaultbutton)
输入参数:
        parent:         可选参数,父级窗口。
        title:          消息框的标题。
        message:        消息框中显示的消息文本。
        buttons:        消息框中显示的按钮类型,如 qmessagebox.yes、qmessagebox.no 等。
        defaultbutton:  可选参数,指定默认按钮。
##########################################################################"""

在这里插入图片描述

def show_warning(message=none):
    import tkinter as tk
    from tkinter import messagebox

    root = tk.tk()
    root.withdraw()  # 隐藏主窗口
    messagebox.showwarning("warning", message)
    root.destroy()  # 关闭主窗口


if __name__ == '__main__':
    show_warning(message="请仔细检查")

4.2.14、选项卡界面 qtabwidget

 4.2.14.1、在一个窗口中显示多个页面

from pyqt5.qtwidgets import qapplication, qmainwindow, qtabwidget, qwidget, qvboxlayout, qlabel

class mywindow(qmainwindow):
    def __init__(self):
        super().__init__()

        # 创建tab控件
        self.tab_widget = qtabwidget()
        self.setcentralwidget(self.tab_widget)

        # 创建页面并添加到tab控件中
        self.page1 = qwidget()
        self.page2 = qwidget()
        self.tab_widget.addtab(self.page1, "page 1")
        self.tab_widget.addtab(self.page2, "page 2")

        # 设置页面的布局和内容
        layout1 = qvboxlayout()
        layout1.addwidget(qlabel("this is page 1"))
        self.page1.setlayout(layout1)

        layout2 = qvboxlayout()
        layout2.addwidget(qlabel("this is page 2"))
        self.page2.setlayout(layout2)


if __name__ == "__main__":
    app = qapplication([])
    window = mywindow()
    window.show()
    app.exec_()

 4.2.14.2、在主界面中,显示其他.py界面类文件

# main.py

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qtabwidget, qvboxlayout, qwidget, qpushbutton
from other_file import otherwindow  # 导入其他文件中的界面类

class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        self.setwindowtitle("main window")
        self.setgeometry(200, 200, 300, 200)

        # 创建一个qtabwidget控件
        self.tab_widget = qtabwidget(self)
        self.setcentralwidget(self.tab_widget)

        # 创建页面1和页面2
        self.page1 = qwidget()
        self.page2 = otherwindow()  # 调用其他文件中的界面类

        # 将页面1和页面2添加到qtabwidget控件中
        self.tab_widget.addtab(self.page1, "page 1")
        self.tab_widget.addtab(self.page2, "page 2")


if __name__ == "__main__":
    app = qapplication(sys.argv)
    main_window = mainwindow()
    main_window.show()
    sys.exit(app.exec_())

# other_file.py

import sys
from pyqt5.qtwidgets import qapplication, qwidget, qlabel, qvboxlayout, qhboxlayout, qpushbutton, qfiledialog


class otherwindow(qwidget):
    def __init__(self):
        super().__init__()

        self.button = qpushbutton("load:", self)
        self.button.clicked.connect(self.load_image)
        self.label = qlabel("")

        button_layout = qhboxlayout()
        button_layout.addwidget(self.button)
        button_layout.addwidget(self.label)

        layout = qvboxlayout()
        layout.addlayout(button_layout)  # 将button_layout布局添加到主布局中
        self.setlayout(layout)  # 设置窗口的主布局

    def load_image(self):
        self.folder_path = qfiledialog.getexistingdirectory(self, 'select folder', './')

        if self.folder_path:
            print('selected folder:', self.folder_path)
            self.label.settext(self.folder_path)


if __name__ == '__main__':
    app = qapplication(sys.argv)
    window = otherwindow()
    window.show()
    sys.exit(app.exec_())

 4.2.14.3、在主界面中,显示其他.py界面类文件,并进行数据交互

# main.py

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qtabwidget, qvboxlayout, qwidget, qlineedit, qpushbutton, qhboxlayout
from other_file import otherwindow


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()
        self.setwindowtitle("main window")
        self.setgeometry(200, 200, 300, 200)

        self.send_button = qpushbutton("send parameter", self)  # 新建按钮,并设置初始参数
        self.send_button.clicked.connect(self.send_parameter)  # 使用connect方法将信号连接到槽
        self.send_button.setstylesheet("background-color: black; color: white;")  # 设置按钮的背景和字体颜色
        self.input_line_edit = qlineedit("enter parameter", self)  # 新建文本框,并设置初始参数
        #####################################################################
        # 创建一个qtabwidget控件
        self.tab_widget = qtabwidget(self)
        self.setcentralwidget(self.tab_widget)

        # 创建页面1和页面2
        self.page1 = qwidget()
        self.other_window = otherwindow()  # 调用其他文件中的界面类

        # 将页面1和页面2添加到qtabwidget控件中
        self.tab_widget.addtab(self.page1, "page 1")
        self.tab_widget.addtab(self.other_window, "page 2")
        #####################################################################
        self.button_layout = qhboxlayout()
        self.button_layout.addwidget(self.send_button)
        self.button_layout.addwidget(self.input_line_edit)

        layout = qvboxlayout()
        layout.addlayout(self.button_layout)
        layout.addwidget(self.tab_widget)

        central_widget = qwidget()
        central_widget.setlayout(layout)
        self.setcentralwidget(central_widget)

    def send_parameter(self):
        parameter = self.input_line_edit.text()
        self.other_window.receive_parameter(parameter)  # 调用其他界面类other_window中的函数receive_parameter


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

# other_file.py

from pyqt5.qtwidgets import qapplication, qwidget, qvboxlayout, qhboxlayout, qpushbutton, qlabel
import sys

class otherwindow(qwidget):
    def __init__(self):
        super().__init__()

        button_layout = qhboxlayout()  # 水平布局管理器
        self.received_button = qpushbutton("received parameter", self)  # 新建按钮,并设置初始参数
        self.received_button.setstylesheet("background-color: black; color: white;")  # 设置按钮的背景和字体颜色
        self.label = qlabel("hello from other window!")

        button_layout.addwidget(self.received_button)
        button_layout.addwidget(self.label)

        layout = qvboxlayout()
        layout.addlayout(button_layout)
        self.setlayout(layout)

    def receive_parameter(self, parameter):
        self.label.settext(f"{parameter}")

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

4.2.15、调用其他.py文件,并数据交互

测试文件.py
# other_file.py

# 在这里进行运算或其他处理
result = 42
# 将结果打印到控制台
print(result)
print("result =", result + 1)
print("result" + " + " + "result")

方法一:subprocess(subprocess.run)
# main.py

import sys
import subprocess

from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qwidget, qpushbutton, qlabel


class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        self.run_button = qpushbutton("run .py")
        self.run_button.clicked.connect(self.run)
        self.run_label = qlabel("", self)

        layout = qvboxlayout()
        layout.addwidget(self.run_button)
        layout.addwidget(self.run_label)

        central_widget = qwidget()
        central_widget.setlayout(layout)
        self.setcentralwidget(central_widget)

    def run(self):
        try:
        	#########################################################
        	# 若不确定other_file.py是否调用成功,可以使用绝对路径。
            # 不建议:调用.py文件
            # 建议:将py文件封装成一个函数,然后调用函数。
        	#########################################################
            result = subprocess.run(["python", "other_file.py"], capture_output=true, text=true, check=true)
            output = result.stdout.strip()  # 获取输出结果并去除首尾空格
            self.run_label.settext(output)
        except subprocess.calledprocesserror as e:
            self.run_label.settext(str(e))


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

"""##########################################################################
import subprocess

函数简介:python标准库subprocess模块中的一个函数,用于运行一个子进程并等待其完成。
		 可以执行系统命令或其他可执行文件,并可以通过参数来控制进程的行为和交互。
函数说明:subprocess.run(args, *, stdin=none, input=none, stdout=none, 
		 				stderr=none, shell=false, cwd=none, timeout=none, 
		 				check=false, encoding=none, errors=none, text=none, 
		 				env=none, universal_newlines=none, start_new_session=false)
输入参数:
		args: 要运行的命令或可执行文件,以列表或字符串形式传递。如果shell=true,可以传递一个字符串,使用shell运行命令。
		stdin: 用于传递子进程的标准输入的文件对象。
		input: 用于传递子进程的标准输入的字节或字符串数据。
		stdout: 用于接收子进程的标准输出的文件对象。
		stderr: 用于接收子进程的标准错误输出的文件对象。
		shell: 是否在shell中运行命令。如果为true,可以使用通配符等shell特性。
		cwd: 子进程的当前工作目录。
		timeout: 等待子进程完成的超时时间,如果子进程在此时间内未完成,将会被终止。
		check: 是否检查返回代码。如果为true,如果子进程返回的代码非零,将会引发calledprocesserror异常。
		encoding: 用于解码子进程输出的编码。
		errors: 用于处理解码错误的策略。
		text: 是否使用文本模式传递数据,相当于同时设置universal_newlines和encoding。
		env: 用于指定子进程的环境变量。
		universal_newlines: 是否使用通用换行符模式,相当于同时设置stdin、stdout和stderr的text参数。
		start_new_session: 是否在新的会话(session)中启动子进程。
输出参数:
		返回一个completedprocess对象,它包含有关子进程执行的信息,如返回代码、标准输出、标准错误等。
##########################################################################"""
方法二:qprocess(process.start)
# main.py

import sys
from pyqt5.qtwidgets import qapplication, qmainwindow, qvboxlayout, qwidget, qpushbutton, qlabel
from pyqt5.qtcore import qprocess

class mainwindow(qmainwindow):
    def __init__(self):
        super().__init__()

        self.run_button = qpushbutton("run .py")
        self.run_button.clicked.connect(self.run)
        self.run_label = qlabel("", self)
        
        layout = qvboxlayout()
        layout.addwidget(self.run_button)
        layout.addwidget(self.run_label)

        central_widget = qwidget()
        central_widget.setlayout(layout)
        self.setcentralwidget(central_widget)

    def run(self):
        # 清空结果标签
        self.run_label.settext("")
        #########################################################
        # (1)启动进程执行外部脚本
        process = qprocess()
        python_script = r'other_file.py'  # 注意:若不确定other_file.py是否调用成功,可以使用绝对路径。
        para1 = str(9)  # (1)传递参数只能是字符串(2)与外部脚本完成交互。
        process.start("python", [python_script, para1])
        process.waitforfinished(-1)  # 用于等待进程执行完成。传入参数-1表示无限等待

        # (2)进程的退出代码:(1)0表示进程成功执行完成;(2)非零值表示出现错误。
        exit_code = process.exitcode()
        if exit_code == 0:
            self.run_label.settext("调用【成功】,退出代码:{}".format(exit_code))
        else:
            self.run_label.settext("调用【失败】,退出代码:{}".format(exit_code))

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

"""######################################################################################
# 函数介绍:qprocess 是 qt 框架中用于创建和管理外部进程的类。它允许你启动外部应用程序,并与其进行通信。
# 常见方法:
#       (1)启动外部进程:         使用start()方法启动一个外部进程
#       (2)与进程通信:           使用write()方法向进程的标准输入写入数据,并使用readallstandardoutput()和readallstandarderror()方法读取进程的标准输出和标准错误输出。
#       (2)等待进程执行完成:     使用waitforfinished()方法来等待进程执行完成
#       (3)获取进程退出代码:     使用exitcode()方法可以获取进程的退出代码
#       (4)支持信号与槽机制:     使用readyreadstandardoutput()信号在进程有标准输出可读时发出
#       (5)中断进程:            使用terminate()方法尝试终止进程的执行。不一定会立即停止进程,具体行为取决于操作系统和进程本身。
#
#               process = qprocess()
#               process.start("python", ["script.py", "arg1", "arg2"])
#               if process.waitforfinished():
#                   print("process finished")
#               exit_code = process.exitcode()
#               if exit_code == 0:
#                   print("调用成功")
#               else:
#                   print("调用失败,退出代码:", exit_code)
#
#               process.write(b"input data")
#               output = process.readallstandardoutput()
#               error_output = process.readallstandarderror()
#               process.readyreadstandardoutput.connect(handle_output)
#               process.terminate()
######################################################################################"""

"""######################################################################################
# 函数介绍:waitforfinished 是 qprocess 类的一个成员函数。用于阻塞当前线程,直到关联的进程完成执行为止。
# 函数说明:bool qprocess.waitforfinished(int msecs = 30000)
# 输入参数:     msecs:等待的时间(以毫秒为单位)。默认值是 30000 毫秒(30 秒)。如果设置为 -1,表示无限等待。
# 输出参数:     如果进程在给定的时间内完成执行,则返回 true,否则返回 false。
# 
# (1)主要用于等待 qprocess 执行外部程序的过程完成。程序会阻塞当前线程,阻塞在当前行,直到被调用的进程执行完毕。
# (2)如果进程执行的时间很长,这会导致界面冻结,因为界面线程会被阻塞。
# (3)如果你需要在界面上显示进度或状态,或者想要允许用户继续操作界面,而不阻塞界面线程,可以考虑使用多线程、异步编程等技术,以避免界面的冻结。
######################################################################################"""

4.2.16、在当前虚拟环境下,调用其他虚拟环境下的.py文件,并数据交互

import subprocess
import os

virtual_env_name = "tensorflow36"                               # (1)指定要激活的虚拟环境名称
cmd_activate_env = f"conda activate {virtual_env_name}"         # (2)构建激活虚拟环境的命令

script_path = r"deeplearning.py"                                # (3)指定.py文件路径
path = os.getcwd() + 'image.tif'                                # (4)指定.py文件参数
cmd_script_file = f"python {script_path} --image_path {path}"   # (5)构建调用.py文件的命令,包括传递参数

# (6)使用subprocess执行命令
###################################################################################
# 在windows上,通过subprocess.run来激活一个conda环境并不是一种有效的方式。
#       原因分析:因为conda activate命令会在一个新的子进程中执行,该子进程的环境变量变化不会影响到当前python进程中运行的后续代码。
#       解决方法:将激活环境和执行py文件的命令,同时传递给subprocess.run。
###################################################################################
combined_cmd = f"{cmd_activate_env} && {cmd_script_file}"       # 组合两个命令并在子进程中执行
try:
    subprocess.run(combined_cmd, shell=true, check=true)
except subprocess.calledprocesserror as e:
    print(f"error: {e}")

"""######################################################################
import argparse                             # 导入argparse模块

if __name__ == "__main__":
    parser = argparse.argumentparser()      # 创建解析对象
    parser.add_argument('--image_path')     # 添加命令行参数和选项
    args = parser.parse_args()              # 解析添加的参数
    image_path = args.image_path            # 获取添加的参数
######################################################################"""
(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com