Reputation: 530
I have created a simple window with two buttons and a table view in Qt designer and then save my ui as user_interface.ui. Here is the user_interface.
Then, I use the following code to generate some random data and display them on the window with the Generate data and display button click. I also have a save button to give the user the option to save the generated data as csv:
import sys
import pandas as pd
from numpy.random import randn
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.uic import loadUiType
ui,_=loadUiType('user_interface.ui')
class MainApp(QMainWindow, ui):
def __init__(self, parent=None):
QMainWindow.__init__(self)
self.setupUi(self)
self.generate_table.clicked.connect(self.generate_data)
def generate_data(self):
df = pd.DataFrame(randn(5,4),index='A B C D E'.split(),columns='W X Y Z'.split())
model = pandasModel(df)
self.tableView.setModel(model)
self.save_as_csv.clicked.connect(lambda: self.save_data_as_csv(df))
def save_data_as_csv(self, df):
name = QFileDialog.getSaveFileName(self, 'Save File', filter='*.csv')
if(name[0] == ''):
pass
else:
df.to_csv(name[0], index = False)
class pandasModel(QAbstractTableModel):
def __init__(self, data):
QAbstractTableModel.__init__(self)
self._data = data
def rowCount(self, parent=None):
return self._data.shape[0]
def columnCount(self, parnet=None):
return self._data.shape[1]
def data(self, index, role=Qt.DisplayRole):
if index.isValid():
if role == Qt.DisplayRole:
return str(self._data.iloc[index.row(), index.column()])
return None
def headerData(self, col, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self._data.columns[col]
return None
def main():
app=QApplication(sys.argv)
QApplication.processEvents()
window = MainApp()
window.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
When I hit the Generate data and display button, it works fine and I see the generated table. If I keep hitting this button, I do see the random numbers change and it is what I want.
The problem is that when I want to save the generated data, If I have clicked the Generate data and display 20 times to change the data, I will be asked 20 times (except if I hit Cancel in the save popup window) and it basically is trying to save all the dataframes that have been generated on each click of the Generate data and display button. All I want to save is the most recent generated data right before I hit the Save as csv button. I can't figure out what I need to do to achieve that?
Upvotes: 1
Views: 1156
Reputation: 6112
This is occurring because another instance of the signal is connected to save_data_as_csv
each time generate_data
is called. Instead declare the signal connection one time in the constructor and keep a pointer to the most recent dataframe in your class (self.df
) so it no longer requires passing the dataframe as an argument.
class MainApp(QMainWindow, ui):
def __init__(self, parent=None):
QMainWindow.__init__(self)
self.setupUi(self)
self.generate_table.clicked.connect(self.generate_data)
self.save_as_csv.clicked.connect(self.save_data_as_csv)
def generate_data(self):
self.df = pd.DataFrame(randn(5,4),index='A B C D E'.split(),columns='W X Y Z'.split())
model = pandasModel(self.df)
self.tableView.setModel(model)
def save_data_as_csv(self):
name = QFileDialog.getSaveFileName(self, 'Save File', filter='*.csv')
if(name[0] == ''):
pass
else:
self.df.to_csv(name[0], index = False)
Upvotes: 2