python使用Qt实现GUI编程

本文详细介绍了如何使用Python和PyQt5进行GUI编程,包括窗口创建、信号与槽机制、工具栏菜单设计、窗口部件、布局(垂直、水平和网格)以及对话框的实现。通过实例演示了Qt在开发跨平台应用中的关键要素。
摘要由CSDN通过智能技术生成

python使用Qt实现GUI编程


基于 Python 3 和 PyQt 5 来认识 GUI 编程

知识点

以下知识点:

  • 使用 Qt 创建窗口
  • Qt 的信号与槽机制
  • Qt 各个组件的使用

流程

流程如下:

  • Qt 安装
  • 创建窗口
  • 信号与槽
  • 工具栏与菜单
  • 窗口部件
  • 布局
  • 对话框

过程

Qt 安装

Qt 是一个跨平台的 C++ 应用程序开发框架。广泛用于开发 GUI 程序,这种情况下又被称为部件工具箱。也可用于开发非 GUI 程序,比如控制台工具和服务器

pip安装

使用支持的Python版本

pip install PyQt5

创建窗口

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *

import sys

class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 设置窗口标题
        self.setWindowTitle('My First App')

        # 设置标签
        label = QLabel('Welcome to Shiyanlou!')
        # 设置标签显示在中央
        label.setAlignment(Qt.AlignCenter)
        self.setCentralWidget(label)

# 创建应用实例,通过 sys.argv 传入命令行参数
app = QApplication(sys.argv)
# 创建窗口实例
window = MainWindow()
# 显示窗口
window.show()
# 执行应用,进入事件循环
app.exec_()

此处输入图片的描述

这里需要说明的是 Qt 的执行机制。 Qt 的程序通过创建 QApplication 类实例来调用 app.exec_ 方法进入事件循环。此时程序一直在循环监听各种事件并把它们放入消息队列中,在适当的时候从队列中取出处理。

2.3 信号与槽

Qt 中每种组件都有所谓的信号槽(slot)机制。可用来将信号与相应的处理函数进行连接绑定。

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *

import sys

class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 设置窗口标题
        self.setWindowTitle('My First App')

        # 设置标签
        label = QLabel('Welcome to Shiyanlou!')
        # 设置标签显示在中央
        label.setAlignment(Qt.AlignCenter)
        self.setCentralWidget(label)

    def _my_func(self, s='my_func', a=100):
        dic = {'s': s, 'a': a}
        print(dic)

# 创建应用实例,通过 sys.argv 传入命令行参数
app = QApplication(sys.argv)
# 创建窗口实例
window = MainWindow()
# 显示窗口
window.show()
# 执行应用,进入事件循环
app.exec_()

以上主要只给出了部分新添加的代码,原有的代码统一使用 ... 略过。

这里将 QMainWindow 的信号 windowTitleChanged_my_func 槽函数相绑定,当窗口标题被更改的信号发出的时候便会触发函数 _my_func 进行处理。

其中在自定义函数 _my_func 中允许设置任意多个参数。

运行上方程序。

此处输入图片的描述

根据打印出来的字典键值可以发现 windowTitleChanged 信号在被触发的时候向处理函数 _my_func 传递了一个参数也就是窗口标题。当然也有办法忽略这个值,就是采用 lamda 产生式。其原理就是通过 lamda 产生式的参数 x 捕获标题字符串,然后将 x 废弃不用,从而避免标题传入 _my_func

修改如下:

...
self.windowTitleChanged.connect(lambda x: self._my_func('Shiyanlou', 666))
...

运行结果。

此处输入图片的描述

为了更加直观地理解信号与槽,我们进一步修改代码,通过创建按钮响应按钮事件来展示信号与槽机制。

...
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 设置窗口标题
        self.setWindowTitle('My First App')

        # 添加布局
        layout = QHBoxLayout()

        # 创建按钮
        for i in range(5):
            button = QPushButton(str(i))
            # 将按钮按压信号与自定义函数关联
            button.pressed.connect(lambda x=i: self._my_func(x))
            # 将按钮添加到布局中
            layout.addWidget(button)

        # 创建部件
        widget = QWidget()
        # 将布局添加到部件
        widget.setLayout(layout)
        # 将部件添加到主窗口上
        self.setCentralWidget(widget)

    # 自定义的信号处理函数
    def _my_func(self, n):
        print('click button %s' % n)
...

此处输入图片的描述

另外 Qt 还支持自定义信号,可以通过创建 pyqtSignal 对象实例来定义信号对象。

