質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.59%

python2.7 + pyqt4でprint文が実行されなくなる問題

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,047

score 10

現在、Python2.7とPyQt4を使用したGUIアプリケーションの作り方を学んでいます。
一通りチュートリアルを終えたので、簡単なゲームを作ってみようとコーディングをしていたのですが
print文が正常に実行されなくなるという問題が発生しました。

具体的には、keyPressEventで、キーの入力によって状態を変化させ、変更後の状態を出力するという処理の際に一回目に発生したイベントでは、値が出力されず、二回目に発生したイベントで2つの出力が行われるという現象です。

公式のドキュメントなどを参照しましたが、原因がわかりませんので、何方か教えていただければ幸いです。

以下コード
# -*- coding: utf-8 -*-

import sys
from PyQt4 import QtGui, QtCore

class Tankdaze(QtGui.QWidget):
    def __init__(self):
        super(Tankdaze, self).__init__()
        
        self.initUI()
        
    def initUI(self):
        
        #signalをコネクト
        self.c = Communicate()
        self.c.changeUI.connect(self.changeUI)
        
        #スタート画面の生成
        self.titleLabel = QtGui.QLabel(self)
        titleImage = QtGui.QPixmap('Hydrangeas.jpg')
        self.titleLabel.setPixmap(titleImage)
        
        self.setGeometry(100, 100, 1024, 768)
        self.setFixedSize(1024, 768)
        self.show()   

    def changeUI(self):
        self.titleLabel.hide()
        
        imageLabel = QtGui.QLabel(self)
        imageFromCam = QtGui.QPixmap('Jellyfish.jpg')
        imageLabel.setPixmap(imageFromCam)
        imageLabel.show()
        
        #ゲーム残り時間
        timer = QtGui.QLCDNumber(self)
        timer.move(472, 10)
        timer.resize(80, 80)
        timer.show()
        
        #残弾
        bullet = QtGui.QLCDNumber(self)
        bullet.move(894, 638)
        bullet.resize(100, 100)
        bullet.show()
        
        #自機体力
        myHP = QtGui.QProgressBar(self)
        myHP.move(20, 20)
        myHP.resize(400, 50)
        myHP.show()
        
        #敵機体力
        enemyHP = QtGui.QProgressBar(self)
        enemyHP.resize(400, 50)
        enemyHP.move(644, 20)
        enemyHP.show()
        
        #待ちメッセージ
        waitLabel = QtGui.QLabel(self)
        waitLabel.setText(u'<font color = white size = 30>相手プレイヤーの準備を待っています</font>')
        waitLabel.move(250, 650)
        waitLabel.show()
        
        #timerをセット
        loopTimer = QtCore.QTimer()
        loopTimer.timeout.connect(self.gameLoop)
        loopTimer.start(1000)
        
        #ここに、相手も準備ができているか確かめる処理を入れる
        
    def keyPressEvent(self, e):
        if e.key() == QtCore.Qt.Key_Space:
            self.gameState = 'ready'
            print 'current state is ' + self.gameState
            self.c.changeUI.emit()
            
        elif e.key() == QtCore.Qt.Key_A:
            self.gameState = 'game'
            print 'current state is ' + self.gameState
            
    def gameLoop(self):
        print 'hello'
            
            
class Communicate(QtCore.QObject):
    
    changeUI = QtCore.pyqtSignal()
        
def main():
    app = QtGui.QApplication(sys.argv)
    tankdaze = Tankdaze()
    sys.exit(app.exec_())
    
if __name__ == '__main__':
    main()




  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

こちらで試した環境(win8.1/python2.7.6.9/PyQt4.8.7)では、
DOSプロンプトからスクリプトを実行したところ、
keyイベントのprint文は期待通りのタイミングで出力されました。
(画像ファイルがないためそのまま実行できなかったので、画像ファイルは空欄にして実行しました)

端末のバッファ内に出力されずに残っている等が考えられますが、
試しに、print文の直後に sys.stdout.flush() を呼び出してみるとどうでしょう?

後、タイマーのイベントで呼ばれると想定されてるprint文に関しては、
タイマーのオブジェクトが何処にも参照されていないため、changeUI を抜けた後に、
ガベレージコレクタにより自動的に破棄されてしまいます。helloは出力されていませんでした。
loopTimer = QtCore.QTimer(self)
とすると、期待通り1秒間隔でgameloopを呼ぶタイマーを稼働出来ます。


print文の挙動は実行環境によっても動作が異なる可能性があります。
標準出力(Python内でsys.stdout)が他の場所に結び付けられている場合、
例えば、IDE等でデバッグ実行した場合等も変わってくるので、
実行環境の情報も併せて検索すると、類似の問題が見つかるかもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/10/25 16:52

    回答ありがとうございました。
    結局原因は、QTimerのコンストラクタにselfを渡していないことでした。
    引数としてselfを渡したところ、因果関係はよくわかりませんが、print文が正しく動作するようになりました

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る