Question

I am working on a GUI with pyqt and pyqtgraph. In my application, I have 10 tabbed imageview, I was wondering how I could convert the following which takes too many lines with a more elegant pythonic way to address these objects. So instead of something like this:

img1 = pg.ImageView() 
img2 = pg.ImageView() 
img3 = pg.ImageView()
img4 = pg.ImageView()
img5 = pg.ImageView()
img6 = pg.ImageView()
img7 = pg.ImageView()
img8 = pg.ImageView()
img9 = pg.ImageView()
img10 = pg.ImageView()


tab_widget = QtGui.QTabWidget() 
tab1 = QtGui.QWidget() 
tab2 = QtGui.QWidget() 
tab3 = QtGui.QWidget() 
tab4 = QtGui.QWidget() 
tab5 = QtGui.QWidget() 
tab6 = QtGui.QWidget() 
tab7 = QtGui.QWidget() 
tab8 = QtGui.QWidget() 
tab9 = QtGui.QWidget() 
tab10 = QtGui.QWidget() 

p1_vertical = QtGui.QVBoxLayout(tab1) 
p2_vertical = QtGui.QVBoxLayout(tab2) 
p3_vertical = QtGui.QVBoxLayout(tab3) 
p4_vertical = QtGui.QVBoxLayout(tab4) 
p5_vertical = QtGui.QVBoxLayout(tab5) 
p6_vertical = QtGui.QVBoxLayout(tab6) 
p7_vertical = QtGui.QVBoxLayout(tab7) 
p8_vertical = QtGui.QVBoxLayout(tab8) 
p9_vertical = QtGui.QVBoxLayout(tab9) 
p10_vertical = QtGui.QVBoxLayout(tab10) 

tab_widget.addTab(tab1, "Grid 1") 
tab_widget.addTab(tab2, "Grid 2")
tab_widget.addTab(tab3, "Grid 3") 
tab_widget.addTab(tab4, "Grid 4") 
tab_widget.addTab(tab5, "Grid 5") 
tab_widget.addTab(tab6, "Grid 6") 
tab_widget.addTab(tab7, "Grid 7") 
tab_widget.addTab(tab8, "Grid 8") 
tab_widget.addTab(tab9, "Grid 9") 
tab_widget.addTab(tab10, "Grid 10")  

button1 = QtGui.QPushButton("button1") 
p1_vertical.addWidget(img1)
p2_vertical.addWidget(img2) 
p3_vertical.addWidget(img3) 
p4_vertical.addWidget(img4) 
p5_vertical.addWidget(img5) 
p6_vertical.addWidget(img6) 
p7_vertical.addWidget(img7) 
p8_vertical.addWidget(img8) 
p9_vertical.addWidget(img9)  
p10_vertical.addWidget(img10) 

Perhaps something like this:

d = {} 
for i in range(1,10):
    d["img{0}".format(i)]= pg.ImageView()
Was it helpful?

Solution

Create a custom widget class that does all the setup in its __init__:

class ImageViewTab(QtGui.QWidget):
    def __init__(self, parent=None)
        super(ImageViewTab, self).__init__(parent)
        layout = QtGui.QVBoxLayout(self)
        self.imageview = pg.ImageView(self)
        layout.addWidget(self.imageview)

then add instances of your widget to the tab-widget in a loop:

    tab_widget = QtGui.QTabWidget()
    for index in range(1, 11):
        widget = ImageViewTab(tab_widget)
        tab_widget.addTab(widget, 'Grid %s' % index)

After all the setup is done, you can use the QTabWidget.widget method access the widgets by index:

    widget = tab_widget.widget(4)
    widget.imageview.setImage(img)

The main benefit of this approach is that it is very flexible. You can add specialized methods to your custom class, create and emit custom signals, add slots, etc.

OTHER TIPS

imgs = [pg.ImageView() for _ in range(10)]

tab_widget = QtGui.QTabWidget()

tabs = [QtGui.QWidget() for _ in range(10)]

p_verticals = [QtGui.QVBoxLayout(tab) for tab in tabs]

for n, tab in enumerate(tabs):
    tab_widget.addTab(tab, "Grid {0}".format(n+1))

button1 = QtGui.QPushButton("button1")

for p, img in zip(p_verticals, imgs):
    p.addWidget(img)

I don't see why you would want to use a dictionary, lists are fine.

You can create all your variables in lists:

    imgs = [pg.ImageView() for _ in range(10)]
    tab_widget = QtGui.QTabWidget() 
    tabs = [QtGui.QWidget() for _ in range(10)]
    p_verticals = [QtGui.QVBoxLayout(tabs[i]) for i in range(10)]
    for i in range(10):
        tab_widget.addTab(tab[i], "Grid %d" % i+1) 
        p_verticals[i].addWidget(imgs[i])
    button1 = QtGui.QPushButton("button1") 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top