Reputation: 113
First off I'm relatively new to python and very new to PyQt. I'm taking my first steps into object oriented programming and I have been looking at online tutorials, but I'm stuck on a multiple inheritance issue.
I have class called CreateTable() whose purpose is to make a QTableWidget in my app window and when a row is clicked it opens a context menu and you can then choose the option to graph the selected row. Where the graph option is connected to another class Plotter().
My problem is that CreateTable needs to inherit both the QTableWidget from PyQt and my class MainWindow because I need to reference the layout variable in order to embed my graph into my application window.
My code for attempted inheritance is as follows and heavily borrows from here:How does Python's super() work with multiple inheritance?
class QTable(QTableWidget):
def __init__(self):
super(QTable, self).__init__()
class PassMain(MainWindow):
def __init__(self):
super(PassMain, self).__init__()
class PassMainTable(PassMain, QTable):
def __init__(self):
super(PassMainTable, self).__init__()
The main problem is when I try to place the graph inside my MainWindow layout.
self.vboxRight.addWidget(self.Graph)
Here is my code for creating the table and calling plotter
class CreateTable(PassMainTable): #QTableWidget
def __init__(self, Data, row, col, colHeaders, rowHeaders): #Index, ColumnHeaders
super(CreateTable, self).__init__()
self.setSelectionBehavior(self.SelectRows)
print("Start initialization")
self.ColHeader = colHeaders
self.setRowCount(row)
self.setColumnCount(col)
self.data = Data
self.setHorizontalHeaderLabels(colHeaders)
print("Right before for loop")
n = len(Data)
m = len(colHeaders)
for i in range(n):
DataValues = self.data.iloc[i,:]
print("values are {}".format(DataValues))
#m = len(values)
ConvertedVals = pd.to_numeric(DataValues)
ValList = DataValues.values.tolist()
print(ValList)
for j in range(0,m):
self.item = QTableWidgetItem(str(round(ValList[j],5)))
#print("{}, {}".format(i, j))
self.setItem(i,j, self.item)
def contextMenuEvent(self, event):
menu = QMenu(self)
graphAction = menu.addAction("Graph")
compareAction = menu.addAction("Compare")
scatterAction = menu.addAction("Plot types")
aboutAction = menu.addAction("about")
quitAction = menu.addAction("quit")
printAction = menu.addAction("Print Row")
action = menu.exec_(self.mapToGlobal(event.pos()))
if action == quitAction:
qApp.quit()
elif action == printAction:
self.selected = self.selectedItems()
n = len(self.selected)
print("n is {}".format(n))
for i in range(n):
self.selected[i] = str(self.selected[i].text())
for i in range(n):
self.selected[i] = float(self.selected[i])
print(self.selected)
elif action == graphAction:
self.selected = self.selectedItems()
n = len(self.selected)
for i in range(n):
self.selected[i] = str(self.selected[i].text())
for i in range(n):
self.selected[i] = float(self.selected[i])
print("right before plotter called")
self.Graph = Plotter(self.selected, self.ColHeader)
self.vboxRight.addWidget(self.Graph)
else:
print("u clicked something other than quit")
To make matters worse PyQt is catching all my errors as exceptions so all I get for errors is "Process finished with exit code 1"
if you need further reference to my full code I have provided a link here: https://github.com/Silvuurleaf/Data-Analysis-and-Visualization-GUI/blob/master/Plotter3.1.py
Thank you I appreciate any help y'all can give me.
Upvotes: 1
Views: 1582
Reputation: 243993
In order to share data it is not necessary to inherit from the widget, just use signals, this is the natural way in PyQt to share data asynchronously. In your case for example we will create a signal called dataSignal
, according to what is observed of your code you want to use the variables self.selected
, self.ColHeader
, the first one is of type list
, and the second numpy.ndarray
so with that We will build the signal:
class CreateTable(QTableWidget): #QTableWidget
dataSignal = pyqtSignal(list, np.ndarray)
def __init__(self, Data, row, col, colHeaders, rowHeaders): #Index, ColumnHeaders
super(CreateTable, self).__init__()
self.setSelectionBehavior(self.SelectRows)
print("Start initialization")
self.ColHeader = colHeaders
self.setRowCount(row)
self.setColumnCount(col)
self.data = Data
self.setHorizontalHeaderLabels(colHeaders)
print("Right before for loop")
n = len(Data)
m = len(colHeaders)
for i in range(n):
DataValues = self.data.iloc[i,:]
print("values are {}".format(DataValues))
#m = len(values)
ConvertedVals = pd.to_numeric(DataValues)
ValList = DataValues.values.tolist()
print(ValList)
for j in range(0,m):
self.item = QTableWidgetItem(str(round(ValList[j],5)))
#print("{}, {}".format(i, j))
self.setItem(i,j, self.item)
def contextMenuEvent(self, event):
menu = QMenu(self)
graphAction = menu.addAction("Graph")
compareAction = menu.addAction("Compare")
scatterAction = menu.addAction("Plot types")
aboutAction = menu.addAction("about")
quitAction = menu.addAction("quit")
printAction = menu.addAction("Print Row")
action = menu.exec_(self.mapToGlobal(event.pos()))
if action == quitAction:
qApp.quit()
elif action == printAction:
self.selected = self.selectedItems()
n = len(self.selected)
print("n is {}".format(n))
for i in range(n):
self.selected[i] = str(self.selected[i].text())
for i in range(n):
self.selected[i] = float(self.selected[i])
print(self.selected)
elif action == graphAction:
self.selected = self.selectedItems()
n = len(self.selected)
for i in range(n):
self.selected[i] = str(self.selected[i].text())
for i in range(n):
self.selected[i] = float(self.selected[i])
print("right before plotter called")
print(type(self.selected), type(self.ColHeader))
self.dataSignal.emit(self.selected, self.ColHeader)
else:
print("u clicked something other than quit")
Then in the MainWindow class we create a slot, in this create the Plotter object and add it to the layout.
def dataPlotter(self, x_data,y_data):
self.Graph = Plotter(x_data, y_data)
self.vboxRightBottom.addWidget(self.Graph)
To do this we connect the signal when we create the CreateTable
object:
self.Table = CreateTable(self.BaseStats, row, col, colHeaders, rowHeaders)
self.Table.dataSignal.connect(self.dataPlotter)
self.vboxRightBottom.addWidget(self.Table)
The complete code is here.
Upvotes: 1