首页 > 其他分享 >PySide6: 花销工具教程

PySide6: 花销工具教程

时间:2022-11-25 18:37:49浏览次数:69  
标签:__ 教程 right 花销 self PySide6 table data price

在本教程中,您将学习以下概念:

  • 以编程方式创建用户界面,
  • 布局和小部件,
  • 过载Qt类,
  • 连接信号和时隙,
  • 与QWidget交互,
  • 以及构建自己的应用程序。

要求:

  • 应用程序的简单窗口(QMainWindow)。
  • 跟踪花销的表(QTableWidget)。
  • 用于添加花销信息的两个输入字段(QLineEdit)。
  • 用于向表格添加信息、打印数据、清除表格和退出应用程序的按钮(QPushButton)。
  • 避免无效数据输入的验证步骤。
  • 用于可视化将嵌入图表视图(QChartView)中的花销数据(QChart)的图表。
空窗口

QApplication的基本结构位于if__name__==“main”:代码块内。

if __name__ == "__main__":
app = QApplication([])
# ...
sys.exit(app.exec())

现在,要开始开发,请创建一个名为MainWindow的空窗口。您可以通过定义从QMainWindow继承的类来实现这一点。

class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle("Tutorial")

if __name__ == "__main__":
# Qt Application
app = QApplication(sys.argv)

window = MainWindow()
window.resize(800, 600)
window.show()

# Execute application
sys.exit(app.exec())

现在我们的类已经定义,创建它的一个实例并调用show()。

class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle("Tutorial")

if __name__ == "__main__":
# Qt Application
app = QApplication(sys.argv)

window = MainWindow()
window.resize(800, 600)
window.show()

# Execute application
sys.exit(app.exec())

菜单栏

使用QMainWindow可以免费提供一些功能,其中包括菜单栏。要使用它,需要调用方法menuBar()并将其填充到MainWindow类中。

