0

After looking through many posts of class variables and instance variables I am not understanding how to share variables among classes.

#!/usr/bin/python3
from PyQt5.QtWidgets import (QApplication)
import sys
class One():
 def __init__(self, myTextString, parent=None):
 self.mytext = myTextString
 self.printtxt()
 Main.txt = 'another string'
 self.txt2 = 'a third string'
 def printtxt(self):
 print('One',self.mytext)
class Two():
 def __init__(self, parent=None):
 self.printtxt()
 def printtxt(self):
 print('Two',One.txt) # Attribute Error
 print('Two',One.txt2) # Attribute Error
class Main():
 def __init__(self, parent = None):
 self.txt = 'a string of text'
 self.w = One(self.txt)
 self.w1 = Two()
 print(self.txt) # not changed by One
if __name__ == '__main__':
 app = QApplication(sys.argv)
 ex = Main()
 sys.exit(app.exec_())

In the above code the Main class initiates class One and class Two. While I can send the value of self.txt to the initiated class One, there are two problems I am having.

  1. When I try to print One's variables in class Two's printtxt I get attribute errors:

AttributeError: type object 'One' has no attribute 'mytext'

AttributeError: type object 'One' has no attribute 'txt2'

  1. When I try and change Main's txt variable in One, it is not changed

I would like to share a value created in any particular class with all the other classes that are created (in other words 'global' variables up to a point).

The controller concept in Bryan Oakley's Tkinter example (see Switch between two frames in tkinter? and How to get variable data from a class?) is close I think, but if anyone can answer or point me to posts that explain this simply, I'd be grateful. Thank you for any help.

Subsequently, I looked at Bryan Oakley's controller concept againm. My project involves merging 4 of my working programs together into one and have these different parts interact, without much re-coding, but the controller concept seems the simplest and best solution. So this code, based on Oakley's code, might help someone in the future:

#!/usr/bin/python3
class SampleApp():
 def __init__(self, *args, **kwargs):
 self.app_data = 'One'
 for F in (PageOne, PageTwo):
 frame = F(controller=self)
class PageOne():
 def __init__(self, controller):
 self.controller = controller
 value = self.controller.app_data
 print('Page1', value)
class PageTwo():
 def __init__(self, controller):
 self.controller = controller
 self.controller.app_data='Two'
 value = self.controller.app_data
 print('Page2',value)
SampleApp()
asked May 9, 2024 at 17:53
4
  • 1
    There's no necessity to complicate things with multiple levels. Your instance constructor creates a member for that specific instance, not for the class. A simple example is to create an instance (x = One()) and create an attribute for it: x.text = 'test'. text is a member of the instance named "x", but One was untouched, and therefore has no text attribute. What you do in the __init__ is the same, where self refers to the actual instance (remember that "self" is just a name convention): x.text = ... is the same as self.text = ... within any of its methods. Commented May 9, 2024 at 18:30
  • Now, what you're asking is a "global" variable, but those are normally frowned upon and in OOP they're generally discouraged because can lead to unexpected behavior and bugs difficult to track, and are often symptom of bad implementation. Right now your example is quite abstract, can you clarify what you actually need to do, what that variable should be, how/when should it changed, and why it has to be arbitrarily shared among other classes? Commented May 9, 2024 at 18:33
  • I have a PyQt program very similar to Bryan Oakley's example, which is in in Tkinter, with each stackedWidget being defined by a particular class. Each class has the gui and it's underlying code. I want to share some of the values of the variables in any particular class (or stackedWidget) with the other classes. I was using the term 'global' as a description. I should have used maybe universal or world-wide, perhaps! Thanks a lot! Commented May 9, 2024 at 19:45
  • This answer has been useful too:stackoverflow.com/questions/805066/… Commented Jun 1, 2024 at 5:02

1 Answer 1

0

It seems like you haven't learned the basics of python, before getting started with pyqt I would recommend learning the basics of python with a video tutorial before starting to create applications with pyqt.

First you should know that python you shouldn't have each classes importing each class as this will create a loop error, instead you want to have a main class that controls the data flow ( the main.py class ).

If you want to make changes to self.txt inside of class one and it changes the self.txt in main class then you have to return the value. Remember this is just python, there is other ways to update values with PyQt signals, but I wouldn't worry about it at the moment as its mainly to communicate between GUI and non GUI elements. Instead of having class Two, trying to access class One, have it so that the Main class controls the data and sends the data to the class two, (You can also send an instance of the class to access the whole class and its variables).

This way it just sends the self.txt1 and self.txt2 from class one:

#!/usr/bin/python3
from PyQt5.QtWidgets import QApplication
import sys
class One():
 def __init__(self):
 self.txt1 = "Hello World"
 self.txt2 = "Hello World2"
 def change_text(self, text):
 self.txt = text
 self.txt = 'changed text'
 print('One: ',self.txt)
 return self.txt # Returns the new variable
class Two():
 def __init__(self, text1, text2):
 print('Two: ',text1) 
 print('Two: ',text2) 
class Main():
 def __init__(self):
 self.txt = 'a string of text'
 self.w = One()
 self.w1 = Two(self.w.txt1, self.w.txt2)
 self.txt = self.w.change_text(self.txt) # self.txt grabs the returned variable
 print("Main: ", self.txt) 
if __name__ == '__main__':
 app = QApplication(sys.argv)
 ex = Main()
 sys.exit(app.exec_())

If you want to send the whole class and then look for specific variables:

#!/usr/bin/python3
from PyQt5.QtWidgets import QApplication
import sys
class One():
 def __init__(self):
 self.txt1 = "Hello World"
 self.txt2 = "Hello World2"
 def change_text(self, text):
 self.txt = text
 self.txt = 'changed text'
 print('One: ',self.txt)
 return self.txt # Returns the new variable
class Two():
 def __init__(self, class_one):
 print('Two: ',class_one.txt1) 
 print('Two: ',class_one.txt2) 
class Main():
 def __init__(self):
 self.txt = 'a string of text'
 self.w = One()
 self.w1 = Two(self.w)
 self.txt = self.w.change_text(self.txt) # self.txt grabs the returned variable
 print("Main: ", self.txt) 
if __name__ == '__main__':
 app = QApplication(sys.argv)
 ex = Main()
 sys.exit(app.exec_())

As I've said at the start I would recommend learning about the basics of python before getting into PyQt as it requires you to know at least the basic to create an application.

answered May 9, 2024 at 18:50
1
  • Thanks. Yes, recursively importing each class is a bad idea and sending the whole class to another class seems unnecessary. Commented May 21, 2024 at 20:57

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.