[英]pyqt: dynamically update properties for dynamically created widgets
我試圖找到一種方法來更新動態創建的小部件(可以刪除)中的標簽,根據前面小部件中動態設置的屬性。
有沒有辦法自動和動態地將pyqt對象鏈接到其他小部件的屬性,以便當我在任何地方更改值時,該對象會自行更新?
示例:對象'a'具有屬性start
, bars
和end
; bars
給定, start
采取的是前一個對象(或1,如果無), end
計算。 對象'b'從a.end
start
,依此類推。
class myclass(object):
def __init__(self, referrer=None, value=1):
self.referrer=referrer
self.value=value
def _get_start(self):
if not self.referrer:
return 1
else:
return self.referrer.end+1
def _get_end(self):
return self.start+self.value-1
start=property(_get_start)
end=property(_get_end)
def create(value=1):
if not vList:
ref=None
else:
ref=vList[-1]
val=myclass(ref, value)
vList.append(val)
def showList():
for i in vList:
print 'item: %d\tstart: %d\tend: %d' % (vList.index(i),i.start, i.end)
vList=[]
如果我調用create()3次,showList()將顯示:
item: 0 start: 1 end: 1
item: 1 start: 2 end: 2
item: 2 start: 3 end: 3
如果我將vList [0] .value更改為3:
item: 0 start: 1 end: 3
item: 1 start: 4 end: 4
item: 2 start: 5 end: 5
當我需要在gui中更新這些值時會出現問題( 想想它是這樣的接口 ):每個水平小部件都有一個標簽顯示start
的屬性,一個用於bars
的spinbox,一個用於end
的標簽,以及as 任何 spinbox值更改后,每個后續窗口小部件都應根據其先前的窗口小部件更新其start
和end
屬性,並在相關標簽中顯示它們。 此外,當刪除任何窗口小部件時,所有后續窗口小部件都應重新計算每個屬性。
使用getter / setter來設置窗口小部件下一個實例的標簽中的值顯然不能正常工作,因為當我更改任何x.value
,以下實例的start
和end
將僅在被調用時實際更新, AFAIU。 我可以將每個新窗口小部件連接到它之前的(使用valueChanged()
)或創建一個查找后續窗口小部件並更新其屬性的函數,但這不是一個好的解決方案。
因為我幾乎是python的新手(最重要的是:我不是程序員)我認為我忽略了一些關於以更好和最干凈的方式“連接”變量的東西(可能與信號或線程相關?)。
考慮到這些部件實際上是孩子們的另一個“主”小工具,這將有類似性質的小工具: start
從以前的主窗口部件(如果有的話)采取bars
是所有的總和bars
在每一個孩子小部件, end
這將再次start+bars-a
。
謝謝!
(我希望你能理解我的意思,我的英語不完美,因為我不是程序員,我的術語並不總是正確的)
我無法從您的問題中找到用例,但這里有可能使用Qt Signals-Slots的解決方案:
# -*- coding: utf-8 -*-
import functools
from PyQt4 import QtGui, QtCore
class ObservableVariable(QtCore.QObject):
""" Represents variable with value, when value changes it emits
signal: changed(new_value)
"""
changed = QtCore.pyqtSignal(object)
def __init__(self, initial_value=0):
super(ObservableVariable, self).__init__()
self._value = initial_value
def get_value(self):
return self._value
def set_value(self, new_val):
self._value = new_val
self.changed.emit(new_val)
value = property(get_value, set_value)
def __str__(self):
return str(self.value)
# it can support more operators if needed
def __iadd__(self, other):
self.value += other
return self
def __isub__(self, other):
self.value -= other
return self
class MyClass(object):
def __init__(self, referrer=None, value=1):
self.referrer = referrer
self.value = ObservableVariable(value)
self._initial_value = value
if referrer:
# propagate referrer changes to subscribers
referrer.value.changed.connect(
lambda x: self.value.changed.emit(self.value.value)
)
@property
def start(self):
if not self.referrer:
return self.value.value
return self.referrer.end + 1
@property
def end(self):
return self.start + self.value.value - 1
class GuiExample(QtGui.QWidget):
def __init__(self):
super(GuiExample, self).__init__()
self.values = []
layout = QtGui.QVBoxLayout(self)
obj = None
for i in range(5):
obj = MyClass(obj, i)
self.values.append(obj)
# create gui elements
hlayout = QtGui.QHBoxLayout()
spinbox = QtGui.QSpinBox()
spinbox.setValue(obj.value.value)
start_label = QtGui.QLabel()
end_label = QtGui.QLabel()
hlayout.addWidget(start_label)
hlayout.addWidget(spinbox)
hlayout.addWidget(end_label)
layout.addLayout(hlayout)
# function called on value change
def update_start_end(instance, start_label, end_label):
start_label.setText(str(instance.start))
end_label.setText(str(instance.end))
action = functools.partial(update_start_end, obj, start_label,
end_label)
action() # set initial start end text to labels
# connect signals to gui elements
obj.value.changed.connect(action)
spinbox.valueChanged.connect(obj.value.set_value)
obj.value.changed.connect(spinbox.setValue)
layout.addWidget(QtGui.QPushButton('test',
clicked=self.test_modification))
def test_modification(self):
self.values[1].value += 1
app = QtGui.QApplication([])
gui = GuiExample()
gui.show()
app.exec_()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.