...
class MainWindow(QMainWindow):
    # 自定义信号
    my_signal = pyqtSignal(str)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 设置窗口标题
        self.setWindowTitle('My First App')

        button = QPushButton('Click me!')
        button.pressed.connect(self._click_button)
        # 将自定义信号与相应的槽函数连接
        self.my_signal.connect(self._my_func)
        # 将部件添加到主窗口上
        self.setCentralWidget(button)

    # 自定义的信号处理函数
    def _click_button(self):
        # 当按钮被点击的时候将发出信号 my_signal
        self.my_signal.emit('shiyanlou')

    def _my_func(self, s):
        print(s)
...

以上过程实际上就是将按钮按压信号与 _click_button 槽关联,而一旦调用了 _click_button 函数之后又会触发 my_signal 信号,继而调用 my_signal 信号的槽进行处理。

上述调用过程实际上没有任何意义,仅仅只是为了展示 Qt 具备有自定义信号的功能。

此处输入图片的描述

2.4 工具栏与菜单

通常我们使用的软件窗口顶部还会有一条工具栏或者菜单栏。

可以使用 Qt 提供的 QToolBar 创建工具栏。

...
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 设置窗口标题
        self.setWindowTitle('My First App')

        # 设置标签
        label = QLabel('Welcome to Shiyanlou!')
        # 设置标签显示在中央
        label.setAlignment(Qt.AlignCenter)
        # 添加标签到主窗口
        self.setCentralWidget(label)

        # 创建工具栏
        tb = QToolBar('Tool Bar')
        # 添加工具栏到主窗口
        self.addToolBar(tb)
...

由于我们尚未给工具栏添加任何实际功能,所以工具栏只能看到一条空白的横杆。

此处输入图片的描述

接下来我们为工具栏添加实体按钮,并在窗口底部显示提示信息

下面是图标下载地址:

https://labfile.oss.aliyuncs.com/courses/705/icons.zip
...
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 设置窗口标题
        self.setWindowTitle('My First App')

        # 设置标签
        label = QLabel('Welcome to Shiyanlou!')
        # 设置标签显示在中央
        label.setAlignment(Qt.AlignCenter)
        # 添加标签到主窗口
        self.setCentralWidget(label)

        # 创建工具栏
        tb = QToolBar('Tool Bar')
        # 设置工具栏中按钮的大小
        tb.setIconSize(QSize(16, 16))
        # 添加工具栏到主窗口
        self.addToolBar(tb)

        # 添加按钮动作,并加载图标图像
        button_action = QAction(QIcon('icons/penguin.png'), 'Menu button', self)
        # 设置状态栏提示
        button_action.setStatusTip('This is menu button')
        button_action.triggered.connect(self.onButtonClick)
        button_action.setCheckable(True)
        # 添加到工具栏
        tb.addAction(button_action)
        # 为主窗口设置状态栏
        self.setStatusBar(QStatusBar(self))

    def onButtonClick(self, s):
        print(s)
...

此处输入图片的描述

接下来为应用添加菜单栏。

...
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        ...

        # 添加菜单栏
        mb = self.menuBar()
        # 禁用原生的菜单栏
        mb.setNativeMenuBar(False)
        # 添加 “文件” 菜单
        file_menu = mb.addMenu('&File')
        # 为文件菜单添加动作
        file_menu.addAction(button_action)
...

此处输入图片的描述

当然我们还可以实现二级菜单。

...
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        ...

        # 添加新的菜单选项
        button_action2 = QAction('C++', self)
        button_action3 = QAction('Python', self)
        button_action2.setCheckable(True)
        button_action3.setCheckable(True)
        button_action2.triggered.connect(self.onButtonClick)
        button_action3.triggered.connect(self.onButtonClick)

        # 添加菜单栏
        mb = self.menuBar()
        # 禁用原生的菜单栏
        mb.setNativeMenuBar(False)
        # 添加 “文件” 菜单
        file_menu = mb.addMenu('&File')
        # 为文件菜单添加动作
        file_menu.addAction(button_action)
        # 为菜单选项添加分隔符
        file_menu.addSeparator()

        # 添加二级菜单
        build_system_menu = file_menu.addMenu('&Build System')
        build_system_menu.addAction(button_action2)
        build_system_menu.addSeparator()
        build_system_menu.addAction(button_action3)
...

此处输入图片的描述

2.5 窗口部件

Qt 还有一个强大的部件类 QWidgets ,基于这个类派生出很多其它小部件,比如 DialSliderCheckBox 等等。由于部件太多了,这里只是简单做一统一展示,如果有需要深入学习某一部件再参考 官方文档

