PySide-Pitfalls-Japanese: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
(Change category "LanguageBindings::PySide Japanese" -> "PySide")
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
[[Category:LanguageBindings::PySide]]<br />[[Category:LanguageBindings::PySide Japanese]]<br />[toc align_right=&quot;yes&amp;quot; depth=&quot;3&amp;quot;]
{{Cleanup | reason=Auto-imported from ExpressionEngine.}}
 
[[Category:PySide]]
[[Category:PySide]]


'''日本語''' [[PySide_Pitfalls|English]]
'''日本語''' [[PySide_Pitfalls|English]]
Line 11: Line 14:
QObjectはPythonのスコープから外れると削除されてしまいます。そのためオブジェクトの参照を保持するように注意する必要があります。
QObjectはPythonのスコープから外れると削除されてしまいます。そのためオブジェクトの参照を保持するように注意する必要があります。


* 他のオブジェクトの属性にして保持しましょう。例: &lt;code&amp;gt;self.window = QMainWindow()&lt;/code&amp;gt;
* 他のオブジェクトの属性にして保持しましょう。例: <code>self.window = QMainWindow()</code>
* コンストラクタに親となるQObjectを渡しましょう。こうすればそのオブジェクトは親によって保持されます。
* コンストラクタに親となるQObjectを渡しましょう。こうすればそのオブジェクトは親によって保持されます。


'''動作しない例'''
'''動作しない例'''


<code><br />class MyStuff(object):<br /> # …<br /> def animate_stuff(self, target):<br /> animation = QtCore.QPropertyAnimation(target, 'rotation')<br /> animation.setDuration(700)<br /> animation.setEasingCurve(QtCore.QEasingCurve.OutSine)<br /> animation.setEndValue(100)<br /> animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)<br /></code>
<code>
class MyStuff(object):
# …
def animate_stuff(self, target):
animation = QtCore.QPropertyAnimation(target, 'rotation')
animation.setDuration(700)
animation.setEasingCurve(QtCore.QEasingCurve.OutSine)
animation.setEndValue(100)
animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)
</code>


これがうまくいかない理由はanimationが&amp;lt;code&amp;gt;animate_stuff()&lt;/code&amp;gt;の終了時に削除されてしまい、動作をする機会が得られないからです。一般的にアニメーションを使う場合には、対象となるQObjectがある場合が多いので、アニメーションをそのオブジェクトの子にするとよいでしょう。これはコンストラクタの最後の引数に親オブジェクトを与えることによって行います。
これがうまくいかない理由はanimationが<code>animate_stuff()</code>の終了時に削除されてしまい、動作をする機会が得られないからです。一般的にアニメーションを使う場合には、対象となるQObjectがある場合が多いので、アニメーションをそのオブジェクトの子にするとよいでしょう。これはコンストラクタの最後の引数に親オブジェクトを与えることによって行います。


<code><br />class MyStuff(object):<br /> # …<br /> def animate_stuff(self, target):<br /> animation = QtCore.QPropertyAnimation(target, 'rotation', target)<br /> # …<br /></code>
<code>
class MyStuff(object):
# …
def animate_stuff(self, target):
animation = QtCore.QPropertyAnimation(target, 'rotation', target)
# …
</code>


この方法ではanimationの参照がtargetによって保持されるのでうまくいきます。別の方法としてanimationをそのオブジェクトの属性にする方法もあります( &quot;self.animation = …&quot;を使います)。この方法ではオブジェクトが属性を持っている間はアニメーションへの参照が保持され続けます(事前に手動で削除しない限り)。属性の上書き(例えば、最初のアニメーションがまだ実行されている最中に、他のアニメーションを代入するなど)は、また元のようにオブジェクトへの参照が削除されて、結局オブジェクト自体が削除されてしまう原因になるのでご注意ください。
この方法ではanimationの参照がtargetによって保持されるのでうまくいきます。別の方法としてanimationをそのオブジェクトの属性にする方法もあります( "self.animation = …"を使います)。この方法ではオブジェクトが属性を持っている間はアニメーションへの参照が保持され続けます(事前に手動で削除しない限り)。属性の上書き(例えば、最初のアニメーションがまだ実行されている最中に、他のアニメーションを代入するなど)は、また元のようにオブジェクトへの参照が削除されて、結局オブジェクト自体が削除されてしまう原因になるのでご注意ください。


== QtCore.QObject.sender() ==
== QtCore.QObject.sender() ==


