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.
- 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'
- 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()
1 Answer 1
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.
-
Thanks. Yes, recursively importing each class is a bad idea and sending the whole class to another class seems unnecessary.John– John2024年05月21日 20:57:01 +00:00Commented May 21, 2024 at 20:57
x = One()
) and create an attribute for it:x.text = 'test'
.text
is a member of the instance named "x", butOne
was untouched, and therefore has notext
attribute. What you do in the__init__
is the same, whereself
refers to the actual instance (remember that "self" is just a name convention):x.text = ...
is the same asself.text = ...
within any of its methods.