Reputation: 379
I need to connect a comboBox to a plot function defined within a method of a separate class as seen below. The desired result is that the range selected in the comboBox's items is what is plotted in the figure so it will also be necessary to refresh the canvas upon selection which I could also use advice on.
There are two ways I can think of attaining this result but both are problematic. Ideally, the comboBox would be defined within the class containing the plot function to avoid the difficulty of connecting it to the class(method(function))) from outside the class but I don't think this is possible. Alternatively, it could be defined in setupUI but then how would I connect it to the plot function? Is it possible to reach a class's method's function from outside that class? Advice on either approach will be appreciated. I have condensed the code as much as I can.
import math
import matplotlib
import numpy as np
from PyQt4 import QtCore, QtGui
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
def _fromUtf8(s):
return s
try:
_encoding = QtGui.QApplication.UnicodeUTF8
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
def _translate(context, text, disambig):
return QtGui.QApplication.translate(context, text, disambig)
class MyMplCanvas(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self,
QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
def compute_initial_figure(self):
pass
class UsersPerCountryAndPlatformBar(MyMplCanvas):
def compute_initial_figure(self):
A_B = [['Afghanistan', 'Albania', 'Algeria', 'American Samoa', 'Angola'], [1, 9, 7, 1, 1], [1, 7, 2, 0, 1], \
[0, 4, 3, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
C_F = [['Cambodia', 'Canada', 'Chile', 'China', 'Colombia'], [13, 189, 12, 5, 10], [5, 115, 6, 64, 7], \
[1, 11, 1, 2, 4], [2, 12, 0, 2, 0], [2, 5, 0, 0, 0]]
def plot(X_Y):
summedX_Y = []
for i in range(len(X_Y[0])):
summedX_Y.append(X_Y[1][i] + X_Y[2][i] + X_Y[3][i] + X_Y[4][i] + X_Y[5][i])
def roundup(x):
return int(math.ceil(x / 10.0)) * 10
N = len(X_Y[0])
ind = np.arange(N)
width = 0.75
colors = ['yellowgreen', 'paleturquoise', 'royalblue', 'lightsteelblue', 'firebrick']
print [x + y for x, y in zip(X_Y[1], X_Y[2])]
print [x + y + z for x, y, z in zip(X_Y[1], X_Y[2], X_Y[3])]
print [x + y + z + i for x, y, z, i in zip(X_Y[1], X_Y[2], X_Y[3], X_Y[4])]
p1 = self.axes.bar(ind, X_Y[1], width, color = colors[0])
p2 = self.axes.bar(ind, X_Y[2], width, bottom = X_Y[1], color = colors[1])
p3 = self.axes.bar(ind, X_Y[3], width, bottom = [x + y for x, y in zip(X_Y[1], X_Y[2])], color = colors[2])
p4 = self.axes.bar(ind, X_Y[4], width, bottom = [x + y + z for x, y, z in zip(X_Y[1], X_Y[2], X_Y[3])], color = colors[3])
p5 = self.axes.bar(ind, X_Y[5], width, bottom = [x + y + z + i for x, y, z, i in zip(X_Y[1], X_Y[2], X_Y[3], X_Y[4])], color = colors[4])
self.axes.set_ylabel('Count')
self.axes.set_title('Users Per Country And Platform')
self.axes.set_xticks(ind)
self.axes.set_xticklabels(countrylabels, fontsize = 8)
self.axes.set_yticklabels(np.arange(0, max(summedX_Y), roundup(max(summedX_Y) / 10)))
self.axes.legend((p1[0], p2[0], p3[0], p4[0], p5[0]), ('Android', 'iOS', 'Windows', 'OS X', 'WebGL'))
'''comboBox = QtGui.QComboBox(self)
comboBox.addItem('A_B')
comboBox.addItem('C_F')
comboBox.activated[str].connect(compute_initial_figure(plot(text)))'''
# should plot(A_B) or (C_F) as selected
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.main_widget = QtGui.QWidget(MainWindow)
l = QtGui.QVBoxLayout(self.main_widget)
UPCP = UsersPerCountryAndPlatformBar(self.main_widget, width = 10, height = 5, dpi = 100)
l.addWidget(UPCP)
self.main_widget.setFocus()
MainWindow.setCentralWidget(self.main_widget)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Upvotes: 0
Views: 995
Reputation: 339062
You can have a look at the code down below. I removed the doubly subclassing for better readability.
compute_initial_figure
is called when the FigureCanvas is initialized.
The combo sits in the mainwindow class and is connected to an update function. This function converts the text from the combobox to some data which is passed to the plot function.
import math
import numpy as np
from PyQt4 import QtGui
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
class UsersPerCountryAndPlatformBar(FigureCanvas):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
FigureCanvas.__init__(self, fig)
self.axes = fig.add_subplot(111)
self.compute_initial_figure()
def compute_initial_figure(self):
A_B = [['Afghanistan', 'Albania', 'Algeria', 'American Samoa', 'Angola'], [1, 9, 7, 1, 1], [1, 7, 2, 0, 1], \
[0, 4, 3, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
C_F = [['Cambodia', 'Canada', 'Chile', 'China', 'Colombia'], [13, 189, 12, 5, 10], [5, 115, 6, 64, 7], \
[1, 11, 1, 2, 4], [2, 12, 0, 2, 0], [2, 5, 0, 0, 0]]
self.data = {"A_B" : A_B, "C_F" : C_F}
self.updatefig("A_B")
def updatefig(self, text):
self.plot(self.data[text])
def plot(self, X_Y):
self.axes.clear()
summedX_Y = []
for i in range(len(X_Y[0])):
summedX_Y.append(X_Y[1][i] + X_Y[2][i] + X_Y[3][i] + X_Y[4][i] + X_Y[5][i])
def roundup(x):
return int(math.ceil(x / 10.0)) * 10
N = len(X_Y[0])
ind = np.arange(N)
width = 0.75
colors = ['yellowgreen', 'paleturquoise', 'royalblue', 'lightsteelblue', 'firebrick']
print [x + y for x, y in zip(X_Y[1], X_Y[2])]
print [x + y + z for x, y, z in zip(X_Y[1], X_Y[2], X_Y[3])]
print [x + y + z + i for x, y, z, i in zip(X_Y[1], X_Y[2], X_Y[3], X_Y[4])]
p1 = self.axes.bar(ind, X_Y[1], width, color = colors[0])
p2 = self.axes.bar(ind, X_Y[2], width, bottom = X_Y[1], color = colors[1])
p3 = self.axes.bar(ind, X_Y[3], width, bottom = [x + y for x, y in zip(X_Y[1], X_Y[2])], color = colors[2])
p4 = self.axes.bar(ind, X_Y[4], width, bottom = [x + y + z for x, y, z in zip(X_Y[1], X_Y[2], X_Y[3])], color = colors[3])
p5 = self.axes.bar(ind, X_Y[5], width, bottom = [x + y + z + i for x, y, z, i in zip(X_Y[1], X_Y[2], X_Y[3], X_Y[4])], color = colors[4])
self.axes.set_ylabel('Count')
self.axes.set_title('Users Per Country And Platform')
self.axes.set_xticks(ind)
#self.axes.set_xticklabels(countrylabels, fontsize = 8)
self.axes.set_yticklabels(np.arange(0, max(summedX_Y), roundup(max(summedX_Y) / 10)))
self.axes.legend((p1[0], p2[0], p3[0], p4[0], p5[0]), ('Android', 'iOS', 'Windows', 'OS X', 'WebGL'))
self.draw_idle()
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
self.main_widget = QtGui.QWidget(MainWindow)
l = QtGui.QVBoxLayout(self.main_widget)
self.main_widget.setFocus()
MainWindow.setCentralWidget(self.main_widget)
self.UPCP = UsersPerCountryAndPlatformBar(self.main_widget, width = 10, height = 5, dpi = 100)
comboBox = QtGui.QComboBox(MainWindow)
comboBox.addItem('A_B')
comboBox.addItem('C_F')
comboBox.activated[str].connect(self.UPCP.updatefig)
l.addWidget(comboBox)
l.addWidget(self.UPCP)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Upvotes: 1