[英]Qt widget that can be either checkbox or text depending on initial value
I'm trying to figure out how to make a widget that would merge QCheckBox with QLineEdit into one.我试图弄清楚如何制作一个将 QCheckBox 与 QLineEdit 合并为一个的小部件。
In my interface, I parse attributes that can be either booleans or something else and I need to display them for users to edit.在我的界面中,我解析可以是布尔值或其他属性的属性,我需要显示它们以供用户编辑。 This means I have a fair bit of IFs in the code and I would like to encapsulate the logic into a widget.
这意味着我在代码中有相当多的 IF,我想将逻辑封装到一个小部件中。 My very naive implementation looks like this but it is not a true widget and this class requires special handling in the UI.
我非常天真的实现看起来像这样,但它不是一个真正的小部件,这个类需要在 UI 中进行特殊处理。 How can I make it a normal widget that can be used in any interface like all native widgets?
我怎样才能使它成为一个普通的小部件,可以像所有原生小部件一样在任何界面中使用?
from Qt import QtWidgets, QtCore
class SettingWidget(QtWidgets.QWidget):
'''a simple widget that can be either a bool or string. not sure how to make it an actual widget and this is just a wrapper'''
changed = QtCore.Signal(str, object)
def __init__(self, name, value):
super(self.__class__, self).__init__()
self.name = name
if isinstance(value, bool):
self.w_value = QtWidgets.QCheckBox()
self.w_value.stateChanged.connect(self._checkboxChanged)
self.w_value.setChecked(value)
self.changed.emit(self.name, value)
else:
self.w_value = QtWidgets.QLineEdit()
self.w_value.textChanged.connect(self._textChanged)
self.w_value.setText(str(value))
self.changed.emit(self.name, str(value))
def _checkboxChanged(self, state):
if state == QtCore.Qt.Checked:
self.changed.emit(self.name, True)
else:
self.changed.emit(self.name, False)
def _textChanged(self, text):
self.changed.emit(self.name, str(text))
def getWidget(self):
return self.w_value
A possible solution is to use SettingWidget as a container for one of the other widgets and then set it through a layout:一种可能的解决方案是使用 SettingWidget 作为其他小部件之一的容器,然后通过布局设置它:
lay = QtWidgets.QHBoxLayout(self)
lay.addWidget(self.w_value)
But IMO a better design is to create a mixin and design a function that provides the widget.但是 IMO 更好的设计是创建一个 mixin 并设计一个提供小部件的功能。
from Qt import QtCore, QtWidgets
class SettingMixin:
changed = QtCore.Signal(str, object)
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
def handle_changed(self, value):
self.changed.emit(self.name, value)
class SettingCheckBox(QtWidgets.QCheckBox, SettingMixin):
def __init__(self, name, initial_value, parent=None):
super().__init__(parent)
self.name = name
self.setChecked(initial_value)
self.toggled.connect(self.handle_changed)
class SettingLineEdit(QtWidgets.QLineEdit, SettingMixin):
def __init__(self, name, initial_value, parent=None):
super().__init__(parent)
self.name = name
self.setText(initial_value)
self.textChanged.connect(self.handle_changed)
def build_setting_widget(name, initial_value):
if isinstance(initial_value, bool):
return SettingCheckBox(name, initial_value)
elif isinstance(initial_value, str):
return SettingLineEdit(name, initial_value)
def main():
import sys
app = QtWidgets.QApplication(sys.argv)
widget = QtWidgets.QWidget()
lay = QtWidgets.QHBoxLayout(widget)
w1 = build_setting_widget("Foo", True)
w1.changed.connect(print)
w2 = build_setting_widget("Bar", "Hello World")
w2.changed.connect(print)
lay.addWidget(w1)
lay.addWidget(w2)
widget.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.