PySide-Pitfalls-Japanese: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
Line 1: Line 1:
'''日本語''' [[PySide Pitfalls|English]]
[[Category:LanguageBindings::PySide]]<br />[[Category:LanguageBindings::PySide Japanese]]<br />[toc align_right=&quot;yes&amp;quot; depth=&quot;3&amp;quot;]


=PySideの落とし穴=
'''日本語''' [[PySide_Pitfalls|English]]
 
= PySideの落とし穴 =


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


==参照==
== 参照 ==


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


* 他のオブジェクトの属性にして保持しましょう。例: <code>self.window = QMainWindow()</code>
* 他のオブジェクトの属性にして保持しましょう。例: &lt;code&amp;gt;self.window = QMainWindow()&lt;/code&amp;gt;
* コンストラクタに親となるQObjectを渡しましょう。こうすればそのオブジェクトは親によって保持されます。
* コンストラクタに親となる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')<br /> animation.setDuration(700)<br /> animation.setEasingCurve(QtCore.QEasingCurve.OutSine)<br /> animation.setEndValue(100)<br /> animation.start(QtCore.QAbstractAnimation.DeleteWhenStopped)<br /></code>


この方法ではanimationの参照がtargetによって保持されるのでうまくいきます。別の方法としてanimationをそのオブジェクトの属性にする方法もあります( “self.animation = …“を使います)。この方法ではオブジェクトが属性を持っている間はアニメーションへの参照が保持され続けます(事前に手動で削除しない限り)。属性の上書き(例えば、最初のアニメーションがまだ実行されている最中に、他のアニメーションを代入するなど)は、また元のようにオブジェクトへの参照が削除されて、結局オブジェクト自体が削除されてしまう原因になるのでご注意ください。
これがうまくいかない理由はanimationが&amp;lt;code&amp;gt;animate_stuff()&lt;/code&amp;gt;の終了時に削除されてしまい、動作をする機会が得られないからです。一般的にアニメーションを使う場合には、対象となるQObjectがある場合が多いので、アニメーションをそのオブジェクトの子にするとよいでしょう。これはコンストラクタの最後の引数に親オブジェクトを与えることによって行います。


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


シグナルの発行元オブジェクトを取得したい場合は<code>QtCore.QObject.sender()</code>を使用してください。ただし使用する前によく考えるべきです(詳しくはQObjectのAPIドキュメントをごらんください)。どうしても使用する必要があると判断した場合でも次のことに注意してください。この関数は静的メソッドとして呼び出すことはできませんし、呼び出せるのはQObjectのスロット内だけです。
この方法ではanimationの参照がtargetによって保持されるのでうまくいきます。別の方法としてanimationをそのオブジェクトの属性にする方法もあります( &quot;self.animation = …&quot;を使います)。この方法ではオブジェクトが属性を持っている間はアニメーションへの参照が保持され続けます(事前に手動で削除しない限り)。属性の上書き(例えば、最初のアニメーションがまだ実行されている最中に、他のアニメーションを代入するなど)は、また元のようにオブジェクトへの参照が削除されて、結局オブジェクト自体が削除されてしまう原因になるのでご注意ください。
 
== QtCore.QObject.sender() ==
 
シグナルの発行元オブジェクトを取得したい場合は&amp;lt;code&amp;gt;QtCore.QObject.sender()&lt;/code&amp;gt;を使用してください。ただし使用する前によく考えるべきです(詳しくはQObjectのAPIドキュメントをごらんください)。どうしても使用する必要があると判断した場合でも次のことに注意してください。この関数は静的メソッドとして呼び出すことはできませんし、呼び出せるのはQObjectのスロット内だけです。


つまり、 '''次のコードは動作しません'''
つまり、 '''次のコードは動作しません'''
<code><br />def on_signal(*args):<br /> print args<br /> print QtCore.QObject.sender() # THIS DOES NOT WORK!
a.someSignal.connect(on_signal)<br /></code>


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


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


* [[:Category:LanguageBindings|LanguageBindings]]
listener = Listener()<br />a.someSignal.connect(listener.on_signal)
** [[:Category:LanguageBindings::PySide|PySide]]
* [[:Category:LanguageBindings::PySide-Japanese|PySide Japanese]]

Revision as of 10:00, 24 February 2015



[toc align_right="yes&quot; depth="3&quot;]

日本語 English

PySideの落とし穴

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

参照

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

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

動作しない例

<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 />

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

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

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

QtCore.QObject.sender()

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

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

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

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

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


class Listener(QtCore.QObject):
&#64;QtCore.Slot()
def on_signal(self, *args):
print args
print self.sender()

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