所以我有一个GUI,其中包含在数据库中查找变量值的小部件,并以与kv对相同的方式显示变量名称和当前值,使用两个QLabel
彼此相邻并称他们为DisplayItemWidget
。然后我将一堆这些DisplayItemWidget
堆叠在另一个小部件中,我称之为CellContainerWidget
,我在网格中有一堆那些,这样我就可以跟踪变量的多个变量分组。所有小部件查询的数据库不断更新,我希望我的GUI更新每个DisplayItemWidgets
以更新每一秒。但我不知道该怎么做。我尝试使用QTimer将计时器事件发送到MainWindow
,但这不起作用。所以我想知道架构应该是什么样的内部,内部小部件每秒更新一次。
我的代码的精简版本在这里:
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
import random
def main():
app = QApplication(sys.argv)
db = Database()
########## instantiate fake data
cell_list = []
taglist = ['ground_tlm', 'state_tlm']
counter = 0
for tag in taglist:
display_list = []
display_name = tag.split('_')[0] + ' stuff'
for i in range(int((random.random()*5)+1)):
db.update([tag, 'var-%i' % i, 'float', str(random.random())])
widget = DisplayItemWidget(tag, 'var-%i' % i, db)
display_list.append(widget)
ccw = CellContainerWidget(display_list, display_name, counter, 0)
counter += 1
cell_list.append(ccw)
taglist = ['random_tlm', 'up_tlm']
counter = 0
for tag in taglist:
display_list = []
display_name = tag.split('_')[0] + ' stuff'
for i in range(int((random.random()*5)+1)):
db.update([tag, 'var-%i' % i, 'float', str(random.random())])
widget = DisplayItemWidget(tag, 'var-%i' % i, db)
display_list.append(widget)
ccw = CellContainerWidget(display_list, display_name, counter, 1)
counter += 1
cell_list.append(ccw)
##########
mw = MainWindow(cell_list, db)
mw.show()
timer = QBasicTimer()
timer.start(500, mw)
sys.exit(app.exec_())
class DisplayItemWidget(QWidget):
def __init__(self, tag, var_name, db):
super(DisplayItemWidget, self).__init__()
self.layout = QHBoxLayout()
self.label1 = QLabel()
self.label2 = QLabel()
self.tag = tag
self.var_name = var_name
self.db = db
self.init_ui()
def init_ui(self):
self.label1.setText(self.tag + ': ' + self.var_name)
self.label1.setAlignment(Qt.AlignCenter)
self.label1.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
self.layout.addWidget(self.label1)
val = self.db.get_val(self.tag, self.var_name)
if val is not None:
self.label2.setText(val)
self.label2.setText(val)
self.label2.setAlignment(Qt.AlignCenter)
self.label2.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
self.layout.addWidget(self.label2)
self.layout.setSpacing(10)
self.setLayout(self.layout)
self.setWindowTitle("Display Item Widget")
def update_value(self):
val = self.db.get_val(self.tag, self.var_name)
if val is not None:
self.label2.setText(val)
class CellContainerWidget(QWidget):
def __init__(self, display_list, cell_name, col_index, row_index):
super(CellContainerWidget, self).__init__()
self.layout = QVBoxLayout()
self.cell_name_label = QLabel()
self.cell_name_label.setText(cell_name)
self.display_list = display_list
self.col_index = col_index
self.row_index = row_index
self.init_ui()
def init_ui(self):
self.cell_name_label.setAlignment(Qt.AlignCenter)
self.cell_name_label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self.layout.addWidget(self.cell_name_label)
for widget in self.display_list:
widget.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
self.layout.addWidget(widget)
self.layout.setSpacing(0)
self.setLayout(self.layout)
self.setWindowTitle("Cell Item Widget")
def get_widgets(self):
return self.display_list
class MainWindow(QWidget):
def __init__(self, cell_list, db):
super(MainWindow, self).__init__()
self.layout = QGridLayout()
self.cell_list = cell_list
self.db = db
self.init_ui()
def init_ui(self):
for cell in self.cell_list:
cell.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
self.layout.addWidget(cell, cell.col_index, cell.row_index)
self.layout.setSpacing(0)
self.setLayout(self.layout)
self.setWindowTitle("Main Window Widget")
def update_gui(self, event):
########## Mock out update to first column
print self.db.print_contents()
taglist = ['ground_tlm', 'state_tlm']
for tag in taglist:
for i in range(int((random.random()*5)+1)):
self.db.update([tag, 'var-%i' % i, 'float', str(random.random())])
##########
for cell in self.cell_list:
for widget in cell.get_widgets():
widget.update_value()
class Database():
def __init__(self):
self.telemetry_types = {
'state_tlm': {'var-1': ('int', '0'), } # Example of how this will be populated
}
def get_var_table(self, tlm_type):
return self.telemetry_types.get(tlm_type, None)
def update(self, parsed_data):
tlm_type, var_name, var_type, datum = parsed_data
if tlm_type in self.telemetry_types:
self.telemetry_types[tlm_type][var_name] = (var_type, datum)
else:
self.telemetry_types[tlm_type] = {
var_name: (var_type, datum),
}
def get_val(self, tlm_type, var_name):
if tlm_type in self.telemetry_types:
if var_name in self.telemetry_types[tlm_type]:
return self.telemetry_types[tlm_type][var_name][1]
else:
return None
else:
return None
def print_contents(self):
print self.telemetry_types
def get_keys(self):
return self.telemetry_types.keys()
if __name__ == '__main__':
main()
只更新一次然后再更新。并且事件计时器甚至没有被mw注册。我觉得我错过了一些根本错误的东西。
答案 0 :(得分:2)
您没有正确实例化您的计时器。
目前,您正在将对象mw
传递给QBasicTimer
,但尚未编写此对象来处理Timer事件。简而言之,它不知道它应该调用update_gui
(为什么会这样?这是你创建并任意命名的方法!)
相反,我建议使用QTimer
类而不是QBasicTimer
来构建计时器,如下所示:
timer = QTimer(mw)
timer.timeout.connect(mw.update_gui)
timer.start(500)
这会创建一个QTimer
,将timeout
信号连接到update_gui
插槽并启动计时器(超时为500毫秒)。
请注意,您还需要将MainWindow.update_gui
的签名更改为不包含event
变量。所以它应该看起来像def update_gui(self):