class MainWindow(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle("Tutorial")

# Menu
self.menu = self.menuBar()
self.file_menu = self.menu.addMenu("File")

# Exit QAction
exit_action = QAction("Exit", self)
exit_action.setShortcut("Ctrl+Q")

请注意,代码段添加了一个仅带有Exit选项的File菜单。

第一个信号/插槽连接

退出选项必须连接到触发应用程序退出的插槽。实现这一目标的主要思路如下:

element.signal_name.connect(slot_name)

所有接口元件都可以通过信号连接到某些插槽,在QAction的情况下,可以使用触发的信号:

exit_action.triggered.connect(slot_name)

注意: 现在需要定义一个槽来退出应用程序,这可以使用QApplication.quit()来完成。如果我们将所有这些概念放在一起,您将得到以下代码:

        # Exit QAction
exit_action = QAction("Exit", self)
exit_action.setShortcut("Ctrl+Q")
exit_action.triggered.connect(self.exit_app)
self.file_menu.addAction(exit_action)

@Slot()
def exit_app(self, checked):
QApplication.quit()

请注意,您声明的每个槽都需要decorator@Slot()来正确注册它们。插槽是正常的功能,但主要区别在于,当连接时,可以从QObjects的Signals调用它们。

空widget和数据

QMainWindow使我们能够设置显示窗口时将显示的中央控件(​​阅读更多信息​​)。这个中心小部件可以是从QWidget派生的另一个类。

此外,您将定义示例数据,以便稍后可视化。

class Widget(QWidget):
def __init__(self):
QWidget.__init__(self)

# Example data
self._data = {"Water": 24.5, "Electricity": 55.1, "Rent": 850.0,
"Supermarket": 230.4, "Internet": 29.99, "Bars": 21.85,}

在Widget类就位后,修改MainWindow的初始化代码

    # Qt Application
app = QApplication(sys.argv)
# QWidget
widget = Widget()
# QMainWindow using QWidget as central widget

窗口布局

现在主空窗口已经就位,您需要开始添加小部件以实现创建费用应用程序的主要目标。

在声明示例数据之后,您可以在一个简单的QTableWidget上可视化它。为此,您将把这个过程添加到Widget构造函数中。

警告

仅出于示例目的,将使用QTableWidget,但对于性能更关键的应用程序,鼓励将模型和QTableView结合使用。

class Widget(QWidget):
def __init__(self):
QWidget.__init__(self)
self.items = 0

# Example data
self._data = {"Water": 24.5, "Electricity": 55.1, "Rent": 850.0,
"Supermarket": 230.4, "Internet": 29.99, "Bars": 21.85,
"Public transportation": 60.0, "Coffee": 22.45, "Restaurants": 120}

# Left
self.table = QTableWidget()
self.table.setColumnCount(2)
self.table.setHorizontalHeaderLabels(["Description", "Price"])
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

# QWidget Layout
self.layout = QHBoxLayout()

#self.table_view.setSizePolicy(size)
self.layout.addWidget(self.table)

# Set the layout to the QWidget
self.setLayout(self.layout)

# Fill example data

正如您所看到的,代码还包括一个QHBoxLayout,它提供了一个容器来水平放置小部件。

此外,QTableWidget允许对其进行自定义,比如为将要使用的两列添加标签,以及扩展内容以使用整个Widget空间。

最后一行代码表示填充表*,执行该任务的代码如下所示。

    def fill_table(self, data=None):
data = self._data if not data else data
for desc, price in data.items():
self.table.insertRow(self.items)
self.table.setItem(self.items, 0, QTableWidgetItem(desc))
self.table.setItem(self.items, 1, QTableWidgetItem(str(price)))

将这个过程放在一个单独的方法上是一个很好的做法,可以让构造函数更可读,并将类的主要函数拆分为独立的过程。

右侧布局

因为正在使用的数据只是一个示例,所以您需要包括一个向表中输入项目的机制,以及用于清除表内容的额外按钮,还需要退出应用程序。

要分配这些输入行和按钮,您将使用QVBoxLayout,该布局允许您在布局内垂直放置元素。

        # Right
self.description = QLineEdit()
self.price = QLineEdit()
self.add = QPushButton("Add")
self.clear = QPushButton("Clear")
self.quit = QPushButton("Quit")

self.right = QVBoxLayout()
self.right.addWidget(QLabel("Description"))
self.right.addWidget(self.description)
self.right.addWidget(QLabel("Price"))
self.right.addWidget(self.price)
self.right.addWidget(self.add)
self.right.addStretch()
self.right.addWidget(self.clear)
self.right.addWidget(self.quit)

将表放在左侧,将这些新包含的小部件放在右侧,只需向我们的主QHBoxLayout添加一个布局即可,如前一个示例所示:

from PySide6.QtCore import Slot
from PySide6.QtGui import QAction
from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout, QLabel, QLineEdit,
QMainWindow, QPushButton, QTableWidget, QTableWidgetItem,
QVBoxLayout, QWidget)

下一步是将这些新按钮连接到插槽。

添加元素

每个QPushButton都有一个名为clicked的信号,当您单击按钮时会发出该信号。对于这个示例来说,这已经足够了,但是您可以在官方文档中看到其他信号。

        self.add.clicked.connect(self.add_element)
self.quit.clicked.connect(self.quit_application)
self.clear.clicked.connect(self.clear_table)

正如您在前面几行中看到的,我们将每个单击的信号连接到不同的插槽。在这个示例中,槽是负责执行与按钮相关联的确定任务的普通类方法。用@Slot()修饰每个方法声明非常重要,这样PySide6就知道如何在内部将它们注册到Qt中。

    def add_element(self):
des = self.description.text()
price = self.price.text()

self.table.insertRow(self.items)
self.table.setItem(self.items, 0, QTableWidgetItem(des))
self.table.setItem(self.items, 1, QTableWidgetItem(price))

self.description.setText("")
self.price.setText("")

self.items += 1

@Slot()
def quit_application(self):
QApplication.quit()

