1

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.

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
goryef
  • 1,337
  • 3
  • 22
  • 37

1 Answers1

2

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)
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • First of all, thanks again for a perfect solution. Secondly, you are absolutely right about mine lack of knowledge of OOP. I am trying to feel the gaps. Your help is greatly appreciated. What would be the "best practice alternative" to accomplish what I am trying to do without using class ut_Screen1? – goryef Jul 26 '18 at 11:10
  • @goryef I do not know what you are trying to do. ;) – eyllanesc Jul 26 '18 at 11:11
  • You said that i should not use ut_Screen1 in the example that i provided. What is a best way to achieve the same functionality? – goryef Jul 26 '18 at 11:20
  • @goryef It's the one I showed in my answer. Do you understand why you should not use ut_Screen1? :) – eyllanesc Jul 26 '18 at 11:22
  • I understand your solution. It works perfectly for me. I thought you were saying that my whole approach with using class was wrong. – goryef Jul 26 '18 at 11:28
  • No, I did not say that your approach is incorrect, which indicates that your little knowledge of OOP generates these problems – eyllanesc Jul 26 '18 at 11:29
  • Got it. Thanks again! – goryef Jul 26 '18 at 11:31