首页 > 解决方案 > 更新布局中的 Pyqt 小部件

问题描述

我没有像你们一样有那么多经验,但我尽我所能将一些小项目作为一种爱好来实现。可能有些人对我的小程序的代码感到震惊,还有很多改进的地方。我请你理解。3 个月以来,我编写了这个程序,但现在有了布局,我有点存货,我不能再进一步了。

问题

以前,小部件在主窗口中具有绝对位置。一切正常。当我开始将所有小部件实现为适当的布局时,QTableWidget 和 Matplot 不再更新小部件。当我在应用程序中输入一个值时,GUI 没有任何反应,但数据框是正确的。我重新启动程序,输入的值将应用于 QTableWidget 和 Matplot。

尝试

我开始阅读并尝试使用 Signals 和 Slots 将信号发送到事件循环中。还有我尝试过的线程和模型,但可能不是以正确的方式。什么是解决这个问题的好方法。谢谢你的帮助。

代码

import os, sys, matplotlib
from PyQt5.QtGui import QIcon
from PyQt5 import QtGui, QtWidgets, QtCore
from PyQt5.QtWidgets import qApp, QApplication, QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, QAction, QFileDialog, \
                            QLineEdit, QPushButton, QDateEdit, QComboBox, QTableWidget, QTableWidgetItem
from PyQt5.QtCore import Qt, pyqtSlot
import pandas as pd
import numpy as np
from matplotlib import figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt


class MyForm(QMainWindow):

    def __init__(self):
        super(MyForm, self).__init__()
        self.initUI()

    def initUI(self):
        self.setGeometry(50, 50, 1600, 1200)
        self.resize(1350, 1200)
        self.move(0, 120)
        self.setWindowTitle('Asset allocation')
        self.setWindowIcon(QIcon('icon.png'))

        self.tableView = ShowTable(self)
        self.chart = MatplotlibFigure(self)
        self.inputMask = InputValues(self)

        widget=QWidget()
        gridtotoal=QHBoxLayout(widget)
        vtotal=QVBoxLayout()
        vtotal.addWidget(self.inputMask)
        vtotal.addWidget(self.tableView, 1, alignment=Qt.AlignTop)
        gridtotoal.addLayout(vtotal)
        gridtotoal.addWidget(self.chart, 5)
        self.setCentralWidget(widget)


