python - GPIO 事件未显示在 QTreeModel / QWidget / QMainWindow
问题描述
我下面的代码在 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_())
解决方案
add_event_detect 调用的回调在辅助线程上执行,并且在 Qt 中禁止从另一个线程更新 GUI。所以诀窍是使用QTimer.singleShot(0, ...)
with更新 GUI functools.partial
:
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
推荐阅读
- python - Django模型字段中verbose_name和help_text的目的是什么?
- python - Amazon Web Services - Django 中的 S3“您提供的授权机制不受支持”
- jupyter-notebook - 在 jupyter notebook 中使用 cython 进行行分析
- react-native - 错误 reactotron createStore is not function
- laravel - 使用 Carbon laravel 的意外数据 \r\n
- azure-devops - 使用 Azure Devops 和发布变量的 App.Exe 配置转换
- spring - Spring:如何在@Scheduled 注解中提供特定的属性文件?
- javascript - 如何删除所有重复的数组元素,只留下单个值?
- javascript - Vuetify - 鼠标悬停时下拉菜单不突出显示
- android - 从Android Q中的特定文件夹获取文件列表