...
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 设置窗口标题
        self.setWindowTitle('My First App')

        # 定义布局
        layout = QVBoxLayout()

        # 展示的部件列表
        widgets = [QCheckBox,
                QComboBox,
                QDateEdit,
                QDateTimeEdit,
                QDial,
                QDoubleSpinBox,
                QFontComboBox,
                QLCDNumber,
                QLineEdit,
                QProgressBar,
                QPushButton,
                QRadioButton,
                QSlider,
                QSpinBox,
                QTimeEdit]

        # 将部件添加到列表中
        for item in widgets:
            layout.addWidget(item())

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
...

此处输入图片的描述

2.6 布局

Qt 支持多种控件布局方式,主要有:

  • 垂直布局
  • 水平布局
  • 网格布局

当然这些布局方式之间也都支持混合嵌套使用。

2.6.1 垂直布局

为了更加直观的看到布局效果,我们这里定义了一个新类 Color 继承自 QWidget 用于显示色块。

...
# 用于显示色块
class Color(QWidget):
    def __init__(self, color, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setAutoFillBackground(True)

        palette = self.palette()
        palette.setColor(QPalette.Window, QColor(color))
        self.setPalette(palette)

class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 设置窗口标题
        self.setWindowTitle('My First App')

        colors = ['red', 'green', 'blue', 'yellow']
        # 水平布局
        layout = QVBoxLayout()

        for color in colors:
            layout.addWidget(Color(color))

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
...

此处输入图片的描述

2.6.2 水平布局

知道了垂直布局之后,水平布局也相当简单,就是将 QVBoxLayout 修改为 QHBoxLayout

此处输入图片的描述

2.6.3 网格布局
...
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 设置窗口标题
        self.setWindowTitle('My First App')

        colors = ['red', 'green', 'blue', 'yellow']
        # 网格布局
        layout = QGridLayout()

        for i, color in enumerate(colors):
            for j in range(len(colors)):
                layout.addWidget(Color(color), i, j)

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
...

此处输入图片的描述

2.7 对话框

...
# 自定义对话框
class CustomDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setWindowTitle('New Dialog')
        # 添加按钮选项
        QBtn = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
        buttonBox = QDialogButtonBox(QBtn)
        buttonBox.accepted.connect(self.accept)
        buttonBox.rejected.connect(self.reject)

        layout = QVBoxLayout()
        layout.addWidget(buttonBox)
        self.setLayout(layout)

class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # 设置窗口标题
        self.setWindowTitle('My First App')

        # 设置标签
        label = QLabel('Welcome to Shiyanlou!')
        # 设置标签显示在中央
        label.setAlignment(Qt.AlignCenter)
        # 添加标签到主窗口
        self.setCentralWidget(label)

        # 添加按钮动作,并加载图标图像
        button_action = QAction('New dialog', self)
        button_action.triggered.connect(self.onButtonClick)

        # 添加菜单栏
        mb = self.menuBar()
        # 禁用原生的菜单栏
        mb.setNativeMenuBar(False)
        # 添加 “文件” 菜单
        file_menu = mb.addMenu('&File')
        # 为文件菜单添加动作
        file_menu.addAction(button_action)


    def onButtonClick(self, s):
        # 创建对话框
        dlg = CustomDialog(self)
        # 运行对话框,这一步非常重要!!!
        dlg.exec_()
...

此处输入图片的描述

上面我们大概了解了使用 Qt 进行 GUI 编程的流程,也粗略接触了 Qt 各个控件,但是这个要作为 Qt 入门还远远不够,因为 Qt 内容实在太多了,要继续深入学习

### 回答1: 为了开发一个qt与linux终端交互程序,我们需要安装并配置必要的开发工具。以下是一个基本的步骤指南: 步骤1:安装Qt 首先,我们需要在Linux上安装Qt,它是一个跨平台的GUI框架。打开终端,执行以下命令来安装Qt: ``` sudo apt-get update sudo apt-get install qt5-default ``` 步骤2:创建Qt项目 打开Qt Creator,创建一个新的Qt控制台应用程序项目。我们可以选择使用C++或其他支持的语言。在创建项目时,我们需要指定项目名称和路径。 步骤3:添加一个终端控件 在Qt Creator的设计视图中,添加一个QPlainTextEdit控件,用于显示终端输出。将其重命名为consoleTextEdit,并将其扩展到填满窗口。 步骤4:连接终端 我们需要使用QProcess类来连接到终端。在main.cpp文件中,我们可以编写以下代码: ```c++ #include <QCoreApplication> #include <QDebug> #include <QProcess> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QProcess process; process.start("bash"); if(process.waitForStarted()) { qDebug() << "Connected to terminal"; process.write("ls\n"); process.waitForReadyRead(); QByteArray output = process.readAllStandardOutput(); qDebug() << output; } else { qDebug() << "Failed to connect to terminal"; } return a.exec(); } ``` 这个程序将连接到bash终端,并发送一个“ls”命令。当终端输出结果时,它将被读取并在控制台中显示。 步骤5:将输出显示在控件中 我们可以将终端输出显示在之前添加的QPlainTextEdit控件中。我们可以在main.cpp文件中编写以下代码: ```c++ #include <QCoreApplication> #include <QDebug> #include <QProcess> #include <QPlainTextEdit> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QProcess process; process.start("bash"); QPlainTextEdit consoleTextEdit; consoleTextEdit.show(); if(process.waitForStarted()) { qDebug() << "Connected to terminal"; process.write("ls\n"); process.waitForReadyRead(); QByteArray output = process.readAllStandardOutput(); consoleTextEdit.setPlainText(output); } else { qDebug() << "Failed to connect to terminal"; } return a.exec(); } ``` 这个程序将连接到bash终端,并在QPlainTextEdit控件中显示输出结果。 步骤6:添加一个输入框 为了让用户能够输入命令,我们需要添加一个QLineEdit控件。在设计视图中,将其添加到窗口底部,并将其重命名为inputLineEdit。 步骤7:连接输入框 我们需要在用户按下“回车”键时发送命令。我们可以在main.cpp文件中编写以下代码: ```c++ #include <QCoreApplication> #include <QDebug> #include <QProcess> #include <QPlainTextEdit ### 回答2: 开发一个与Linux终端交互的Qt程序可分为以下步骤: 1. 准备开发环境:首先确保已经安装好Qt开发环境和Linux操作系统。然后在Qt Creator中创建一个新的Qt Widget项目。 2. 设计用户界面:使用Qt Designer在程序中设计一个用户界面,可以添加输入框、按钮和文本框等控件,用于用户输入命令和显示终端输出结果。 3. 添加信号与槽函数:为按钮控件添加信号与槽函数,用于捕捉用户点击按钮的事件,并执行终端命令。 4. 编写终端交互代码:编写代码,通过调用Linux终端命令行程序来执行用户输入的命令,并获取终端的输出结果。 5. 运行程序:在Qt Creator中点击运行按钮,编译并运行程序。此时会出现一个带有用户界面的对话框。在输入框中输入要执行的Linux终端命令,然后点击按钮执行。 6. 显示输出结果:在槽函数中,将终端命令的输出结果展示在程序的文本框中,用户可以看到终端命令的执行结果。 通过以上步骤,可以开发一个Qt与Linux终端交互的程序。这个程序可以通过用户界面接收和执行Linux终端命令,并将执行结果反馈给用户。在实际应用中,可以进一步完善程序,如添加输入验证、错误处理等功能,以提高交互体验和程序的稳定性。 ### 回答3: 要开发一个Qt与Linux终端交互程序,可以参照以下步骤: 1. 首先,在Linux系统上安装Qt开发环境,可以通过在终端中运行以下命令来完成安装: ``` sudo apt-get install qt5-default ``` 2. 创建一个新的Qt项目。在Qt Creator中,选择“新建项目”,选择“Qt Widgets应用程序”,然后点击“选择”,输入项目名称并选择保存路径。接下来,选择一个基于Qt Widgets的桌面项目模板。 3. 在Qt Creator中,创建一个主窗口。可以使用拖放方式将控件放置在主窗口上,并设置控件的属性和信号槽连接。 4. 在Qt中与Linux终端进行交互,需要使用Qt的QProcess类。在主窗口的槽函数中,使用QProcess执行命令,并通过读取其输出来获取终端的返回结果。 5. 在函数中,创建一个QProcess对象,并使用start()方法来执行终端命令。例如: ``` QProcess process; process.start("ls -l"); ``` 6. 在交互过程中,可以通过process.readAll()来读取终端的输出结果,并将结果显示在主窗口的文本区域中。 7. 为了使用户能够输入命令并与终端进行交互,可以添加一个输入框和一个“执行”按钮。在按钮的槽函数中获取输入框中的命令,并使用QProcess执行该命令。 8. 运行程序,可以在Qt Creator中点击“运行”按钮。这将先编译程序,然后运行生成的可执行文件。 通过以上步骤,可以开发一个基于Qt的与Linux终端交互的应用程序。可以根据需要进一步完善UI界面和功能,例如支持命令参数输入、错误处理等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Deng872347348

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

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

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

打赏作者

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

抵扣说明:

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

余额充值