I use Python 3.6.3
I have following code:
class Parent:
def __init__(self, **kw):
print("init parent")
class PP:
def __init__(self, **kw):
print("init PP")
class Child(PP, Parent):
def __init__(self, **kw):
print("init child")
super().__init__()
exp=Child()
I expect:
init child
init PP
init parent
but I got:
init child
init PP
when I try to print the MRO,I got the correct answer.
print(exp.__class__.mro())
[<class '__main__.Child'>, <class '__main__.PP'>, <class '__main__.Parent'>, <class 'object'>]
Why is there no print of parent?
Python doesn't automatically call __init__ of Parent. You have to do it explicitly with super().__init__() in PP:
class Parent:
def __init__(self, **kw):
print("init parent")
class PP:
def __init__(self, **kw):
print("init PP")
super().__init__()
class Child(PP, Parent):
def __init__(self, **kw):
print("init child")
super().__init__()
exp = Child()
Now the output is:
init child
init PP
init parent
Related
If I define a disable_signal = QtCore.pyqtSignal() outside of the custom button class, the behaviour I am looking for (all instance are disabled when clicked upon).
class CustomButton(QtWidgets.QToolButton):
def __init__(self, parent, disable_signal):
super(CustomButton, self).__init__(parent)
self.disable_signal = disable_signal
self.disable_signal.connect(self.disable)
self.pressed.connect(self.buttonPressed)
def buttonPressed(self):
self.disable_signal.emit()
#QtCore.pyqtSlot()
def disable(self):
print("received")
self.setEnabled(False)
However, if I define the signal as a class attribute, each instance behave as if they each had their individual signal (pressing upon one, disable only that one):
class CustomButton(QtWidgets.QToolButton):
disable_signal = QtCore.pyqtSignal()
def __init__(self, parent):
super(CustomButton, self).__init__(parent)
self.disable_signal.connect(self.disable)
self.pressed.connect(self.buttonPressed)
def buttonPressed(self):
self.disable_signal.emit()
#QtCore.pyqtSlot()
def disable(self):
print("received")
self.setEnabled(False)
I don't understand why the signal is not shared? I tried to use instead of self.disable_signal.connect(self.disable), CustomButton.disable_signal.connect(self.disable) but I get the error: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'.
class botclass(QtCore.QObject):
progressChanged = QtCore.pyqtSignal(int)
def bot(self):
example_error_message = QListWidgetItem("Error")
example_error_message.setForeground(Qt.red)
self.loglist.insertItem(0, error)
class MainPage(QMainWindow):
def __init__(self, *args, **kwargs):
QtWidgets.QWidget.__init__(self, *args, **kwargs)
loadUi("uifile.ui", self)
example_working_message = QListWidgetItem("Working")
example_working_message.setForeground(Qt.green)
self.loglist.insertItem(0, example_working_message)
self.thread = QtCore.QThread()
self.botwork = botclass()
self.botwork.moveToThread(self.thread)
self.thread.started.connect(self.botwork.bot)
self.botwork.clicked.connect(self.thread.start)
Error is "AttributeError: 'botclass' object has no attribute 'loglist'"
I'm getting this error when using PyQt5 in Python, how can I solve it? "botclass" will be used with selenium.
How can fix this?
You must not access the GUI from another thread, what you must do is create a signal that sends the text and then in the GUI you create the item:
class BotClass(QtCore.QObject):
progressChanged = QtCore.pyqtSignal(int)
messageChanged = QtCore.pyqtSignal(str)
def bot(self):
self.messageChanged.emit("Error")
class MainPage(QMainWindow):
def __init__(self, *args, **kwargs):
QtWidgets.QMainWindow.__init__(self, *args, **kwargs)
loadUi("uifile.ui", self)
self.add_item("Working", Qt.green)
self.bot_thread = QtCore.QThread()
self.botwork = BotClass()
self.botwork.messageChanged.connect(self.handle_message_changed)
self.botwork.moveToThread(self.bot_thread)
self.bot_thread.started.connect(self.botwork.bot)
self.<some_button>.clicked.connect(self.bot_thread.start)
def handle_message_changed(self, message):
self.add_item(message, Qt.red)
def add_item(self, message, color):
item = QListWidgetItem(message)
item.setForeground(color)
self.loglist.insertItem(0, item)
To fix this you need to declare loglist in the same class as botclass.
It would be:
class botclass(QtCore.QObject):
def __init__(self):
self.loglist = #what you want loglist to be
progressChanged = QtCore.pyqtSignal(int)
def bot(self):
example_error_message = QListWidgetItem("Error")
example_error_message.setForeground(Qt.red)
self.loglist.insertItem(0, error)
If loglist is already a variable before the class, then do this:
class botclass(QtCore.QObject):
def __init__(self):
global loglist
self.loglist = loglist
progressChanged = QtCore.pyqtSignal(int)
def bot(self):
example_error_message = QListWidgetItem("Error")
example_error_message.setForeground(Qt.red)
self.loglist.insertItem(0, error)
This makes self.loglist = to the global variable loglist.
from tkinter import *
from tkinter.ttk import *
class window(Tk):
def __init__(self, **kwargs):
Tk.__init__(self, **kwargs)
box=Frame(self).pack(fill=BOTH,expand=1)
login=Frame(box,self).pack(fill=BOTH,expand=1)
register=Frame(box,self).pack(fill=BOTH,expand=1)
self.fup(login)
def fup(self,f):
f.tkraise()
class login(Frame):
def __init__(self, parent, controller,**kwargs):
Frame.__init__(self, parent)
super().__init__(**kwargs)
lab=Label(self,text='Login').grid(row=0,column=3,pady=3)
but=Button(self,text='Signup',command=lambda : controller.fup(register)).grid(row=4,column=0)
class register(Frame):
def __init__(self, parent, controller,**kwargs):
Frame.__init__(self, parent)
super().__init__(**kwargs)
lab=Label(self,text='Register').grid(row=0,column=3,pady=3)
but=Button(self,text='<<',command=lambda : controller.fup(login)).grid(row=0,column=0)
win=window()
win.mainloop()
You have a number of problems here. First, you're confused about how classes and class objects work. When you said
login=Frame(box,self).pack(fill=BOTH,expand=1)
That does not create an object of class login. It creates a simple Frame. In this case, it doesn't store an object at all, because the pack method does not return anything. In your login class, you refer to register, but that isn't an object, it's a class.
This is closer to what you want, and brings up a window, but since I can't tell what you really wanted, you'll have to take it from here.
from tkinter import *
from tkinter.ttk import *
class login(Frame):
def __init__(self, parent, controller,**kwargs):
super().__init__(parent, **kwargs)
lab=Label(self,text='Login').grid(row=0,column=3,pady=3)
but=Button(self,text='Signup',command=lambda : controller.fup(controller.register)).grid(row=4,column=0)
class register(Frame):
def __init__(self, parent, controller,**kwargs):
super().__init__(parent, **kwargs)
lab=Label(self,text='Register').grid(row=0,column=3,pady=3)
but=Button(self,text='<<',command=lambda : controller.fup(controller.login)).grid(row=0,column=0)
class window(Tk):
def __init__(self, **kwargs):
Tk.__init__(self, **kwargs)
box=Frame(self)
box.pack(fill=BOTH,expand=1)
self.login=login(box,self)
self.login.pack(fill=BOTH,expand=1)
self.register=register(box,self)
self.register.pack(fill=BOTH,expand=1)
self.fup(self.login)
def fup(self,f):
f.tkraise()
win=window()
win.mainloop()
Let suppose we have defined two classes:
class A():
def __init__(self):
self.a = 0
class B():
def __init__(self):
self.b = 0
Now, we want to define a third class C that inherits from A and B:
class C(A, B):
def __init__(self):
A.__init__(self) # how to do this using super()
B.__init__(self) # how to do this using super()
You did not specify whether you are Python 2 or Python 3 and it matters as we shall see. But either way, if you will be using super() in a derived class to initialize the base classes, then the base classes must use super() also. So,
For Python 3:
class A():
def __init__(self):
super().__init__()
self.a = 0
class B():
def __init__(self):
super().__init__()
self.b = 0
class C(A, B):
def __init__(self):
super().__init__()
For Python 2 (where classes must be new-style classes) or Python 3
class A(object):
def __init__(self):
super(A, self).__init__()
self.a = 0
class B(object):
def __init__(self):
super(B, self).__init__()
self.b = 0
class C(A, B):
def __init__(self):
super(C, self).__init__()
Can anyone tell me how to call add_row method from def test(self): method in User class ?
Now i am using code for call Rows().add_row().I print something in def add_row(self): then it prints but not add widget in screen.
test.py
class User(Popup):
def __init__(self, obj, **kwargs):
super(User, self).__init__(**kwargs)
def test(self):
Rows().add_row()
class narration(BoxLayout):
col_data = ListProperty(["?", "?", "?"])
button_text = StringProperty("")
def __init__(self, **kwargs):
super(narration, self).__init__(**kwargs)
class Rows(BoxLayout):
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
def add_row(self):
self.row_count += 1
self.add_widget(narration(button_text=str(self.row_count)))
class User(Popup):
def __init__(self, obj, **kwargs):
super(User, self).__init__(**kwargs)
self.row_obj = obj
def test(self):
self.row_obj.add_row()
class narration(BoxLayout):
col_data = ListProperty(["?", "?", "?"])
button_text = StringProperty("")
def __init__(self, **kwargs):
super(narration, self).__init__(**kwargs)
class Rows(BoxLayout):
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
def add_row(self):
self.row_count += 1
self.add_widget(narration(button_text=str(self.row_count)))
rows_obj = Rows()
user_obj = User(rows_obj)
It it not a working code it's just an example But your approach should be something like that.If you don't want to pass object of "Rows" class than make "User" class as a child of "Rows" class using inheritance concept.
class User(Rows,Popup):
I changed your code a little to show you how it's done.
in tmp.py
class Rows(object):
row_count = 0
def __init__(self, **kwargs):
super(Rows, self).__init__(**kwargs)
def add_row(self):
self.row_count += 1
print "Hello"
# self.add_widget(narration(button_text=str(self.row_count)))
class User(Rows):
def __init__(self, obj, **kwargs):
super(User, self).__init__(**kwargs)
def test(self):
self.add_row()
class narration(object):
# col_data = ListProperty(["?", "?", "?"])
# button_text = StringProperty("")
def __init__(self, **kwargs):
super(narration, self).__init__(**kwargs)
I had to comment out some lines in order to get it working.
now, in tmp2.py
from tmp import User
if __name__ == '__main__':
temp = User("H")
temp.test()
# outputs : Hello
What we did is instanciating the User class such as :
class User(Rows):, so when you will call User class, with the proper super() statement, you will be able to use the methods of Rows as you would use it as if it was defined in User class.
So you will call (it has been modified in the code) : self.add_row(), even if add_row() is a method from Rows.