def fill_table(self, data=None):
data = self._data if not data else data
for desc, price in data.items():
self.table.insertRow(self.items)
self.table.setItem(self.items, 0, QTableWidgetItem(desc))
self.table.setItem(self.items, 1, QTableWidgetItem(str(price)))
self.items += 1

@Slot()
def clear_table(self):
self.table.setRowCount(0)
self.items = 0

因为这些槽是方法,所以我们可以访问类变量,比如我们的QTableWidget来与它交互。

将元素添加到表中的机制描述如下:

  • 从字段中获取描述和价格,
  • 向表中插入新的空行,
  • 设置每列空行的值,
  • 清除输入文本字段,
  • 包括表行的全局计数。

要退出应用程序,可以使用唯一QApplication实例的quit()方法,要清除表的内容,只需将表行计数和内部计数设置为零即可。

验证步骤

向表中添加信息是一项关键操作,需要验证步骤以避免添加无效信息,例如空信息。

您可以使用QLineEdit中名为textChanged[str]的信号,该信号将在每次内部内容发生变化时发出,即:每个按键笔划。注意,这一次,信号上有一个[str]部分,这意味着信号还将发出已更改的文本值,这对于验证QLineEdit的当前内容非常有用。

您可以将两个不同对象的信号连接到同一插槽,当前应用程序就是这样:

self.description.textChanged[str].connect(self.check_disable)
self.price.textChanged[str].connect(self.check_disable)

check_disable槽的内容非常简单:

    @Slot()
def check_disable(self, s):
if not self.description.text() or not self.price.text():
self.add.setEnabled(False)
else:
self.add.setEnabled(True)

您有两个选项,根据检索到的字符串的当前值编写验证,或者手动获取两个QLineEdit的全部内容。在这种情况下,第二个是首选的,因此您可以验证两个输入是否为空,以启用按钮Add。

提示: Qt还提供了一个名为QValidator的特殊类,您可以使用它来验证任何输入。

空图表视图

可以将新项目添加到表中,可视化目前还可以,但通过以图形方式表示数据,您可以完成更多工作。

首先,您将在应用程序的右侧包含一个空的QChartView占位符。

        # Chart
self.chart_view = QChartView()
self.chart_view.setRenderHint(QPainter.Antialiasing)

此外,如何在右侧QVBoxLayout中包含小部件的顺序也会改变。

        self.right = QVBoxLayout()
self.right.addWidget(QLabel("Description"))
self.right.addWidget(self.description)
self.right.addWidget(QLabel("Price"))
self.right.addWidget(self.price)
self.right.addWidget(self.add)
self.right.addWidget(self.plot)
self.right.addWidget(self.chart_view)
self.right.addWidget(self.clear)
self.right.addWidget(self.quit)

注意,之前我们用self.right.addStretch()填充Add和Clear按钮之间的垂直空间,但现在,使用QChartView就不需要了。

此外,如果您想按需执行,则需要包含“Plot ”按钮。

完整应用程序

最后一步,您需要将Plot按钮连接到一个插槽,该插槽创建一个图表并将其包含在QChartView中。

        self.add.clicked.connect(self.add_element)
self.quit.clicked.connect(self.quit_application)
self.plot.clicked.connect(self.plot_data)
self.clear.clicked.connect(self.clear_table)
self.description.textChanged[str].connect(self.check_disable)
self.price.textChanged[str].connect(self.check_disable)

这并不是什么新鲜事,因为你已经为其他按钮做过了,但现在看看如何创建图表并将其包含到QChartView中。

    def plot_data(self):
# Get table information
series = QPieSeries()
for i in range(self.table.rowCount()):
text = self.table.item(i, 0).text()
number = float(self.table.item(i, 1).text())
series.append(text, number)

chart = QChart()
chart.addSeries(series)
chart.legend().setAlignment(Qt.AlignLeft)
self.chart_view.setChart(chart)

以下步骤显示如何填充QPieSeries:

  • 创建QPieSeries,
  • 遍历表行ID,
  • 在i位置获取项目,
  • 将这些值添加到系列中。

用我们的数据填充系列后,您可以创建一个新的QChart,在上面添加系列,并可以选择为图例设置对齐方式。