シグナルの発行元オブジェクトを取得したい場合は&amp;lt;code&amp;gt;QtCore.QObject.sender()&lt;/code&amp;gt;を使用してください。ただし使用する前によく考えるべきです(詳しくはQObjectのAPIドキュメントをごらんください)。どうしても使用する必要があると判断した場合でも次のことに注意してください。この関数は静的メソッドとして呼び出すことはできませんし、呼び出せるのはQObjectのスロット内だけです。
シグナルの発行元オブジェクトを取得したい場合は<code>QtCore.QObject.sender()</code>を使用してください。ただし使用する前によく考えるべきです(詳しくはQObjectのAPIドキュメントをごらんください)。どうしても使用する必要があると判断した場合でも次のことに注意してください。この関数は静的メソッドとして呼び出すことはできませんし、呼び出せるのはQObjectのスロット内だけです。


つまり、 '''次のコードは動作しません'''
つまり、 '''次のコードは動作しません'''


<code><br />def on_signal(*args):<br /> print args<br /> print QtCore.QObject.sender() # THIS DOES NOT WORK!
<code>
def on_signal(*args):
print args
print QtCore.QObject.sender() # THIS DOES NOT WORK!


a.someSignal.connect(on_signal)<br /></code>
a.someSignal.connect(on_signal)
</code>


これを実現するには、次のように、スロットを持ったQObjectのサブクラスを作成して、そのオブジェクトのメンバー関数としてsender()にアクセスします。
これを実現するには、次のように、スロットを持ったQObjectのサブクラスを作成して、そのオブジェクトのメンバー関数としてsender()にアクセスします。


<code><br />class Listener(QtCore.QObject):<br /> &amp;#64;QtCore.Slot()<br /> def on_signal(self, *args):<br /> print args<br /> print self.sender()
<code>
class Listener(QtCore.QObject):
@QtCore.Slot()
def on_signal(self, *args):
print args
print self.sender()


listener = Listener()<br />a.someSignal.connect(listener.on_signal)
listener = Listener()
a.someSignal.connect(listener.on_signal)

Latest revision as of 04:54, 5 June 2016

This article may require cleanup to meet the Qt Wiki's quality standards. Reason: Auto-imported from ExpressionEngine.
Please improve this article if you can. Remove the {{cleanup}} tag and add this page to Updated pages list after it's clean.

日本語 English

PySideの落とし穴

このWikiページでは、PySideを使ってプログラム開発を始めたときに陥りやすい、よくある落とし穴についてまとめています。PySideを使ってアプリを開発している最中に「オー!」体験を見つけたら、是非その体験をここに記録してください。

参照

QObjectはPythonのスコープから外れると削除されてしまいます。そのためオブジェクトの参照を保持するように注意する必要があります。

  • 他のオブジェクトの属性にして保持しましょう。例:
    self.window = QMainWindow()
    
  • コンストラクタに親となるQObjectを渡しましょう。こうすればそのオブジェクトは親によって保持されます。

動作しない例

class MyStuff(object):
 # …
 def animate_stuff(self, target):
 animation = QtCore.QPropertyAnimation(target, 'rotation')
 animation.setDuration(700)
 animation.setEasingCurve(QtCore.QEasingCurve.OutSine)
 animation.setEndValue(100)
 animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)

これがうまくいかない理由はanimationが

animate_stuff()

の終了時に削除されてしまい、動作をする機会が得られないからです。一般的にアニメーションを使う場合には、対象となるQObjectがある場合が多いので、アニメーションをそのオブジェクトの子にするとよいでしょう。これはコンストラクタの最後の引数に親オブジェクトを与えることによって行います。

class MyStuff(object):
 # …
 def animate_stuff(self, target):
 animation = QtCore.QPropertyAnimation(target, 'rotation', target)
 # …

この方法ではanimationの参照がtargetによって保持されるのでうまくいきます。別の方法としてanimationをそのオブジェクトの属性にする方法もあります( "self.animation = …"を使います)。この方法ではオブジェクトが属性を持っている間はアニメーションへの参照が保持され続けます(事前に手動で削除しない限り)。属性の上書き(例えば、最初のアニメーションがまだ実行されている最中に、他のアニメーションを代入するなど)は、また元のようにオブジェクトへの参照が削除されて、結局オブジェクト自体が削除されてしまう原因になるのでご注意ください。

QtCore.QObject.sender()

シグナルの発行元オブジェクトを取得したい場合は

QtCore.QObject.sender()

を使用してください。ただし使用する前によく考えるべきです(詳しくはQObjectのAPIドキュメントをごらんください)。どうしても使用する必要があると判断した場合でも次のことに注意してください。この関数は静的メソッドとして呼び出すことはできませんし、呼び出せるのはQObjectのスロット内だけです。

つまり、 次のコードは動作しません

def on_signal(*args):
 print args
 print QtCore.QObject.sender() # THIS DOES NOT WORK!

a.someSignal.connect(on_signal)

これを実現するには、次のように、スロットを持ったQObjectのサブクラスを作成して、そのオブジェクトのメンバー関数としてsender()にアクセスします。

class Listener(QtCore.QObject):

@QtCore.Slot()
def on_signal(self, *args):
print args
print self.sender()

listener = Listener() a.someSignal.connect(listener.on_signal)