2016-09-13 15 views
0

QTimer.singleShot(..)関数を使用して、ある程度の遅延を伴う特定のアクション/関数を実行することがよくあります。確かに、私はtime.sleep(..)でもそれを行うことができますが、それは私のユーザーインターフェースをフリーズさせるでしょう。Python:QTimer.singleShot(..)関数の遅延展開を防ぐにはどうしたらいいですか?

パラメータを遅延関数に渡すことがあります。それはPythonのlambda機能が役立つところです。次の例を見てください。

####################################### 
    # Print 'Hello world' vertically # 
    ####################################### 
    myString = 'Hello world' 
    i = 0 
    for c in myString: 
     QtCore.QTimer.singleShot(10 + i*100, lambda: print(str(c))) 
     i += 1 

出力は直感的には左のようになります。しかし、実際には、文字列 'd'の垂直リストを取得します。これは、指定された文字列の最後の文字(驚き)です。

  _        _ 
    H  |       d  | 
    e  |       d  | 
    l  |       d  | 
    l  |       d  | 
    o  | Result you    d  | Result you 
      > would expect   d  > actually get! 
    w  |       d  | 
    o  |       d  | 
    r  |       d  | 
    l  |       d  | 
    d  |       d  | 
     _|        _| 

QTimer.singleshot(..)機能は「遅れ拡張」の原則を適用するように思えます。状況によっては素晴らしいですが、必ずしもそうではありません。

どのように拡張を制御できますか?すぐに展開することはできますか?


例コード:

新鮮なのpythonファイルに次のコードをコピー&ペースト、およびシェルから実行します。

import sys 
    from PyQt4 import QtGui, QtCore 

    class MainForm(QtGui.QMainWindow): 
     def __init__(self, parent=None): 
      super(MainForm, self).__init__(parent) 

      # create button 
      self.button = QtGui.QPushButton("QTimer.singleShot(..)", self) 
      self.button.clicked.connect(self.btnAction) 
      self.button.resize(200, 30) 


     def btnAction(self): 
      myString = 'Hello world' 
      i = 0 
      for c in myString: 
       QtCore.QTimer.singleShot(10 + i*100, lambda: print(str(c))) 
       i += 1 


    def main(): 
     app = QtGui.QApplication(sys.argv) 
     form = MainForm() 
     form.show() 
     app.exec_() 

    if __name__ == '__main__': 
     main() 

ボタンをクリックすると、あなたのシェルで「こんにちは世界の例が表示されます。

enter image description here

答えて

1

私は答えを見つけたと思います。

はあなたのコメントをありがとうござい@ekhumoro:functools.partial(..)ライブラリは、引数が

import sys 
from PyQt4 import QtGui, QtCore 
import functools 



class MainForm(QtGui.QMainWindow): 
    def __init__(self, parent=None): 
     super(MainForm, self).__init__(parent) 

     # create button 
     self.button = QtGui.QPushButton("QTimer.singleShot(..)", self) 
     self.button.clicked.connect(self.btnAction) 
     self.button.resize(200, 30) 


    def btnAction(self): 
     myString = 'Hello world' 
     i = 0 
     for c in myString: 
      #QtCore.QTimer.singleShot(10 + i*100, lambda: print(str(c))) 
      QtCore.QTimer.singleShot(10 + i * 100, functools.partial(print, str(c))) 
      i += 1 


def main(): 
    app = QtGui.QApplication(sys.argv) 
    form = MainForm() 
    form.show() 
    app.exec_() 

if __name__ == '__main__': 
    main() 

EDIT :-)凍結を受けることを除いて、あなたはlambda:..機能とまったく同じことを行うことができます。あなたのコード行も同様に動作します。

+3

'lambda arg = c:print(str(arg))'。 – ekhumoro

関連する問題