1

I'm facing a problem that I cannot solve, even if it shouldn't be difficult.

I have a QListWidget with 5 items (so 5 rows) and 2 related QStackedWidgets. The first made of 3 pages: the first page of it contains another nested QStackedWidgets with 2 pages. So a total pf 5 pages.

A small gif to have an idea:

enter image description here

Now what I'm trying to do is to create a function that links the QListWidget and the 2 QStackedWidget. I would like that the item 1 and 2 of the QListWidget were linked only to the first page of the parent QStackedWidget and the first and second page of the nested QStackedWidget while item 3, 4 and 5 were linked only to the parent QStackedWidget (2nd, 3rd and 4th page).

The piece of code I wrote is the following:

# connect the listWidget currentRow signal to a custom function
self.listWidget.currentRowChanged.connect(self.updateStacked)

def updateStacked(self):

    idx = self.listWidget.currentRow()
    if idx is 0 or idx is 1:
        self.stackedPlotWidget.setCurrentIndex(0)
        self.stackedNestedWidget.setCurrentIndex(1)

    else:
        self.stackedPlotWidget.setCurrentIndex(idx - 1)

but something is not working correctly: for QlistWidget rows 0 and 1 works nice but it seems not taking into account the else statement.

Some suggestions?

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
matteo
  • 4,683
  • 9
  • 41
  • 77
  • I cannot see any good reason for having a stack-widget nested inside another stack-widget. It just complicates things unnecessarily. Put all the pages in one stack-widget, so there's a simple one-to-one relationship between list-widget items and pages. – ekhumoro Nov 24 '17 at 15:22
  • That's because I want to have some buttons (the same ones) for the nested stacked-widget. To do that I thought to create the parent stacked widget, put there the buttons and create the nested stacked widget. I don't know if this is a good idea, but it could work. If you have some other ideas, more than welcome ;) – matteo Nov 25 '17 at 17:55
  • I made a small gif to have a better idea – matteo Nov 26 '17 at 11:17

1 Answers1

1

The correct way to write the slot is like this:

self.listWidget.currentRowChanged.connect(self.updateStacked)

def updateStacked(self, row):
    if 0 <= row <= 1:
        self.stackedPlotWidget.setCurrentIndex(0)
        self.stackedNestedWidget.setCurrentIndex(row)
    elif row > 1:
        self.stackedPlotWidget.setCurrentIndex(row - 1)

UPDATE:

Below is a complete example showing how to handle all the signals. Note that the spin-box is only there to mimic setting the indexes of the stack-widgets programmatically.

import sys
from PyQt4 import QtCore, QtGui

class Window(QtGui.QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.stack1 = QtGui.QStackedWidget()
        self.stack2 = QtGui.QStackedWidget()
        for text in 'ONE', 'TWO':
            page = QtGui.QWidget(self.stack2)
            layout = QtGui.QVBoxLayout(page)
            layout.addWidget(QtGui.QLabel(text))
            self.stack2.addWidget(page)
        page = QtGui.QWidget(self.stack1)
        layout = QtGui.QVBoxLayout(page)
        layout.addWidget(QtGui.QLabel('TOP'))
        layout.addWidget(self.stack2)
        layout.addWidget(QtGui.QLabel('BOTTOM'))
        self.stack1.addWidget(page)
        for text in 'THREE', 'FOUR', 'FIVE':
            page = QtGui.QWidget(self.stack1)
            layout = QtGui.QVBoxLayout(page)
            layout.addWidget(QtGui.QLabel(text))
            self.stack1.addWidget(page)
        self.listWidget = QtGui.QListWidget()
        self.listWidget.addItems('ONE TWO THREE FOUR FIVE'.split())
        self.listWidget.currentRowChanged.connect(self.updateStacked)
        self.spin = QtGui.QSpinBox()
        self.spin.setRange(0, 4)
        self.spin.valueChanged.connect(self.updateStacked)
        layout = QtGui.QHBoxLayout(self)
        layout.addWidget(self.listWidget)
        layout.addWidget(self.stack1)
        layout.addWidget(self.spin)
        self.stack1.currentChanged.connect(self.updateList)
        self.stack2.currentChanged.connect(self.updateList)

    def updateStacked(self, row):
        if 0 <= row <= 1:
            self.stack1.setCurrentIndex(0)
            self.stack2.setCurrentIndex(row)
        elif row > 1:
            self.stack1.setCurrentIndex(row - 1)

    def updateList(self, index):
        self.listWidget.blockSignals(True)
        if self.sender() is self.stack1:
            index += (1 if index >= 1 else self.stack2.currentIndex())
        self.listWidget.setCurrentRow(index)
        self.listWidget.blockSignals(False)

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 50, 300, 50)
    window.show()
    sys.exit(app.exec_())
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • nope it does not work. For the nested widgets no problem, but when clicking on the 3rd row nothing changes. I added 2 prints statements in your function and it seems that when `row > 1`, for a millisecond the correct index changes but afterwards it goes back in `if 0 <= row <= 1`. – matteo Nov 27 '17 at 07:02
  • @matteo. It works perfectly for me. All the pages are shown exactly as they should be. You must be doing something else wrong - I would guess that it has something to do with your [other question](https://stackoverflow.com/q/47453406/984421), where you are also trying to re-set the list index when the stack widgets change. I have updated my question with an example that shows how to handle all the signals correctly. – ekhumoro Nov 27 '17 at 16:20
  • ehehe you get it ;) I wanted to mix too many things. Your solution, after turning off the piece of code in the other question, is solved. Many many thanks! – matteo Nov 28 '17 at 08:03