PyQT5 - QTableView.setModel crashes the program
Sabari Girish Janakiraman
jsgirish at gmail.com
Mon Apr 27 16:20:18 BST 2020
Hello Experts,
I am Sabari Girish and I joined this mailer list just today. Hence, this is
my first query in this forum. Also, I am fairly new to PyQT5.
*What I am trying to do*
I am trying to build a desktop application in Python to analyze and
generate performance reports on a Stock Market Swing Trading Strategy by
downloading end of the day data from our Indian Stock Market Exchange (NSE)
and using this data to analyze our trading strategy which we have put in an
excel.
I have a tabbed view and in each tabs I am trying to display some data in
tabular format using QTableView and TableModel.
As of now, I have 3 tables:
(1) NSE Data Table - Data changes dynamically based on a date selected from
a combo box.
(2) Swing Data Table - Data changes dynamically based on a date selected
from a combo box.
(3) Swing Filter Data Table - Data changes dynamically based on a date
selected from a combo box.
*My Issue:*
(1) NSE Data Table works fine without issues
(2) Swing Data Table - Program crashes while setting the model.
self._view.swingmaindata_table.setModel(self._view.swingmain_model)
The program abruptly crashes here with the following message:
Process finished with exit code -1073740791 (0xC0000409)
*My Environment*
Python 3.7.2
PyCharm IDE
PyQT5
I am looking for help to see where the below issues are and how I can fix
them:
(1) setModel crashing the program
(2) How to dynamically update data in a table? (Replace entire data with a
different set of data)
*Code Snip*
I am trying to use the MVC architecture.
class DbtMain(QMainWindow):
# DBT's View (GUI) Initializer
def __init__(self):
super().__init__()
# Set main window properties
self.__set_main_window_properties__()
# Set the central widget, layout
self.__set_central_widget_and_layout__()
# Set Tabs in the layout
self.__set_tabs_in_layout__()
'''
Set main window properties
'''
def __set_main_window_properties__(self):
self.title = 'DELIVERY BASED SWING TRADING'
self.left = 0
self.top = 0
self.width = 1300
self.height = 700
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
'''
Set central widget and layout
'''
def __set_central_widget_and_layout__(self):
self.layout = QVBoxLayout(self)
self._dbt = QWidget(self)
self.setCentralWidget(self._dbt)
self._dbt.setLayout(self.layout)
'''
Set tabs in layout.
Create and add tabs to the DBT central widget layout.
1. DBT App configuration tab
2. NSE Data downloader and view tab
3. Swing file upload tab
4. Charts tab
'''
def __set_tabs_in_layout__(self):
# Main tab widget
self.tabs = QTabWidget()
self.tabs.resize(1000, 600)
# Create configure tab and add to main tab widget
self._configure_ui()
# Create NSE data download and view tab and add to main tab widget
self._nsedata_ui()
# Create swing file upload tab and add to main tab widget
self._upload_swing_ui()
# Add tabs to main DBT layout
self.layout.addWidget(self.tabs)
def label(self, lbl, text, y, x):
lbl.setText(text)
lbl.move(y, x)
def format_text(self, txt):
txt = f"<P><b><FONT COLOR='#ff0000' FONT SIZE = 4>{txt}</b></P></br>"
return txt
def _nsedata_ui(self):
# Create the NSE data tab
self.nsedata_tab = QWidget()
self.tabs.addTab(self.nsedata_tab, "NSE EoD Data")
# Add the drop down box
self.dc_label = QLabel(self.nsedata_tab)
txt = self.format_text("NSE data available dates")
# txt = "<P><b><FONT COLOR='#ff0000' FONT SIZE = 4>NSE data
available dates</b></P></br>"
self.label(self.dc_label, txt, 5, 20)
self.nsedata_dates = QComboBox(self.nsedata_tab)
self.nsedata_dates.addItems(NseData.data.keys())
self.nsedata_dates.move(10, 50)
# Add the QTableView
self.nsetbl_label = QLabel(self.nsedata_tab)
self.nsedata_table = QTableView(self.nsedata_tab)
self.nsedata_table.resize(1050, 550)
self.nsedata_table.move(200, 50)
def _configure_ui(self):
self.configure_tab = QWidget()
self.tabs.addTab(self.configure_tab, "Configuration")
def _upload_swing_ui(self):
self.swingdata_tab = QWidget()
self.tabs.addTab(self.swingdata_tab, "Swing File Upload")
# Add the drop down box
self.swing_dc_label = QLabel(self.swingdata_tab)
txt = self.format_text("Swing data available dates")
self.label(self.swing_dc_label, txt, 5, 20)
self.swingdata_dates = QComboBox(self.swingdata_tab)
self.swingdata_dates.addItems(SwingFile.data.keys())
self.swingdata_dates.move(10, 50)
# Add the QTableView for Main swing data
self.swingmaintbl_label = QLabel(self.swingdata_tab)
self.swingmain_table = QTableView(self.swingdata_tab)
self.swingmain_table.resize(1050, 250)
self.swingmain_table.move(200, 50)
# Add the QTableView for Filter swing data
self.swingfiltertbl_label = QLabel(self.swingdata_tab)
self.swingfilter_table = QTableView(self.swingdata_tab)
self.swingfilter_table.resize(1050, 250)
self.swingfilter_table.move(200, 400)
class DbtController:
# Controller initializer
def __init__(self, view):
self._view = view
# Default to 1st date of download
self._show_nse_data(self._view.nsedata_dates.currentText())
# Connect signals and slots
self._connect_signals()
def _refresh_nse_data(self, i):
self._show_nse_data(self._view.nsedata_dates.currentText())
def _show_nse_data(self, dt=datetime.date.today().strftime("%d-%b-%Y")):
self._view.nsedata_model = TableModel(NseData.data[dt])
self._view.nsedata_table.setModel(self._view.nsedata_model)
txt = f"<P><b><FONT COLOR='#ff0000' FONT SIZE = 4>NSE Data for
{dt}</b></P></br>"
self._view.label(self._view.nsetbl_label, txt, 300, 20)
def _refresh_swing_data(self, i):
print(f"REFRESH SWING - {i},
{self._view.swingdata_dates.currentText()}")
# self._show_swing_data(self._view.swingdata_dates.currentText())
self._view.swingmain_model.update(self._view.swingdata_dates.currentText())
def _show_swing_data(self, dt=datetime.date.today().strftime("%d-%b-%Y")):
if dt == datetime.date.today().strftime("%d-%b-%Y"):
dt = max(SwingFile.datesobj).strftime("%d-%b-%Y")
print(f"SHOW SWING - {dt}")
self._view.swingmain_model = TableModel(SwingFile.data[dt]['main'])
print(SwingFile.data[dt]['main'])
print("MOD-1")
self._view.swingmaindata_table.setModel(self._view.swingmain_model)
# <--- *PROGRAM CRASHES HERE*
print("MOD-1.1")
txt = f"<P><b><FONT COLOR='#ff0000' FONT SIZE = 4>Swing Main
Data for {dt}</b></P></br>"
self._view.label(self._view.swingmaintbl_label, txt, 300, 20)
self._view.swingfilter_model = TableModel(SwingFile.data[dt]['filter'])
print("MOD-2")
self._view.swingfilterdata_table.setModel(self._view.swingfilter_model)
print("MOD-2.1")
txt = f"<P><b><FONT COLOR='#ff0000' FONT SIZE = 4>Swing Filter
Data for {dt}</b></P></br>"
self._view.label(self._view.swingfiltertbl_label, txt, 300, 400)
'''
Connect "Choose date from drop down box signal" with respective slots
'''
def _connect_signals(self):
self._view.nsedata_dates.activated.connect(partial(self._refresh_nse_data))
self._view.swingdata_dates.activated.connect(partial(self._refresh_swing_data))
# self._view.buttons['Update'].clicked.connect(self._refresh_nse_data)
class TableModel(QtCore.QAbstractTableModel):
def __init__(self, data):
super(TableModel, self).__init__()
self._data = data
self.header_labels = data[0]
print(data[0])
self._data.remove(data[0])
def headerData(self, section, orientation, role=Qt.DisplayRole):
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self.header_labels[section]
return QAbstractTableModel.headerData(self, section, orientation, role)
def update(self, datain):
self._data = datain
def data(self, index, role):
if role == Qt.DisplayRole:
# See below for the nested-list data structure.
# .row() indexes into the outer list,
# .column() indexes into the sub-list
return self._data[index.row()][index.column()]
def rowCount(self, index):
# The length of the outer list.
return len(self._data)
def columnCount(self, index):
# The following takes the first sub-list, and returns
# the length (only works if all rows are an equal length)
return len(self._data[0])
Thanks all in advance.
J.S.Girish
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://www.riverbankcomputing.com/pipermail/pyqt/attachments/20200427/43bb0c93/attachment-0001.htm>
More information about the PyQt
mailing list