class InputValues(QWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.initUI()

    def initUI(self):

        h1_layout = QHBoxLayout()
        h1_layout.addSpacing(20)
        self.ledt_value = QLineEdit("", self)
        self.ledt_value.setMaximumSize(190, 40)
        self.ledt_value.setMinimumSize(190, 40)
        self.ledt_value.setCursorPosition(0)
        h1_layout.addWidget(self.ledt_value)

        self.dateEdit = QDateEdit(self)
        self.dateEdit.setMaximumSize(190, 40)
        self.dateEdit.setMinimumSize(190, 40)
        self.dateEdit.setDate(QtCore.QDate.currentDate())
        h1_layout.addWidget(self.dateEdit)

        pbtn_apply = QPushButton('Apply', self)
        pbtn_apply.setMaximumSize(190, 40)
        pbtn_apply.setMinimumSize(190, 40)
        pbtn_apply.setObjectName("pbtn_apply")
        pbtn_apply.clicked.connect(self.input)
        h1_layout.addWidget(pbtn_apply)
        h1_layout.addStretch()

        self.cmbo_account = QComboBox(self)
        self.cmbo_account.setMaximumSize(190, 40)
        self.cmbo_account.setMinimumSize(190, 40)
        self.cmbo_account.addItem("Current Account", "Currrent")
        self.cmbo_account.addItem("Savings Account", "Savings")
        self.cmbo_account.addItem("Stock Portfolio", "Stock")
        h2_layout = QHBoxLayout()
        h2_layout.addSpacing(20)
        h2_layout.addWidget(self.cmbo_account,1, alignment=Qt.AlignLeft)

        v_layout = QVBoxLayout()
        v_layout.addSpacing(35)
        v_layout.addLayout(h1_layout)
        v_layout.addLayout(h2_layout)
        v_layout.addStretch()
        self.setLayout(v_layout)

    def input(self, index):

        value = self.ledt_value.text()
        dateinput = self.dateEdit.date().toPyDate()
        self.euformat = '%d.%m.%Y'
        self.dateeu = dateinput.strftime(self.euformat)
        exists = os.path.isfile("data.csv")
        if exists:
            raw_data = pd.read_csv("data.csv", header=0, delimiter=";")
            df = pd.DataFrame(raw_data, columns=["Date", "Current Account", "Savings Account", "Stock Portfolio"])
        else:
            df = pd.DataFrame(columns=["Date", "Current Account", "Savings Account", "Stock Portfolio"])
        dfdate = pd.to_datetime(df["Date"], format="%d.%m.%Y", dayfirst=True)
        dfdateeu = dfdate.dt.strftime('%d.%m.%Y')
        nanlist = np.argwhere(df[self.cmbo_account.currentData(index)].isnull().values).tolist()

        if len(nanlist)!= 0:
            df.loc[nanlist[0], self.cmbo_account.currentData(index)] = value
        else:
            raw_data_app=pd.DataFrame({'Date': [self.dateeu],self.cmbo_account.currentData(index): [value]})
            df = df.append(raw_data_app, ignore_index=True, sort=False)
        df.to_csv("data.csv", mode='w', header=True, sep=';', index=False)

        tabel = ShowTable(self)
        tabel.createtable()
        canvas = MatplotlibFigure(self)
        canvas.plot()


class ShowTable(QTableWidget):
    def __init__(self, parent):
        super().__init__(parent)
        self.initUI()

    def initUI(self):
        self.tableWidget = QTableWidget()
        self.layout = QVBoxLayout()
        self.setMinimumSize(647, 400)
        self.setMaximumSize(647, 900)
        self.layout.addWidget(self.tableWidget)
        self.setLayout(self.layout)
        self.createtable()

    def createtable(self):
        exists = os.path.isfile("data.csv")
        if exists:
            raw_data = pd.read_csv("data.csv", header=0, delimiter=";")
            df = pd.DataFrame(raw_data, columns=["Date", "Current Account", "Savings Account", "Stock Portfolio"])
        else:
            df = pd.DataFrame(columns=["Date", "Current Account", "Savings Account", "Stock Portfolio"])
        countrows = len(df)
        countcolumn=len(df.columns)

        self.tableWidget.setRowCount(countrows)
        self.tableWidget.setColumnCount(countcolumn)
        for i in range(len(df.index)):
            for j in range(len(df.columns)):
                self.tableWidget.setItem(i, j, QTableWidgetItem(str(df.iloc[i, j])))
        self.tableWidget.resizeRowsToContents()
        self.tableWidget.verticalScrollBar().setValue(self.tableWidget.verticalScrollBar().maximum())
        self.tableWidget.setHorizontalHeaderLabels(["Date", "Current Account", "Savings Account", "Stock Portfolio"])


class MatplotlibFigure(QWidget):

    def __init__(self, parent):
        super().__init__(parent)
        self.left = 10
        self.top = 450
        self.width = 1200
        self.height = 750
        self.setGeometry(self.left, self.top, self.width, self.height)
        # self.layout = QVBoxLayout()
        plt.style.use('fivethirtyeight')
        self.figure = matplotlib.figure.Figure(tight_layout=True)
        self.canvas = FigureCanvas(self.figure)
        self.toolbar = NavigationToolbar(self.canvas, self)
        # self.canvas.setParent(self)
        layout = QVBoxLayout(self)
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        self.plot()
        self.show()

    def plot(self):
        exists = os.path.isfile("data.csv")
        if exists:
            raw_data = pd.read_csv("data.csv", header=0, delimiter=";")
            df = pd.DataFrame(raw_data, columns=["Date","Current Account", "Savings Account", "Stock Portfolio"])
            df["Date"]=pd.to_datetime(df["Date"], format="%d.%m.%Y", dayfirst=True)
            df.set_index(["Date"], drop=True, inplace=True)
            df.index = df.index.to_period(freq='M')
            # df = pd.DataFrame(raw_data, columns=["Girokonto", "Sparkonto", "Depot"], index=pd.date_range(start='2019/04/01', end='2019/06/01',  freq='M'))
            self.figure.clf()
            ax = self.figure.add_subplot(211)
            ax.set_title("Asset allocation", fontsize=20)
            ax.set_xlabel("Date", fontsize=13)
            ax.set_ylabel("Amount of money", fontsize=13)
            ax.tick_params(axis="x", rotation=90)
            ax.grid(which='major', axis='both', linestyle='steps', alpha=0.8)
            df.plot.area(ax=ax, grid=True)

            dfsavings=df.copy()
            dfsavings["Assets"] = dfsavings.sum(axis=1)
            dfsavings["Savings"] = dfsavings["Assets"].diff(periods=1)
            ay = self.figure.add_subplot(212)
            ay.set_title("Monthly Savings", fontsize=20)
            ay.set_xlabel("Date", fontsize=13)
            ay.set_ylabel("Amount of money", fontsize=13)
            ay.tick_params(axis="x", rotation=90)
            ay.grid(which='major', axis='both', linestyle='steps', alpha=0.8)
            dfsavings["Savings"].plot.bar(ax=ay, grid=True)
            self.canvas.draw()
        else:
            pass


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle('fusion')
    MainWindow = MyForm()
    MainWindow.show()
    sys.exit(app.exec_())

CSV 文件的样本数据

Date;Current Account;Savings Account;Stock Portfolio
26.01.2019;13811.0;0.0;20000.0
26.02.2019;14322.0;0.0;20000.0
26.03.2019;7863.0;0.0;20000.0
26.04.2019;5087.0;3000.0;20000.0
26.05.2019;7319.0;3000.0;20000.0
26.06.2019;3667.0;5000.0;23000.0

感谢您的努力!

标签: pythonpyqt5

解决方案


推荐阅读