Search code examples
pythonpyqtpyqt5qwidgetqstackedwidget

setCurrentIndex of QStackedWidget from outside its class


I am trying to set index of the StackedWidget from outside its class, but getting an error that object has no attribute. My code is below (I apologize for messed up indentations, it didn't paste properly):

import sys
from functools import partial
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5 import QtCore, QtWidgets, QtGui

class MainWindow(QMainWindow):
  def __init__(self, parent=None):

    QMainWindow.__init__(self, parent)
    self.setWindowTitle('Sample')
    self.resize(400,400)
    qr = self.frameGeometry()  
    cp = QDesktopWidget().availableGeometry().center()  
    qr.moveCenter(cp)  
    self.move(qr.topLeft())  

    self.central_widget = QStackedWidget()
    self.setCentralWidget(self.central_widget)
    self.start_screen = ut_Screen1()
    self.central_widget.addWidget(self.start_screen)
    self.central_widget.setCurrentWidget(self.start_screen)

class ut_Screen1(QWidget):
  def __init__ ( self ):
    super ( ut_Screen1, self ).__init__ ()

    nav_layout = QVBoxLayout()
    nav_layout.setSpacing(0)
    nav_layout.setContentsMargins(0,0,0,0)
    self.setLayout(nav_layout)
    self.frame_top = QFrame()
    self.frame_top.setMinimumSize(QtCore.QSize(400,100))
    self.frame_top.setMaximumSize(QtCore.QSize(400, 100))
    self.frame_top.setStyleSheet("background-color: rgb(100, 100, 255)")

    self.frame_top.stack_t1 = ut_Nav()
    self.frame_top.StackTop = QStackedWidget(self)
    self.frame_top.StackTop.addWidget(self.frame_top.stack_t1)
    layout_top_h = QVBoxLayout(self.frame_top)
    layout_top_h.addWidget(self.frame_top.StackTop)

    self.stack_b1 = ut_Bottom1()
    self.stack_b2 = ut_Bottom2()
    self.StackBot = QStackedWidget(self)
    self.StackBot.addWidget(self.stack_b1)
    self.StackBot.addWidget(self.stack_b2)

    nav_layout.addWidget(self.frame_top)
    nav_layout.addWidget(self.StackBot)


class ut_Bottom1(QWidget):
 def __init__(self):
    super(ut_Bottom1, self).__init__()

    selection_layout = QVBoxLayout()
    self.setLayout(selection_layout)
    self.frame_bot = QFrame()
    selection_layout.addWidget(self.frame_bot)
    self.lblBottom1 = QLabel ( 'Bottom1', self.frame_bot )
    self.lblBottom1.move ( 50, 50 )

class ut_Bottom2(QWidget):
  def __init__(self):
    super(ut_Bottom2, self).__init__()

    selection_layout = QVBoxLayout()
    self.setLayout(selection_layout)
    self.frame_bot = QFrame()
    selection_layout.addWidget(self.frame_bot)
    self.lblBottom1 = QLabel ( 'Bottom2', self.frame_bot )
    self.lblBottom1.move ( 50, 50 )

class ut_Nav(QWidget):
  clicked = pyqtSignal ()
   def __init__ ( self ):
    super ( ut_Nav, self ).__init__ ()

    nav_layout = QVBoxLayout()
    self.setLayout(nav_layout)
    self.frame_nav = QFrame()
    nav_layout.addWidget(self.frame_nav)
    b1 = QtWidgets.QPushButton ("Button1", self.frame_nav )
    b1.setObjectName ('Button1')
    b1.clicked.connect (partial(ut_ButtonClicked, b1.objectName()))

def ut_ButtonClicked(name):
    try:
     if name == "Button1":
        ut_Screen1.StackBot.setCurrentIndex(1)
    except Exception as e:
      print(e)

  if __name__ == '__main__':

app = QApplication(sys.argv)
myWindow = MainWindow()
myWindow.show ()
sys.exit(app.exec_())

When the button is clicked I am getting an error:

type object 'ut_Screen1' has no attribute 'StackBot'

Thanks in advance for any guidance.


Solution

  • I think your knowledge of OOP is poor so I recommend you review them.

    A class is an abstract concept, it only models the behavior of the objects that are created using the class, so that ut_Screen1 is not an object but the name of the class. Only objects can use the non-static methods of the class. In conclusion you should not use ut_Screen1.

    A possible solution is to access the object of the ut_Screen1 class called start_screen using the myWindow object of the MainWindow class:

    def ut_ButtonClicked(name):
        try:
            if name == "Button1":
                myWindow.start_screen.StackBot.setCurrentIndex(1)
        except Exception as e:
            print(e)