为什么不能将生成器函数用作插槽?
Why can't you use a generator function as a slot?
我正在尝试循环访问 PySide2 应用程序中的列表。因此,每次按下 "Next" 按钮时,都会从列表中返回并显示下一项。我可以跟踪我的列表中最近读取的条目的索引,并在每次槽调用时手动增加索引,但我认为将槽转换为生成器函数可能更优雅。但它不起作用。
下面是最小的(不是)工作示例。
import sys
from PySide2.QtWidgets import QApplication, QPushButton
from PySide2.QtCore import SIGNAL, QObject
def func():
stringEntries=["One", "Two", "Three"]
for item in stringEntries:
# In the application this sets the values of a numpy array
# and fires a signal which updates a matplotlib canvas but meh, whatever
print("func ", item, " has been called!")
# This sort of works without the following yield statement
yield
app = QApplication(sys.argv)
button = QPushButton("Next")
QObject.connect(button, SIGNAL ('clicked()'), func)
button.show()
sys.exit(app.exec_())
我有点期待每次按下 "Next" 按钮时打印不同的字符串,但它只是坐在那里嘲笑我...
有人能指出我从根本上误解的地方吗?
正如 @jasonharper 在评论中指出的那样,每次按下按钮时都会创建一个新的迭代器,这会产生问题,一个可能的解决方案是创建一个 class 将迭代器作为一个属性并使用 __call__ 方法查看它,为了使其简单和优雅,我创建了一个装饰器:
from PySide2.QtCore import QObject
from PySide2.QtWidgets import QApplication, QPushButton
class decorator:
def __init__(self, f):
self._f = f
self._iterator = None
def __call__(self, *args, **kwargs):
if self._iterator is None:
self._iterator = self._f(*args, **kwargs)
try:
return next(self._iterator)
except StopIteration:
pass
@decorator
def func():
stringEntries = ["One", "Two", "Three"]
for item in stringEntries:
print("func ", item, " has been called!")
yield
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
button = QPushButton("Next")
button.clicked.connect(func)
button.show()
sys.exit(app.exec_())
我正在尝试循环访问 PySide2 应用程序中的列表。因此,每次按下 "Next" 按钮时,都会从列表中返回并显示下一项。我可以跟踪我的列表中最近读取的条目的索引,并在每次槽调用时手动增加索引,但我认为将槽转换为生成器函数可能更优雅。但它不起作用。
下面是最小的(不是)工作示例。
import sys
from PySide2.QtWidgets import QApplication, QPushButton
from PySide2.QtCore import SIGNAL, QObject
def func():
stringEntries=["One", "Two", "Three"]
for item in stringEntries:
# In the application this sets the values of a numpy array
# and fires a signal which updates a matplotlib canvas but meh, whatever
print("func ", item, " has been called!")
# This sort of works without the following yield statement
yield
app = QApplication(sys.argv)
button = QPushButton("Next")
QObject.connect(button, SIGNAL ('clicked()'), func)
button.show()
sys.exit(app.exec_())
我有点期待每次按下 "Next" 按钮时打印不同的字符串,但它只是坐在那里嘲笑我...
有人能指出我从根本上误解的地方吗?
正如 @jasonharper 在评论中指出的那样,每次按下按钮时都会创建一个新的迭代器,这会产生问题,一个可能的解决方案是创建一个 class 将迭代器作为一个属性并使用 __call__ 方法查看它,为了使其简单和优雅,我创建了一个装饰器:
from PySide2.QtCore import QObject
from PySide2.QtWidgets import QApplication, QPushButton
class decorator:
def __init__(self, f):
self._f = f
self._iterator = None
def __call__(self, *args, **kwargs):
if self._iterator is None:
self._iterator = self._f(*args, **kwargs)
try:
return next(self._iterator)
except StopIteration:
pass
@decorator
def func():
stringEntries = ["One", "Two", "Three"]
for item in stringEntries:
print("func ", item, " has been called!")
yield
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
button = QPushButton("Next")
button.clicked.connect(func)
button.show()
sys.exit(app.exec_())