How to access variables in other classes - python

In Functions class, I would like to access the variable of the Frame class.
Please tell me if there is any way.
class Functions():
def changeText():
...
...
I want to change the 'text' in the Frame class
ex )Frame.text.SetFont('change text')
GUI element
class Frame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, ....)
....
....
self.text = wx.StaticText(panel, .....)

You can do this by sending an instance of the class to the function:
class myClass(object):
def __init__(self, text):
self.text = text
def changeText(input):
input.text = "world"
example = myClass("hello")
changeText(example)

You will have to tell your objects what to work on. Out of thin air your Functions instance will not know (how should it?) what Frame should be. You could make Frame a global, but I do not think that is a good idea (it will break if you want to work with more than one frame instance). So you would write:
class Functors:
...
def set_text(txt_frame, the_text):
"""txt_frame has to be a :class:`my_txt_frm` instance with ``self.text`` being a ``StaticText`` instance."""
txt_frame.text.SetLabel(the_text)
class my_txt_frm(wx.Frame): # do not name the derived class Frame to make more clear it is derived!
def __init__(# ...
...
self.text = wx.StaticText(#...
So now comes the interesting part: how to tie the parts together? You have to have something like that somewhere in your code:
funct = Functors() # the class which know how to do things on our GUI elements
frm = my_txt_frm(#...
Some lines later...
funct.set_text(frm, 'thenewtext')
So for your app which has the bigger picture it is necessary to keep references to the building blocks to be able to tie them together later.
An orderly way to tie things together is called MVC (see a great example in the wxPython wiki). Even if you do not want to model your app after this paradigm, you can learn from it how to reason about separation of concerns.

Related

Can you transfer attributes from one class instance to another without using inheritance?

I'm building a Tkinter app and it is currently all one big class. I'm trying to split it into smaller pieces to make it easier to work on. The problem is some of the smaller pieces contain elements that are referenced elsewhere in the larger app.
editing to add more code:
OK so say I am using init_library to make a big complicated frame which then becomes self.library.
class GUI:
def __init__(self):
self.root = tk.Tk()
self.init_library()
self.root.mainloop()
return
def init_library(self):
self.library = tk.Frame(self.root)
[...]
self.library_var = tk.StringVar("HEY")
self.library_label = tk.Label(self.library, textvariable=self.library_var)
[...]
def action(self, new_text):
[...]
self.library_var.set(new_text)
[...]
So assume that init_library is large and I would like to put it in a different file to make life easier. Now instead of a class function, I just instantiate LibraryClass.
from pieces import LibraryClass
class App:
def __init__(self):
self.root = tk.Tk()
self.library = LibraryClass()
self.root.mainloop()
return
The problem is library_var is now a child of self.library instead of App. So we would have to change action.
def action(self, new_text):
[...]
self.library.library_var.set(new_text)
[...]
Is there a way to directly assign the LibraryClass functions and attributes of self.library to App?
(I know it seems like a small thing but it would really make my life easier)

Understanding Tkinter.Frame

I have a problem about analyzing these lines of code, if you want to view the whole code I can post it.
Can you guys please explain whats going on here?
I'm planning to create a database program with tkinter and sqlite, I have a windows PC.
I didnt write the code I just want to study it.
class meh(Tkinter.Frame):
def __init__(self, parent):
Tkinter.Frame.__init__(self, parent)
self.parent=parent
self.initialize_user_interface()
Whats going on here?
def __init__(self, parent):
Tkinter.Frame.__init__(self, parent)
Python supports object-oriented programming. One of the core concepts in OOP is inheritance, which means that a class can "inherit" methods from another class. For instance
class Animal:
def __init__(self, name): # The __init__ function is called when an object is
self.name = name # instantiated. That's called a "constructor"
print('Created ' + name)
def make_sound(self):
print("...")
def die(self):
print(self.name + ' died.')
class Cat(Animal): # The class in the parenthesis is the superclass.
def make_sound(self): # A cat makes a different sound from any other animal,
print("Meow") # so we give it its own make_sound method. But it dies
# the same as any other animal, so it will inherit
# the die method from the superclass.
Now when we try this code:
>>> fluffy = Animal('Fluffy')
Created Fluffy
>>> fluffy.make_sound()
...
>>> fluffy.die()
Fluffy died.
>>> kitty = Cat("Kitty")
Created Kitty
>>> kitty.make_sound()
Meow
>>> kitty.die()
Kitty died.
So now, let's look at the code you gave:
class meh(Tkinter.Frame):
This line creates a class that inherits from Tkinter.Frame. That means that it should be able to do anything that a Frame can do, which will probably be things like containing UI elements.
def __init__(self, parent):
This is a constructor that gets called when you create a new meh. It takes parent as a parameter. I'd check the documentation, but in UI development, that often means interface element that this one should appear inside. For instance, the parent might be a window or another frame.
Tkinter.Frame.__init__(self, parent)
This is calling the __init__ method of the class Tkinter.Frame. This basically means that instead of defining something to do instead of what Tkinter.Frame does in its constructor, they're defining things to do in addition to Tkinter.Frame.__init__.

How to refactor those basic classes (PyQt5)

I am learning PyQt5 and I tried to create a extended widgets.
I am also learning OOP so I lack experience for this project.
My final goal is to have master widgets that can disable/enable some slave widgets.
So far I need check and radio buttons.
So I tried to create an abstract class that contains the extended behavior of the widgets (the management of the state of the slaves widgets):
class QDisablingWidget():
__metaclass__ = ABCMeta
def __init__(self):
self.slaveWidgets = []
self.slaveStateWhenMasterIsEnabled = {}
def addSlaveWidget(self, slaveWidget, isEnabledWhenMasterIsEnabled=True):
[...]
def updateSlaveStatus(self):
[...]
Then I create my extended widget classes:
class QDisablingCheckBox(QtWidgets.QCheckBox, QDisablingWidget):
def __init__(self, text=None, parent=None, isInMutexGroup=False):
super(QtWidgets.QCheckBox, self).__init__()
super(QDisablingWidget, self).__init__()
if text:
self.setText(text)
if parent:
self.setParent(parent)
self.isInMutexGroup = isInMutexGroup
# Click signal handling
self.stateChanged.connect(self.updateSlaveStatus)
class QDisablingRadioButton(QtWidgets.QRadioButton, QDisablingWidget):
def __init__(self, text=None, parent=None, isInMutexGroup=False):
super(QtWidgets.QRadioButton, self).__init__()
super(QDisablingWidget, self).__init__()
if text:
self.setText(text)
if parent:
self.setParent(parent)
self.isInMutexGroup = isInMutexGroup
# Click signal handling
self.toggled.connect(self.updateSlaveStatus)
You can already see the problem:
I need to connect my self.updateSlaveStatus to the correct signals (stateChanged and toggled) so I added it in the constructor of the derived classes.
Recently I also added the isInMutexGroup argument for some implementation reasons and I realize that I am duplicating the code in both derived classes...
It is the first time I try to use OOP "for real" (first attempt of multiple inheritance and abstract class), so even if I know I am breaking the beauty of the OOP concept, I don't know what to do to get a nice class hierarchy...
So basically, I am looking for a solution on this example. But I am also looking for guidelines, general advice, tutorials, etc. Actually anything that could help me!
Thank you for your help.
Even if I got a downvote for that question, I think some beginners could be interested by the solution I found:
I have my extension abstract class like that:
class QDisablingWidget(QtCore.QObject):
__metaclass__ = ABCMeta
def __init__(self, isInMutexGroup=False, **kwds):
[...]
Then I can derive class like that:
class QDisablingCheckBox(QtWidgets.QCheckBox, QDisablingWidget):
def __init__(self, **kwds):
super().__init__(**kwds)
# On click signal handling
self.stateChanged.connect(self.updateSlaveStatus)
and
class QDisablingRadioButton(QtWidgets.QRadioButton, QDisablingWidget):
def __init__(self, **kwds):
super().__init__(**kwds)
# On click signal handling
self.toggled.connect(self.updateSlaveStatus)
Finally, when I use the classes I need to create object like that:
disablingRadioBut = QWidgets.QDisablingRadioButton(text="My button",
parent=self,
isInMutexGroup=True)
I.e I must use keywords explicitly so that each constructors will eat the kewords the use/know.
Thanks to this approach I have maximum reusability of my extension class.
I got this solution here:
http://pyqt.sourceforge.net/Docs/PyQt5/multiinheritance.html
And more details here:
http://rhettinger.wordpress.com/2011/05/26/super-considered-super/
A very nice article!

Create frame class in Tkinter Gui

I'm working on a Gui and I'd like to know how to create a class that would implement frame.
e.g.
class WindowContent(Tkinter.?)
""" This class would create a frame for my program window """
class App(Tkinter.Tk):
""" main window constructor """
def __init__(self):
Tkinter.Tk.__init__(self)
program_window = WindowContent ?
self.config(window = window_content) ?
rgds,
I found the answer :
class WindowProgram(Tkinter.Frame)
""" This class creates a frame for my program window """
def __init__(self, parent):
Tkinter.Frame.__init__(self, parent)
class App(Tkinter.Tk):
""" application constructor """
def __init__(self):
Tkinter.Tk.__init__(self)
self.window_program = Window_Program(self)
Why do you want a class that creates several frames? Creating one class that creates multiple frames is not a very good solution. You don't need a single class for that.
Either create separate classes for each frame, or just create methods in your app to create each frame. I prefer the latter, but if you want a frame that can be used in multiple contexts it sometimes makes sense to create a class.
When I do a GUI I structure my code like this:
class App(Tkinter.Tk):
def __init__(self):
Tkinter.Tk__init__(self)
self.menubar = self.makeMenubar(...)
self.frame1 = self.makeFrame1(...)
self.frame2 = self.makeFrame2(...)
self.configure(menu=self.menubar)
self.frame1.grid(...)
self.frame2.grid(...)
In this way, each major section gets its own method to hide the details of widget creation. You could, of course, have each frame be a custom object but usually that's unnecessary.

Problem with Classes in Python

Ok guys, I'm really new at python (and programming itself) so sorry for my ignorance, but I really needed to ask this.
So im doing a wxPython project where I added several tabs for a notebook (each tab of the notebook = a class) and there is one tab where I added a checkbox (in a tab, lets call it for example Tab1), and what I want is that when someone checks it, a button that exists in other tab (class called for example tab2) gets hidden where previously it was being shown.
Well I see that it isn't hard to accomplish this, but my problem is the classes (tab1 and tab2, in this example). I've been trying to figure it out by searching but I guess im not searching hard enough because I just can't get it right. If they were in the same class I wouldn't have a problem, but as they are in different classes, im having a huge struggle with this.
Hope someone can help me, and sorry for my ignorance once again.
EDIT: Sorry guys wasn't being shown/hidden, but rather being enabled/disabled.
class Tab2(wx.Panel):
def __init__(self, parent):
.....
self.jaddbutton = wx.Button(self,-1, label ="Button", size = (160,24))
self.jaddbutton.Bind(wx.EVT_BUTTON, self.jaddbuttonclick, self.jaddbutton)
def jaddbuttonclick(self, event):
....
class Tab1(wx.Panel):
def __init__(self, parent):
self.jdcheck = wx.CheckBox(self, -1, 'Disable')
self.jdcheck.Bind(wx.EVT_CHECKBOX, self.checkoptions, self.jdcheck)
def checkoptions(self,event):
checkboxval = self.jdcheck.GetValue()
if checkboxval == False:
self.jaddbutton.Disable() # This is what I want to do but it is on the other class
else:
self.jaddbutton.Enable() # Same as above
class TextFrame(wx.Frame):
def __init__(self):
p = wx.Panel(self)
self.nb = wx.Notebook(p, size = (750, 332))
#Tabs
tab1 = Tab1(self.nb)
tab2 = Tab2(self.nb)
self.nb.AddPage(tab1, "ssomething")
self.nb.AddPage(tab2, "somethingr")
This sounds more like a wxpython question than a classes question. Normally, in python, tab1 would need a handle to tab2 in order to hide the button in tab2. Or it would need a handle to some shared resource, like a parent class or shared model class, that would allow tab1 to affect settings in tab2 (like the hiding of a button). PyQt provides an event system to allow communication between classes which may not necessarily contain handles to each other. What is the common "accepted" way to communicate in wxpython?
Here is a fairly abstract example of the shared parent solution.
class Parent(object):
def create_tabs():
self.tab1 = Tab1(self)
self.tab2 = Tab2(self)
def hide_tab2_button():
self.tab2.hide_button()
class Tab1(object):
def __init__(self, parent):
self.parent = parent
def on_checkbox_checked(self):
self.parent.hide_tab2_button()
class Tab2(object):
def __init__(self, parent):
self.parent = parent
def hide_button(self):
self.button.hide() # Or whatever the wxpython command is to hide a button.
In the tabs' __init__, save the parent reference (the notebook):
class Tab1(wx.Panel):
def __init__(self, parent):
self.parent = parent
...etc, etc...
Then, self.parent.GetPage(x) lets you access the x-th page (i.e., tab) of the notebook from any other page (tab). So instead of self.jaddbutton.Disable() etc, you'd be using, e.g.:
othertab = self.parent.GetPage(1)
othertab.jaddbutton.Disable()
and so forth.

Categories