最后一行self.chart_view.setChart(chart)负责将新创建的图表带到QChartView。

应用程序将如下所示:

PySide6: 花销工具教程_pySide6

现在您可以看到整个代码:

# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial

import sys
from PySide6.QtCore import Qt, Slot
from PySide6.QtGui import QAction, QPainter
from PySide6.QtWidgets import (QApplication, QHeaderView, QHBoxLayout, QLabel, QLineEdit,
QMainWindow, QPushButton, QTableWidget, QTableWidgetItem,
QVBoxLayout, QWidget)
from PySide6.QtCharts import QChartView, QPieSeries, QChart

class Widget(QWidget):
def __init__(self):
QWidget.__init__(self)
self.items = 0

# Example data
self._data = {"Water": 24.5, "Electricity": 55.1, "Rent": 850.0,
"Supermarket": 230.4, "Internet": 29.99, "Bars": 21.85,
"Public transportation": 60.0, "Coffee": 22.45, "Restaurants": 120}

# Left
self.table = QTableWidget()
self.table.setColumnCount(2)
self.table.setHorizontalHeaderLabels(["Description", "Price"])
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

# Chart
self.chart_view = QChartView()
self.chart_view.setRenderHint(QPainter.Antialiasing)

# Right
self.description = QLineEdit()
self.price = QLineEdit()
self.add = QPushButton("Add")
self.clear = QPushButton("Clear")
self.quit = QPushButton("Quit")
self.plot = QPushButton("Plot")

# Disabling 'Add' button
self.add.setEnabled(False)

self.right = QVBoxLayout()
self.right.addWidget(QLabel("Description"))
self.right.addWidget(self.description)
self.right.addWidget(QLabel("Price"))
self.right.addWidget(self.price)
self.right.addWidget(self.add)
self.right.addWidget(self.plot)
self.right.addWidget(self.chart_view)
self.right.addWidget(self.clear)
self.right.addWidget(self.quit)

# QWidget Layout
self.layout = QHBoxLayout()
#self.table_view.setSizePolicy(size)
self.layout.addWidget(self.table)
self.layout.addLayout(self.right)

# Set the layout to the QWidget
self.setLayout(self.layout)

# Signals and Slots
self.add.clicked.connect(self.add_element)
self.quit.clicked.connect(self.quit_application)
self.plot.clicked.connect(self.plot_data)
self.clear.clicked.connect(self.clear_table)
self.description.textChanged[str].connect(self.check_disable)
self.price.textChanged[str].connect(self.check_disable)

# Fill example data
self.fill_table()

@Slot()
def add_element(self):
des = self.description.text()
price = self.price.text()

try:
price_item = QTableWidgetItem(f"{float(price):.2f}")
price_item.setTextAlignment(Qt.AlignRight)

self.table.insertRow(self.items)
description_item = QTableWidgetItem(des)

self.table.setItem(self.items, 0, description_item)
self.table.setItem(self.items, 1, price_item)
self.description.setText("")
self.price.setText("")
self.items += 1
except ValueError:
print("Wrong price", price)


@Slot()
def check_disable(self, s):
if not self.description.text() or not self.price.text():
self.add.setEnabled(False)
else:
self.add.setEnabled(True)

@Slot()
def plot_data(self):
# Get table information
series = QPieSeries()
for i in range(self.table.rowCount()):
text = self.table.item(i, 0).text()
number = float(self.table.item(i, 1).text())
series.append(text, number)

chart = QChart()
chart.addSeries(series)
chart.legend().setAlignment(Qt.AlignLeft)
self.chart_view.setChart(chart)

@Slot()
def quit_application(self):
QApplication.quit()

def fill_table(self, data=None):
data = self._data if not data else data
for desc, price in data.items():
description_item = QTableWidgetItem(desc)
price_item = QTableWidgetItem(f"{price:.2f}")
price_item.setTextAlignment(Qt.AlignRight)
self.table.insertRow(self.items)
self.table.setItem(self.items, 0, description_item)
self.table.setItem(self.items, 1, price_item)
self.items += 1

