GPIO事件未显示在QTreeModel / QWidget / QMainWindow中

时间:2019-04-14 22:01:48

标签: python pyqt raspberry-pi pyqt5 gpio

我下面的代码在Pi上运行,并且屏幕上的“滚动”按钮有效,可以滚动屏幕上的内容。然后,我将按下GPIO按钮的按钮附加到相同的Scroll方法上,并且当按下硬件按钮时代码运行时,直到将鼠标移到应更新的区域上,屏幕才会更新。

我尝试了各种方法来更新屏幕,但没有一个起作用:

    self.IQM.dataChanged.emit(QtCore.QModelIndex(), QtCore.QModelIndex())
    self.IQM.layoutChanged.emit()
    self.update()

最小示例代码如下。非常感谢您的帮助。

非常感谢

凯文

#!/usr/bin/python3
# -*- coding: utf-8 -*-

from PyQt5.QtWidgets import QMainWindow, QWidget, QGridLayout
from PyQt5.QtWidgets import QTreeView, QApplication, qApp, QPushButton

from PyQt5.QtGui import QStandardItemModel, QStandardItem
from PyQt5.QtCore import Qt, pyqtSlot

import sys

import RPi.GPIO as GPIO


class StartMarshall(QMainWindow):

    def __init__(self):
        super().__init__()

        self.data = ['XXX' for _ in range(10)]

        # Build Central Widget
        self.widget = QWidget()
        self.setCentralWidget(self.widget)

        # build buttons
        scrollButton = self.createButton(self.scroll, 'Scroll', 'Scroll action')
        exitButton = self.createButton(qApp.quit, 'Exit', 'Exit action')

        # Setup RPI GPIO Hardware Buttons
        # Use Broadcom GPIO numbers (BCM)
        GPIO.setmode(GPIO.BCM)
        pinStartGate = 4
        # Setup pinSG as an Input with a pull up resistor attached (ie pull down for press)
        GPIO.setup(pinSG, GPIO.IN, pull_up_down=GPIO.PUD_UP)
        # Call self.scroll on button press
        GPIO.add_event_detect(pinSG, GPIO.FALLING, callback=self.scroll, bouncetime=300)

        grid = QGridLayout()
        grid.setSpacing(10)

        # intialize view of data
        self.IQ = IQ = QTreeView()

        # Prepopulate View Models
        self.IQM = self.prepModel(IQ)

        self.fillModel(self.IQM, self.data[2:len(self.data)])

        # include the widgets
        grid.addWidget(IQ, 3, 1, -1, -1)

        grid.addWidget(scrollButton, 5, 0)
        grid.addWidget(exitButton, 7, 0)

        self.widget.setLayout(grid)

        # Show QMainWindow
        self.show()
        #self.showFullScreen()
        #self.showMaximized()

    def createButton(self, on_click, btn_txt='button title', btn_tip='this is a button hint'):
        button = QPushButton(btn_txt, self)
        button.setToolTip(btn_tip)
        button.clicked.connect(on_click)
        return button

    def prepModel(self, widget):
        # initialize a model
        model = QStandardItemModel()

        # remove indentation and headers
        widget.setIndentation(0)
        widget.setHeaderHidden(1)

        # add (data) model to widget
        widget.setModel(model)
        return model

    def fillModel(self, model, data):
        # for refilling model data
        for i, d in enumerate(data):
            model.setItem(i, QStandardItem(d))
        return

    @pyqtSlot()
    def scroll(self, event=None):
        print("Scroll")
        # when scroll button is clicked
        if self.data[1:2] == '':  # if second data is blank then no need to scroll
            return

        # remove the first element from data
        self.data.pop(0)

        # add the padded (blank) element from data
        self.data.append('')

        # show the full queue (-1 doesnt show last racer?)
        self.fillModel(self.IQM, self.data[2:len(self.data)])

        return

# Main
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = StartMarshall()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:0)

add_event_detect调用的回调在辅助线程上执行,在Qt中,禁止从另一个线程更新GUI。因此,诀窍是使用QTimer.singleShot(0, ...)functools.partial来更新GUI:

from functools import partial

# ...

class StartMarshall(QMainWindow):
    # ...

    @pyqtSlot(QStandardItemModel, list)
    def fillModel(self, model, data):
        # for refilling model data
        for i, d in enumerate(data):
            model.setItem(i, QStandardItem(d))
        return

    def scroll(self, event=None):
        print("Scroll")
        # when scroll button is clicked
        # if second data is blank then no need to scroll
        if self.data[1:2] == "":
            return
        # remove the first element from data
        self.data.pop(0)
        # add the padded (blank) element from data
        self.data.append("")
        # show the full queue (-1 doesnt show last racer?)
        wrapper = partial(self.fillModel, self.IQM, self.data[2:])
        QtCore.QTimer.singleShot(0, wrapper)
        return