单击按钮后在 PyQt 窗口中显示 PyQt 图表

Posted

技术标签:

【中文标题】单击按钮后在 PyQt 窗口中显示 PyQt 图表【英文标题】:Displaying a PyQt Chart in a PyQt Window after a button click 【发布时间】:2021-12-18 19:02:05 【问题描述】:

我正在使用 PyQT 和 QtDesigner 为大学项目构建一个简单的(!)GUI 应用程序。

主窗口显示一些简单的标签和文本框(工资、养老金缴款百分比、询问用户是否有学生贷款)。单击并单击“计算”按钮后,其想法是 QtChart(现在是简单的饼图)将在表单底部显示一些预定义的空间。我在表单底部添加了一个 Widget,可以正确执行所有计算并绘制图表,但我不知道如何设置 Widget 的属性以便它显示图表。

我观看了大量教程并阅读了大量文章,但似乎找不到以相同方式执行此操作的示例。一个不太理想的选择是启动一个显示图表的新窗口,但实际上我想在我的 gui 中的预定义空间中显示,以便我可以完全控制 UI 体验。

我在下面添加了相关的代码部分,如果有人能告诉我哪里出错了,我将不胜感激!非常感谢。

# main.py

import sys
import gui

# app_choice = 'mail'
app_choice = 'salary'
# app_choice = 'todo_list'

if __name__ == "__main__":
    app = gui.QtWidgets.QApplication(sys.argv)
    win = gui.QtWidgets.QMainWindow()

    if app_choice == 'mail':
        ui = gui.Ui_MainWindowMail()
    elif app_choice == 'salary':
        ui = gui.Ui_MainWindowTax()
    elif app_choice == 'todo_list':
        raise ValueError('This app is still being built!')
    else:
        raise ValueError('An incorrect app choice was made.')

    ui.setupUi(win)
    win.show()
    sys.exit(app.exec_())


# gui.py

from PyQt5 import QtCore, QtGui, QtWidgets
import mail
import tax
from PyQt5.QtWidgets import *
from PyQt5.QtChart import QChart, QChartView, QPieSeries, QPieSlice
from PyQt5.QtGui import QPainter, QPen, QFont
from PyQt5.QtCore import Qt

class Ui_MainWindowMail(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(362, 255)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.btn_send = QtWidgets.QPushButton(self.centralwidget)
        self.btn_send.setGeometry(QtCore.QRect(250, 190, 81, 31))
        self.btn_send.setObjectName("btn_send")
        self.btn_send.clicked.connect(self.btn_send_click)  # Call the 'clicked' function when button is clicked
        self.lbl_to = QtWidgets.QLabel(self.centralwidget)
        self.lbl_to.setGeometry(QtCore.QRect(30, 20, 51, 21))
        self.lbl_to.setObjectName("lbl_to")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(30, 40, 111, 31))
        self.label.setObjectName("label")
        self.txt_to = QtWidgets.QLineEdit(self.centralwidget)
        self.txt_to.setGeometry(QtCore.QRect(120, 20, 211, 20))
        self.txt_to.setObjectName("txt_to")
        self.txt_msg = QtWidgets.QTextEdit(self.centralwidget)
        self.txt_msg.setGeometry(QtCore.QRect(120, 50, 211, 131))
        self.txt_msg.setDocumentTitle("")
        self.txt_msg.setObjectName("textEdit")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 362, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Send Email Tool"))
        self.btn_send.setText(_translate("MainWindow", "Send Email"))
        self.lbl_to.setText(_translate("MainWindow", "Send to:"))
        self.label.setText(_translate("MainWindow", "Email message:"))

    def btn_send_click(self):
        if self.txt_to.text() != "" and self.txt_msg.toPlainText() != "":
            mail.send_mail(self.txt_to.text(), self.txt_msg.toPlainText())
            self.txt_to.setText("")
            self.txt_msg.setText("")
            qm = QtWidgets.QMessageBox()
            qm.setWindowTitle("Send Email Tool")
            qm.setText("Email sent")
            qm.exec()
        else:
            qm = QtWidgets.QMessageBox()
            qm.setWindowTitle("Send Email Tool - ERROR")
            qm.setText("Some information is missing.  Please check and try again.")
            qm.exec()


