如何每秒更新容器小部件中的标签小部件

时间:2014-08-29 20:06:20

标签: pyqt

所以我有一个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注册。我觉得我错过了一些根本错误的东西。

1 个答案:

答案 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):