Mixins - Inherits from two QLineEdits using UiLoader
-
I have two custom
QLineEdit
:- ValidatedQLineEdit
- DelayedQLineEdit
If I want to have a
QLineEdit
with the functionality of both, how do I do it?I am doing this:
class DelayedValidatedLineEdit(DelayedLineEdit, ValidatedLineEdit): pass
But when I run it Qt creates an empty
QLineEdit
for me and then:
This happens because my two customQLineEdit
inherits fromQLineEdit
. If one of them did not inherit from anyone, it does work.If I create the
DelayedValidatedLineEdit
manually it works but I'm loading the ui file with the promotedQLineEdit
and then this happens.from PySide2 import QtCore, QtWidgets from utils import Color class DelayedLineEdit(QtWidgets.QLineEdit): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.delay = 250 self.timer = QtCore.QTimer() self.timer.setSingleShot(True) self.textEdited.connect(self._restart_timer) def _restart_timer(self): self.timer.start(self.delay) class ValidatedLineEdit(QtWidgets.QLineEdit): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.color = Color.DEFAULT def color_default(self): if self.color != Color.DEFAULT: self.color = Color.DEFAULT self.setStyleSheet(None) def color_red(self): if self.color != Color.RED: self.color = Color.RED self.setStyleSheet('background-color: rgb(255, 200, 200)') def validate(self, extra_condition=True, validate_empty=True): if (not validate_empty or self.text()) and extra_condition: self.color_default() else: self.color_red() class DelayedValidatedLineEdit(DelayedLineEdit, ValidatedLineEdit): pass
-
Thank you very much for your work! I like your code, it shows that you have experience.
That resource you found on google was one that I looked to try to fix this.
I understand that
super()
is a problem because of the differences between Python and C++, I will try not to use it.I have had to make some modifications to your code to make it work with my
UiLoader
class. Unfortunately, in the end, it returns the same error as it had before.The modifications I have made to your code are the following:
And I've also had to add*args
and**kwargs
so UiLoader won't throw me an error.from PySide2.QtCore import * from PySide2.QtWidgets import * from utils import Color class Delayer(QTimer): def __init__(self, *args, **kwargs): QTimer.__init__(self, *args, **kwargs) self.delay = 250 self.setSingleShot(True) def Restart(self): self.timer.start(self.delay) class DelayedLineEdit(QLineEdit): def __init__(self, *args, **kwargs): QLineEdit.__init__(self, *args, **kwargs) self.Delyr = Delayer() self.textEdited.connect(self.Delyr.Restart) class Validator(QObject): def __init__(self, LinEditr, *args, **kwargs): QObject.__init__(self, *args, **kwargs) self.LneEdt = LinEditr self.color = Color.DEFAULT def SetColorDefault(self): if self.color != Color.DEFAULT: self.color = Color.DEFAULT self.LneEdt.setStyleSheet(None) def SetColorRed(self): if self.color != Color.RED: self.color = Color.RED self.LneEdt.setStyleSheet('background-color: rgb(255, 200, 200)') def Valid(self, validate_empty=True, extra_condition=True): if (not validate_empty or self.LneEdt.text()) and extra_condition: self.SetColorDefault() else: self.SetColorRed() class ValidatedLineEdit(QLineEdit): def __init__(self, *args, **kwargs): QLineEdit.__init__(self, *args, **kwargs) self.Vldatr = Validator(self) # Nothing within your code snippet did more than this # which does nothing but I assume your finished piece # makes that connection class DelayedValidatedLineEdit(QLineEdit): def __init__(self, *args, **kwargs): QLineEdit.__init__(self, *args, **kwargs) # Here is the semi-universal Validator self.Vldatr = Validator(self) # Here is the semi-universal Delayer self.Delyr = Delayer() self.textEdited.connect(self.Delyr.Restart)
I got my UiLoader class from these sources:
- https://robonobodojo.wordpress.com/2017/10/03/loading-a-pyside-ui-via-a-class/
- https://robonobodojo.wordpress.com/2018/10/29/pyside2-widget-class-from-a-qt-designer-ui/
- https://gist.github.com/fredrikaverpil/0a89b174c9d29bc585f11d250adf2a7c
My UiLoader class:
from PySide2.QtUiTools import QUiLoader def load_ui(ui_file, base_instance=None, custom_classes=()): loader = UiLoader(base_instance) for custom_class in custom_classes: loader.registerCustomWidget(custom_class) loader.load(ui_file) class UiLoader(QUiLoader): def __init__(self, base_instance): super().__init__() self.base_instance = base_instance def createWidget(self, class_name, parent=None, name=''): if parent is None and self.base_instance: return self.base_instance else: return super().createWidget(class_name, parent, name)
And I fixed it, I have copied the code as is from the third link I put in one message above. Now it works.
https://gist.github.com/fredrikaverpil/0a89b174c9d29bc585f11d250adf2a7c
Now I can go in peace but against your recommendations xD
-
Thank you very much for your work! I like your code, it shows that you have experience.
That resource you found on google was one that I looked to try to fix this.
I understand that
super()
is a problem because of the differences between Python and C++, I will try not to use it.I have had to make some modifications to your code to make it work with my
UiLoader
class. Unfortunately, in the end, it returns the same error as it had before.The modifications I have made to your code are the following:
And I've also had to add*args
and**kwargs
so UiLoader won't throw me an error.from PySide2.QtCore import * from PySide2.QtWidgets import * from utils import Color class Delayer(QTimer): def __init__(self, *args, **kwargs): QTimer.__init__(self, *args, **kwargs) self.delay = 250 self.setSingleShot(True) def Restart(self): self.timer.start(self.delay) class DelayedLineEdit(QLineEdit): def __init__(self, *args, **kwargs): QLineEdit.__init__(self, *args, **kwargs) self.Delyr = Delayer() self.textEdited.connect(self.Delyr.Restart) class Validator(QObject): def __init__(self, LinEditr, *args, **kwargs): QObject.__init__(self, *args, **kwargs) self.LneEdt = LinEditr self.color = Color.DEFAULT def SetColorDefault(self): if self.color != Color.DEFAULT: self.color = Color.DEFAULT self.LneEdt.setStyleSheet(None) def SetColorRed(self): if self.color != Color.RED: self.color = Color.RED self.LneEdt.setStyleSheet('background-color: rgb(255, 200, 200)') def Valid(self, validate_empty=True, extra_condition=True): if (not validate_empty or self.LneEdt.text()) and extra_condition: self.SetColorDefault() else: self.SetColorRed() class ValidatedLineEdit(QLineEdit): def __init__(self, *args, **kwargs): QLineEdit.__init__(self, *args, **kwargs) self.Vldatr = Validator(self) # Nothing within your code snippet did more than this # which does nothing but I assume your finished piece # makes that connection class DelayedValidatedLineEdit(QLineEdit): def __init__(self, *args, **kwargs): QLineEdit.__init__(self, *args, **kwargs) # Here is the semi-universal Validator self.Vldatr = Validator(self) # Here is the semi-universal Delayer self.Delyr = Delayer() self.textEdited.connect(self.Delyr.Restart)
I got my UiLoader class from these sources:
- https://robonobodojo.wordpress.com/2017/10/03/loading-a-pyside-ui-via-a-class/
- https://robonobodojo.wordpress.com/2018/10/29/pyside2-widget-class-from-a-qt-designer-ui/
- https://gist.github.com/fredrikaverpil/0a89b174c9d29bc585f11d250adf2a7c
My UiLoader class:
from PySide2.QtUiTools import QUiLoader def load_ui(ui_file, base_instance=None, custom_classes=()): loader = UiLoader(base_instance) for custom_class in custom_classes: loader.registerCustomWidget(custom_class) loader.load(ui_file) class UiLoader(QUiLoader): def __init__(self, base_instance): super().__init__() self.base_instance = base_instance def createWidget(self, class_name, parent=None, name=''): if parent is None and self.base_instance: return self.base_instance else: return super().createWidget(class_name, parent, name)
-
Yeah it works but the UiLoader is so useful... I can edit the gui, save and run. Otherwise you would have to generate the .py code, format the code ... (before doing it like this)
I will search on the internet again to see if I find how to fix the UiLoader.
-
Thank you very much for your work! I like your code, it shows that you have experience.
That resource you found on google was one that I looked to try to fix this.
I understand that
super()
is a problem because of the differences between Python and C++, I will try not to use it.I have had to make some modifications to your code to make it work with my
UiLoader
class. Unfortunately, in the end, it returns the same error as it had before.The modifications I have made to your code are the following:
And I've also had to add*args
and**kwargs
so UiLoader won't throw me an error.from PySide2.QtCore import * from PySide2.QtWidgets import * from utils import Color class Delayer(QTimer): def __init__(self, *args, **kwargs): QTimer.__init__(self, *args, **kwargs) self.delay = 250 self.setSingleShot(True) def Restart(self): self.timer.start(self.delay) class DelayedLineEdit(QLineEdit): def __init__(self, *args, **kwargs): QLineEdit.__init__(self, *args, **kwargs) self.Delyr = Delayer() self.textEdited.connect(self.Delyr.Restart) class Validator(QObject): def __init__(self, LinEditr, *args, **kwargs): QObject.__init__(self, *args, **kwargs) self.LneEdt = LinEditr self.color = Color.DEFAULT def SetColorDefault(self): if self.color != Color.DEFAULT: self.color = Color.DEFAULT self.LneEdt.setStyleSheet(None) def SetColorRed(self): if self.color != Color.RED: self.color = Color.RED self.LneEdt.setStyleSheet('background-color: rgb(255, 200, 200)') def Valid(self, validate_empty=True, extra_condition=True): if (not validate_empty or self.LneEdt.text()) and extra_condition: self.SetColorDefault() else: self.SetColorRed() class ValidatedLineEdit(QLineEdit): def __init__(self, *args, **kwargs): QLineEdit.__init__(self, *args, **kwargs) self.Vldatr = Validator(self) # Nothing within your code snippet did more than this # which does nothing but I assume your finished piece # makes that connection class DelayedValidatedLineEdit(QLineEdit): def __init__(self, *args, **kwargs): QLineEdit.__init__(self, *args, **kwargs) # Here is the semi-universal Validator self.Vldatr = Validator(self) # Here is the semi-universal Delayer self.Delyr = Delayer() self.textEdited.connect(self.Delyr.Restart)
I got my UiLoader class from these sources:
- https://robonobodojo.wordpress.com/2017/10/03/loading-a-pyside-ui-via-a-class/
- https://robonobodojo.wordpress.com/2018/10/29/pyside2-widget-class-from-a-qt-designer-ui/
- https://gist.github.com/fredrikaverpil/0a89b174c9d29bc585f11d250adf2a7c
My UiLoader class:
from PySide2.QtUiTools import QUiLoader def load_ui(ui_file, base_instance=None, custom_classes=()): loader = UiLoader(base_instance) for custom_class in custom_classes: loader.registerCustomWidget(custom_class) loader.load(ui_file) class UiLoader(QUiLoader): def __init__(self, base_instance): super().__init__() self.base_instance = base_instance def createWidget(self, class_name, parent=None, name=''): if parent is None and self.base_instance: return self.base_instance else: return super().createWidget(class_name, parent, name)
And I fixed it, I have copied the code as is from the third link I put in one message above. Now it works.
https://gist.github.com/fredrikaverpil/0a89b174c9d29bc585f11d250adf2a7c
Now I can go in peace but against your recommendations xD