accessing UI elements from another class in python - python

Example
function.py
class testClass(object):
def functionA(self):
#doSomething
self.Qlabel.clear()
main.py
class mainClass(object):
def __init__(self, parent = #something):
#initialize something
super(mainClass, self).__init__(parent)
self.setupUi(self)
self.Qlabel.clicked.connect(self.testFunc)
def testFunc(self):
import function as FT
FT.testClass().functionA(self)
I tried connecting my PyQt function.py to main.py. It keeps giving me this TypeError: functionA() takes exactly 1 argument (2 given).
If I take away the 'self' in so that it's FT.testClass().functionA(), then I get AttributeError: 'testClass' object has no attribute 'Qlabel'
I saw in PyQt : accessing elements from outside the class that it works with just using obj but not with classes.
I would like to understand how to fix this and also why my previous method doesn't work. Any help would be appreciated!

I have managed to get it working. The problem was basically in function.py, I was using self.Qlabel.clear() instead of object.Qlabel.clear(),
This is the working code.
function.py
class testClass(object):
def functionA(self, object):
#doSomething
object.Qlabel.clear()
main.py
class mainClass(object):
def __init__(self, parent = something):
#initialize something
super(mainClass, self).__init__(parent)
self.setupUi(self)
self.Qlabel.clicked.connect(self.testFunc)
def testFunc(self):
import function as FT
FT.testClass().functionA(self)

In the definition of functionA make one more Entry.
For e.g.
def functionA(self, mainClassObj):
#doSomething
self.Qlabel.clear()
Cause of the error is you're calling testclass function with one extra argument.Whereas you define it with one argument.
Note: You have to initiate Qlabel :
def functionA(self, mainClassObj):
#doSomething
from PyQt5.QtWidgets import QLabel
Qlabel().clear()
This should work for you.

Related

Passing Generic type to inner class

In this code, I want to pass the type T to the inner class Emitter.
T = TypeVar('T')
class MySignal(Generic[T]):
class Emitter(QtCore.QObject,Generic[T]):
signal = Signal(T)
def __init__(self):
super(MySignal.Emitter, self).__init__()
def __init__(self):
self.emitter = MySignal.Emitter[T]()
def emit(self,*args,**kw):
self.emitter.signal.emit(*args,**kw)
It doesn't behave as expected.
If I do
minMaxChanged=MySignal[tuple]()
Then minMaxChanged.emitter.__orig_class__.__args__[0] looks like T~ instead of tuple. The minMaxChanged class itself is as expected.
Generally, specifying Signal(typ) results in typ being the argument type expected to be passed to emit function. Consequently, in this case, Signal is called as if it were called without args, and calling emit with 1 argument fails since it expects no args.
I also expected the code
T = TypeVar('T')
class MySignal(Generic[T]):
class Emitter(QtCore.QObject):
signal = Signal(T)
def __init__(self):
super(MySignal.Emitter, self).__init__()
def __init__(self):
self.emitter = MySignal.Emitter()
def emit(self,*args,**kw):
self.emitter.signal.emit(*args,**kw)
to work. However, the exact same issue remains.
Update
Notice that this is not a redundant complication. This class (partially brought here) is meant to wrap a Qt Signal which can only be omitted from class that is a Qt class. It meant to provide a generic signal wrapper. See how to emit signal from a non PyQt class?
Trying double inheritance MySignal(QtCore.QObject, Generic[T]) resulted in a c++ style crash.
#ekhumu suggestion indeed works. I hoped for something prettier.
class MySignal:
def __init__(self,typ):
Emitter = type('Emitter', (QtCore.QObject,), {'signal': Signal(typ)})
self.emitter = Emitter()
def emit(self,*args,**kw):
self.emitter.signal.emit(*args,**kw)
def connect(self, slot):
self.emitter.signal.connect(slot)

Python Multiple inheritance Error:object ha s no attribute

I am new to python and asking very basic question. I am trying to understand multiple inheritance. I have two parent classes i.e Speciy and Living and one child class Bird but when i run the following program, i get error 'Bird' object has no attribute '_Living__house'.Please tell me what i am doing wrong
But when i use single inheritance i.e class Bird(Speciy) or class Bird(Living)it works fine. So only the error comes when i use multiple inheritence
class Speciy:
def __init__(self,legs=4,colour="White"):
self.__legs=legs
self.__colour=colour
def get_legs(self):
return self.__legs
def set_legs(self,legs):
self.__legs=legs
def get_colour(self):
return self.__colour
def set_colour(self,colour):
self.__colour=colour
class Living:
def __init__(self,house="city"):
self.__house=house
def get_house(self):
return self.__house
def set_house(self,house):
self.__house=house
class Bird(Speciy,Living):
def __init__(self,wings=2):
super().__init__()
super().__init__()
self.__wings=wings
def get_wings(self):
return self.__wings
def set_wings(self,wings):
self.__wings=wings
b1=Bird(4)
print(b1.get_wings())
b1.set_colour("Green")
print(b1.get_colour())
print(b1.get_house())
I have solved the issue my self using
Speciy.__init__(self,legs,colour)
Living.__init__(self,house)

Python heritage

I have a question that sounds perhaps strange, but I want to call a function of my parent class inside my children.
I use tkinter and MyChild allready inherrit from a frame.
ex:
class MyParent:
def __init__(self):
do_things()
def myfunction(self):
child_class = MyChild()
def call_me(self):
print("I'm here!")
class MyChild:
def __init__(self):
do_things()
def my_call(self):
#here call the call_me function
here I want that when in MyChild class the my_call function is called, it calls the call_me function of the MyParent class.
I just want to know if and how it is possible to call call_me in the my_call function like Myparent.call_me()
Based on the code in your question, your child will have to be told what its parent is. This is normally done when you create the child. The child can keep a reference, so that it can be used whenever it needs to call a method on the parent.
Example:
class MyParent:
def myfunction(self):
child_class = MyChild(parent=self)
def call_me(self):
print("I'm here!")
class MyChild:
def __init__(self, parent):
self.parent = parent
do_things()
def my_call(self):
self.parent.call_me()

PyQt Code Splitting - Design Vs Functionality

Am struggling to comprehend how to split code in (Py)Qt. The aim is to have the design & navigation tabs in QMainWindow, each tab triggering code in other files. So far it only launches with the ActionClass in the same document / putting in an external document causes 'app not defined' when clicking the tab. The below works without errors, but is clunky.
class Main(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.u = Ui_MainWindow()
self.u.setupUi(self)
self.u.tabs.currentChanged.connect(self.TabsChanged)
def TabsChanged(self, i):
if i == self.u.tabs.indexOf(self.u.tabFirst): ActionClass.__init__
class ActionClass(Main):
def __init__(self):
app.u.lineEdit.setText("test")
app = Main()
app.show()
sys.exit(app.exec_())
The examples I keep seeing have all code in one document. Is there another way to do this e.g. where the ActionClass is in another file/writing u.lineEdit.setText instead of app.u.lineEdit.setText. It seems inheritance & an instance of Main can't be accessed from the ActionClasses doc, so I can't see how they would communicate back to the Main?
Much appreciated
As suggest #M4rtini you can separate your code into python modules. And then import them (use them) in your main module.
For instance the code you posted can be separated in to files:
# actions_class.py
class ActionClass(Main):
def __init__(self):
app.u.lineEdit.setText("test")
and
# main.py
from action_class import ActionClass # This line no need much explanation ;)
class Main(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.u = Ui_MainWindow()
self.u.setupUi(self)
self.u.tabs.currentChanged.connect(self.TabsChanged)
def TabsChanged(self, i):
if i == self.u.tabs.indexOf(self.u.tabFirst): ActionClass.__init__
app = Main()
app.show()
sys.exit(app.exec_())
In order to understand how import works see the link I left you above.
More explanation
Lest's see:
The correct way of executin code inside a __init__ method is creating an instance. See the example below.
class A:
def __init__(self):
print("Executing A.__init__")
print("Doing things wrong")
A.__init__ # This don't print enything
print("Doing things well")
A() # This works as expected.
So, you line reads:
if i == self.u.tabs.indexOf(self.u.tabFirst): ActionClass.__init__
and should reads:
if i == self.u.tabs.indexOf(self.u.tabFirst): ActionClass()
On the other hand, is a bad practice put code that's not for initialize the instance inside the __init__ methods.
If you don't need the instance but yet you want to store the functions inside a class (something like a c++ namespace) you creating
use #staticmethod decorator.
class A:
#staticmethod
def foo():
print("Oh, wow, a static method in Python!")
A.foo()
So, your ActionClass could be rewritten as:
class ActionClass(Main):
#staticmethod
def do_action:
app.u.lineEdit.setText("test")
ans then you can use it like this:
if i == self.u.tabs.indexOf(self.u.tabFirst): ActionClass.do_action()

How export methods with dbus in a extended class in python, inherited methods?

I have a top class and classes that extend the top class, but almost all methods from the child classes are from the top class (using inheritance, without reimplementation), so I don't have the methods in the child classes, how could I export them with dbus for each child class (with the name of each child class as part of dbus path)?
I will show a example code for clarify, my class structure is:
Window (main class)
|--WindowOne (child class)
|--WindowTwo
|--WindowThree
My interface for dbus is com.example.MyInterface and I would like to access each child class using: com.example.MyInterface.WindowOne, and for each child class I would like to access the methods, inclusive the inherited methods from the main class, like com.example.MyInterface.WindowOne.show and com.example.MyInterface.WindowOne.destroy.
In this code, I extend the child class 'WindowOne' with the 'Window' class, the methods show() and destroy() in the 'Window' are not re-implemented in 'WindowOne', but in this code I put the method show() to explain the problem, the way I get the code to work was this, I re-declare the method show() in child class, but this seems bad.
The big question maybe is: There is some way to use the decorator: #dbus.service.method('com.example.MyInterface.WindowOne') for classes (child classes in this case)?
The test source code:
# interface imports
from gi.repository import Gtk
# dbus imports
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
# Main window class
class Window(dbus.service.Object):
def __init__(self, gladeFilePath, name):
# ... inicialization
self.name = name
self.busName = dbus.service.BusName('com.example.MyInterface.', bus=dbus.SessionBus())
dbus.service.Object.__init__(self, self.busName, '/com/example/MyInterface/' + self.name)
def show(self):
self.window.show_all()
def destroy(self):
Gtk.main_quit()
# Child window class
class WindowOne(Window):
def __init__(self, gladeFilePath):
Window.__init__(self, gladeFilePath, "WindowOne")
#dbus.service.method('com.example.MyInterface.WindowOne')
def show(self):
self.window.show_all()
if __name__ == "__main__":
DBusGMainLoop(set_as_default=True)
gladeFilePath = "/etc/interface.glade"
windowOne = WindowOne(gladeFilePath)
Gtk.main()
After some experimentation, I realize something essential, that I don't find before in documentation: The path for exported methods don't need to have the same path of exported object! Clarifing: If the method is not reimplemented in the child class (WindowOne), I don't need to export it in the child class using #dbus.service.method('com.example.MyInterface.WindowOne') , for example, I just need to export the method in the main class (Window) using: #dbus.service.method('com.example.MyInterface.Window')
So I just need to use a fixed path when export the method of the top class Window, see in the fixed code below.
# interface imports
from gi.repository import Gtk
# dbus imports
import dbus
import dbus.service
from dbus.mainloop.glib import DBusGMainLoop
# Main window class
class Window(dbus.service.Object):
def __init__(self, gladeFilePath, name):
# ... inicialization
self.name = name
self.busName = dbus.service.BusName('com.example.MyInterface.', bus=dbus.SessionBus())
dbus.service.Object.__init__(self, self.busName, '/com/example/MyInterface/' + self.name)
#dbus.service.method('com.example.MyInterface.Window')
def show(self):
self.window.show_all()
#dbus.service.method('com.example.MyInterface.Window')
def destroy(self):
Gtk.main_quit()
#dbus.service.method('com.example.MyInterface.Window')
def update(self, data):
# top class 'update' method
# Child window class
class WindowOne(Window):
def __init__(self, gladeFilePath):
Window.__init__(self, gladeFilePath, "WindowOne")
#dbus.service.method('com.example.MyInterface.WindowOne')
def update(self, data):
# reimplementation of top class 'update' method
if __name__ == "__main__":
DBusGMainLoop(set_as_default=True)
gladeFilePath = "/etc/interface.glade"
windowOne = WindowOne(gladeFilePath)
Gtk.main()
In the code for call the bus method, I just use like below:
bus = dbus.SessionBus()
dbusWindowOne = bus.get_object('com.example.MyInterface', '/com/example/MyInterface/WindowOne')
showWindowOne = dbusWindowOne.get_dbus_method('show', 'com.example.MyInterface.Window')
updateWindowOne = dbusWindowOne.get_dbus_method('update', 'com.example.MyInterface.WindowOne')
The method show is called in the top class Window, but is executed in the object WindowOne that is a child class.
And the method update is called in the child class WindowOne, because it is reimplementing the top class method.

Categories