Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
152 views
in Technique[技术] by (71.8m points)

python - 如何使用PyQt5 for Python显示计时器(How to display a timer using PyQt5 for Python)

I'm making a game where I would like a timer to be displayed on the screen after the user clicks on 'NEW GAME', to keep track of how long they've been playing.

(我正在制作一个游戏,希望在用户单击“新游戏”后在屏幕上显示计时器,以跟踪他们玩了多长时间。)

I have a class that runs the timer fine by itself, but when I incorporate it into the rest of my game and then on top of that, try to display the updated values of the timer, no values in the UI are updated and the printout of the timer doesn't even occur in the terminal.

(我有一个可以自行运行计时器的类,但是当我将其合并到游戏的其余部分中,然后再在其上进行操作时,请尝试显示计时器的更新值,UI中的任何值都不会更新并且不会打印输出的计时器甚至不在终端中发生。)

I've tried running the timer in the same thread as the game-setup process and I've also tried creating a new thread to run the timer but neither work.

(我尝试在与游戏设置过程相同的线程中运行计时器,并且还尝试创建一个新的线程来运行计时器,但均无效。)

The game loads up and functions fine, with the exception of the timer not counting upwards and not displaying the updated timer values.

(游戏加载并正常运行,但计时器不向上计数且不显示更新的计时器值。)

Where am I going wrong here?

(我在哪里错了?)

Here is my standalone Timer class, which again, works fine by itself.

(这是我的独立Timer类,再次可以正常工作。)

from PyQt5 import QtCore
import sys

def startThread(functionName, *args, **kwargs):
    print(args)
    if len(args) == 0:
        t = threading.Thread(target=functionName)
    else:
        try:
            t = threading.Thread(target=functionName, args=args, kwargs=kwargs)
        except:
            try:
                if args is None:
                    t = threading.Thread(target=functionName, kwargs=kwargs)
            except:
                t = threading.Thread(target=functionName)
    t.daemon = True
    t.start()

class Timer(object):
    app = QtCore.QCoreApplication(sys.argv)

    def __init__(self):
        super(Timer, self).__init__()

    def start_timer(self):
        print("Starting timer...")
        Timer.timer = QtCore.QTimer()
        Timer.time = QtCore.QTime(0, 0, 0)
        Timer.timer.timeout.connect(self.tick)
        Timer.timer.start(1000)
        Timer.app.exec_()

    def tick(self):
        Timer.time = Timer.time.addSecs(1)
        self.update_UI('%s' % Timer.time.toString("hh:mm:ss"))

    def update_UI(self, text_string):
        print(text_string)
        # This is where the text would be sent to try and update the UI

Timer().start_timer()

This is more or less how my game-setup class is structured - currently I'm showing the version that uses threading:

(这或多或少是我的游戏设置类的结构方式-当前,我正在显示使用线程的版本:)

class BuildUI(PyQt5.QtWidgets.QMainWindow, Ui_game):

    def __init__(self):
        super(BuildUI, self).__init__()
        self.setupUi(self)
        self.easy_mode = 38
        self.user_available_cells = []
        self.start_easy_game.triggered.connect(lambda: self.setup_game(self.easy_mode))

    def setup_game(self, hidden_count):
        def create_game_board():
            startThread(Timer().start_timer)
            self.game = BuildGame()
                    #The BuildGame class is not deliberately not shown

        startThread(create_game_board)

class GAME(object):
    def __init__(self):
        GAME.app = PyQt5.QtWidgets.QApplication(sys.argv)
        GAME.UI = BuildUI()
        GAME.UI.show()
        GAME.app.exec_()

def main():
    GAME()

if __name__ == '__main__':
    main()
  ask by NLee23 translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The key to getting this to work is by using signals.

(使它起作用的关键是使用信号。)

Leaving the Timer class exactly as it is, the only modifications to be done are in the initialization of the GAME class, a signal needs to be added at the beginning of the BuildUI class and then using emit() to trigger that signal just before the self.game = BuildGame() call.

(保留Timer类的原样,唯一要做的修改是在GAME类的初始化中,需要在BuildUI类的开始处添加一个信号,然后在开始之前使用Emit()触发该信号。 self.game = BuildGame()调用。)

class BuildUI(PyQt5.QtWidgets.QMainWindow, sudoku_ui.Ui_sudoku_game):
    # This signal just triggers a msgbox to display, telling the user the game is loading
    process_start = PyQt5.QtCore.pyqtSignal()
    # this is called to automatically close the msgbox window       
    process_finished = PyQt5.QtCore.pyqtSignal()
    # This signal, when called will start the timer
    start_game_timer = PyQt5.QtCore.pyqtSignal()

    def __init__(self):
        super(BuildUI, self).__init__()
        self.setupUi(self)
        self.easy_mode = 38
        self.user_available_cells = []
        self.start_easy_game.triggered.connect(lambda: self.setup_game(self.easy_mode))

    def setup_game(self, hidden_count):
        def create_game_board():
            self.game = BuildGame()
            # Now that the game is built, the timer can start
            # This is the emit which will start the timer
            GAME.UI.start_game_timer.emit()

        startThread(create_game_board)

class GAME(object):
    def __init__(self):
        GAME.app = PyQt5.QtWidgets.QApplication(sys.argv)
        GAME.UI = BuildUI()
        GAME.dialog_box = MsgPrompt()

        # This is the key right here - initializing the timer class
        GAME.timer = Timer()
        # This line below attaches a function to the emit() call - which will kick off the timer
        GAME.UI.start_game_timer.connect(GAME.timer.start_timer)
        # The below referenced class is deliberately omitted from this post
        GAME.UI.process_start.connect(GAME.dialog_box.show_dialog_box)
        GAME.UI.process_finished.connect(GAME.dialog_box.hide_dialog_box)
        GAME.UI.show()
        GAME.app.exec_()

def main():
    GAME()

if __name__ == '__main__':
    main()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...