GPIO 事件未显示在 QTreeModel / QWidget / QMainWindow 中
GPIO Event not showing in QTreeModel / QWidget / QMainWindow
我下面的代码在 Pi 上运行,屏幕上的 'Scroll' 按钮起作用,可以明显地滚动屏幕内容。然后我将 GPIO 按钮按下附加到相同的 Scroll 方法,当按下硬件按钮时代码运行,屏幕不会更新,直到鼠标移到应该更新的区域上。
我尝试了各种方法来更新屏幕,但 none 奏效了:
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, ...)
和 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
我下面的代码在 Pi 上运行,屏幕上的 'Scroll' 按钮起作用,可以明显地滚动屏幕内容。然后我将 GPIO 按钮按下附加到相同的 Scroll 方法,当按下硬件按钮时代码运行,屏幕不会更新,直到鼠标移到应该更新的区域上。
我尝试了各种方法来更新屏幕,但 none 奏效了:
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, ...)
和 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