class Ui_MainWindowTax(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(465, 650)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label_title = QtWidgets.QLabel(self.centralwidget)
        self.label_title.setGeometry(QtCore.QRect(20, 10, 371, 21))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_title.setFont(font)
        self.label_title.setAlignment(QtCore.Qt.AlignCenter)
        self.label_title.setObjectName("label_title")
        self.label_salary = QtWidgets.QLabel(self.centralwidget)
        self.label_salary.setGeometry(QtCore.QRect(30, 60, 240, 21))
        self.label_salary.setObjectName("label_salary")
        self.txt_salary = QtWidgets.QLineEdit(self.centralwidget)
        self.txt_salary.setGeometry(QtCore.QRect(270, 60, 161, 20))
        self.txt_salary.setObjectName("txt_salary")
        self.label_pension = QtWidgets.QLabel(self.centralwidget)
        self.label_pension.setGeometry(QtCore.QRect(30, 100, 221, 16))
        self.label_pension.setObjectName("label_pension")
        self.spin_pension = QtWidgets.QSpinBox(self.centralwidget)
        self.spin_pension.setGeometry(QtCore.QRect(270, 100, 51, 22))
        self.spin_pension.setObjectName("spin_pension")
        self.combo_student_loan = QtWidgets.QComboBox(self.centralwidget)
        self.combo_student_loan.setGeometry(QtCore.QRect(270, 140, 69, 22))
        self.combo_student_loan.setContextMenuPolicy(QtCore.Qt.PreventContextMenu)
        self.combo_student_loan.setEditable(True)
        self.combo_student_loan.setObjectName("combo_student_loan")
        self.combo_student_loan.addItem("")
        self.combo_student_loan.addItem("")
        self.label_student_loan = QtWidgets.QLabel(self.centralwidget)
        self.label_student_loan.setGeometry(QtCore.QRect(30, 140, 211, 16))
        self.label_student_loan.setObjectName("label_student_loan")
        self.button_calculate = QtWidgets.QPushButton(self.centralwidget)
        self.button_calculate.setGeometry(QtCore.QRect(30, 190, 401, 41))
        self.button_calculate.setObjectName("button_calculate")
        self.button_calculate.clicked.connect(self.button_calculate_click)  # Call the 'clicked' function when button is clicked
        self.widget_chart = QWidget(self.centralwidget)
        self.widget_chart.setObjectName("widget_chart")
        self.widget_chart.setGeometry(QtCore.QRect(40, 240, 381, 331))
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 465, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Salary Calculator"))
        self.label_title.setText(_translate("MainWindow", "Salary Calculator"))
        self.label_salary.setText(_translate("MainWindow", "Please enter you gross salary to the nearest £:"))
        self.label_pension.setText(_translate("MainWindow", "Please select your pension contribution (%):"))
        self.combo_student_loan.setCurrentText(_translate("MainWindow", "No"))
        self.combo_student_loan.setItemText(0, _translate("MainWindow", "Yes"))
        self.combo_student_loan.setItemText(1, _translate("MainWindow", "No"))
        self.label_student_loan.setText(_translate("MainWindow", "Do you have a student loan?"))
        self.button_calculate.setText(_translate("MainWindow", "Calculate!"))

    def button_calculate_click(self):

        # Get values entered into the form
        salary = self.txt_salary.text()
        salary = int(salary)
        student_loan_flag = self.combo_student_loan.currentText()
        pension_contribution = self.spin_pension.value()

        # Calculate income tax deductions
        income_tax = tax.calculate_income_tax(salary)
        ni = salary * 0.01

        # Calculate pension deduction
        pension = salary * (pension_contribution / 100)

        # Calculate student loan deduction
        student_loan_pay_threshold = 19895  # Plan 1 repayment threshold.  ToDo: Update to work for all loan plans
        if student_loan_flag == 'No' or salary < student_loan_pay_threshold:
            student_loan = 0
        else:
            student_loan = (salary - student_loan_pay_threshold) * 0.09

        # Calculate Net Pay
        net_pay = salary - income_tax - ni - pension - student_loan

        # Create PyQt chart
        series = QPieSeries()
        series.setHoleSize(0.1)
        series.append("Income Tax", income_tax)
        series.append("NI", ni)
        series.append("Pension", pension)
        series.append("Student Loan", student_loan)
        series.append("Net Pay", net_pay)

        chart = QChart()
        chart.addSeries(series)
        chart.setAnimationOptions(QChart.SeriesAnimations)
        chart.setTheme(QChart.ChartThemeLight)

        chartview = QChartView(chart)
        chartview.setRenderHint(QPainter.Antialiasing)

        #self.widget_chart.setLayout(chartview)

【问题讨论】:

你可以尝试创建一个包含图表视图的中间布局并设置它,不确定它是否可以工作 【参考方案1】:

将图表小部件添加到您的布局中,然后根据需要使用其 QWidget show() hide() 插槽。

【讨论】:

以上是关于单击按钮后在 PyQt 窗口中显示 PyQt 图表的主要内容,如果未能解决你的问题,请参考以下文章

PyQt:按下按钮时没有显示第二个窗口

PyQt5 - 第二个窗口中的按钮在单击时不执行操作

在现有主窗口上显示在 PyQt GUI 上选择组合框选项的图表

PyQT5 与 matplotlib 图,事件循环已经在运行

在 PyQT5 的 groupbox 中显示 matplotlib 图表

在 PyQt 窗口中无延迟地绘制 matplotlib 矩形