@Slot()
def clear_table(self):
self.table.setRowCount(0)
self.items = 0


class MainWindow(QMainWindow):
def __init__(self, widget):
QMainWindow.__init__(self)
self.setWindowTitle("Tutorial")

# Menu
self.menu = self.menuBar()
self.file_menu = self.menu.addMenu("File")

# Exit QAction
exit_action = QAction("Exit", self)
exit_action.setShortcut("Ctrl+Q")
exit_action.triggered.connect(self.exit_app)

self.file_menu.addAction(exit_action)
self.setCentralWidget(widget)

@Slot()
def exit_app(self, checked):
QApplication.quit()

if __name__ == "__main__":
# Qt Application
app = QApplication(sys.argv)
# QWidget
widget = Widget()
# QMainWindow using QWidget as central widget
window = MainWindow(widget)
window.resize(800, 600)
window.show()

# Execute application
sys.exit(app.exec())


标签:__,教程,right,花销,self,PySide6,table,data,price
From: https://blog.51cto.com/u_13722598/5887390

相关文章

  • 2分钟实战QQ机器人教程(保姆级)手把手教你极速开发
    2022十二月最新版QQ机器人搭建官网:https://lovekami.com声明:本项目仅用于自动化测试,不可用于非法行为。且不承担一切法律责任。windows篇:去官网下载主程序:  (如下......
  • python3下载及安装教程
    1.下载python安装包进入python官网下载(官网https://www.python.org/)鼠标指向Downloads(不用点击)会弹出下拉框,根据自己的环境需要下载对应的版本,这里我下载的是Windows环境......
  • RNA-seq 详细教程:分析流程介绍(1)
    学习目标了解从RNA提取到获取基因表达矩阵,既RNA-seq分析的整个流程。1.workflow进行差异表达基因分析的前提是,获取代表基因表达水平的矩阵。因此在进行分析前,必须......
  • 【J2me 2D 游戏开发系列】◣Himi游戏开发启蒙教程◢Java零基础学习J2me游戏开发全过程
    本站文章均为​​ 李华明Himi ​​​原创,转载务必在明显处注明:Himi从写博客的最早开始就是Android游戏开发相关的,其实那么很多童鞋也知道Himi是做Java-J2me/Kjava出身,所......
  • PS新手教程-如何使用PS将风景照里的草地变为湖泊场景
    如何使用PS将风景照里的草地变为湖泊场景?给大家介绍如何使用PS将风景照里的草地变为湖泊场景,一起来看看吧。1.将风景照片素材拖进PS中,复制多次背景图层,得到背景副本、背景......
  • 3.3 Docker最新入门教程-Docker入门-更新应用程序
    3.3更新应用程序在第2部分中,您容器化了一个待办事项应用程序。在这一部分中,您将更新应用程序和容器镜像。您还将学习如何停止和删除容器。更新源代码在下面的步骤中,......
  • Java基础学习笔记(菜鸟教程版)
    Java基础学习笔记(菜鸟教程版)入门概览第一个Java程序helloworldpublicclassHello{publicstaticvoidmain(String[]args){/*pubic-->访问修饰符static-......
  • 2022最新整理iOS app上架app详细教程​
    上架iOS需要一个付费688的开发者账号,还没有的话申请一个或者借用。​​​申请苹果开发者账号教程​​​上架AppStore之前是先安装到苹果手机测试调试好,app能正常运行再上......
  • iOS App上架App Store详细教程​
    ​​​​​​​注意:下载AU后需安装java8运行环境才能启动;安装好了最新Java8运行环境,解压AU软件包,无需安装,Windows64位系统点击appuploader.exe启动;如果是Linux/Windo......
  • 2022最新整理iOS app上架app详细教程
     上架iOS需要一个付费688的开发者账号,还没有的话申请一个或者借用。申请苹果开发者账号教程上架AppStore之前是先安装到苹果手机测试调试好,app能正常运行再上......