QT Widgets的实时变化?

Real Time Change of QT Widgets?

我正在尝试创建一个简单的 class 背诵应用程序,它会从学生列表中随机选择。 可以用,但是我要实时变化,所以有点悬念谁被pick了

您可以在下面的插图视频中看到控制台实时更新名称,但 QtWidget 不会: https://dl.dropboxusercontent.com/s/rwcbhhj58tevshl/py003_pyqt_real_time_update_widget.mp4?dl=0

import sys
import os

from PySide2.QtCore import Qt
from PySide2.QtWidgets import QApplication, QMainWindow, QSpinBox, QWidget, QPushButton, QTextEdit, QVBoxLayout, QHBoxLayout, QLineEdit, QLabel
from PySide2.QtGui import QPixmap

from time import sleep, perf_counter
import time
import random


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
 
        self.setWindowTitle("Class Recitation")

        # Widget 
        root_img_path = 'img'
        self.image_list = []

        for root, dirs, files in os.walk(root_img_path):
            for f in files:

                img_path = os.path.join(root_img_path, f)
                first_name =  f.split('_')[0]
                last_name = f.split('_')[1]
                self.image_list.append( (img_path, first_name + " " + last_name ) ) 

        # creating label 
        self.label = QLabel(self) 
          
        # loading image 
        #self.pixmap = QPixmap('img/Eijirou_Kirishima_Portrait.png')
        self.pixmap = QPixmap(self.image_list[0][0])

        # adding image to label 
        self.label.setPixmap(self.pixmap) 

        self.name_label = QLabel()
        self.name_label.setText(self.image_list[0][1])

        self.pick_btn = QPushButton("Pick")
        self.pick_btn.setObjectName("Pick")
        self.pick_btn.clicked.connect(self.random_pick)


        # Layout Creations  

        hbox = QHBoxLayout()

        # hbox.addWidget(self.search_button)
        # hbox.addWidget(self.search_bar)

        vbox = QVBoxLayout()
        vbox.addWidget(self.label)
        vbox.addWidget(self.name_label)
        vbox.addWidget(self.pick_btn)

        # vbox.addWidget(self.result_text_edit)

        layout = QVBoxLayout()  
        layout.addLayout(hbox)
        layout.addLayout(vbox)

        widget = QWidget()
        widget.setLayout(layout)

        self.setCentralWidget(widget)

    def random_pick(self):

        choice_list = self.image_list
        time_started = time.perf_counter()
        counter = 0

        for x in range(0,10000):

            random_pick = random.choice(choice_list)
            self.name_label.setText(random_pick[1])
            self.label.setPixmap(random_pick[0]) 
            print (random_pick[1])
            sleep(counter)
            current_time = time.perf_counter()

            time_elapse = current_time - time_started
            counter += 0.0001 * (2**4)

            if time_elapse >= 5: 
                break

        return random_pick


    def change_name(self):

        self.name_label.setText("Name Changed")

app = QApplication(sys.argv)

window = MainWindow()
window.show()
app.exec_()

有解决办法吗?

time.sleep()

之后调用QApplication.processEvents()
def random_pick(self):
    ...
    for x in range(0,10000):
        ...
        sleep(counter)
        QApplication.processEvents()
        ...

或者使用 QTimer 代替,它也避免了任意循环并且是完全非阻塞的。

class MainWindow(QMainWindow):
    def __init__(self):
        ...
        self.pick_btn = QPushButton("Pick")
        self.pick_btn.setObjectName("Pick")
        <b>self.pick_btn.clicked.connect(self.start_timer)
        self.timer = QTimer(timeout=self.random_pick)
        ...</b>

    def start_timer(self):
        self.time_started = time.perf_counter()
        self.counter = 0
        self.timer.start(0)

    def random_pick(self):
        choice_list = self.image_list
        random_pick = random.choice(choice_list)
        self.name_label.setText(random_pick[1])
        self.label.setPixmap(random_pick[0])
        
        current_time = time.perf_counter()
        time_elapse = current_time - self.time_started
        self.counter += 0.0001 * (2**4)
        <b>self.timer.setInterval(self.counter * 1000)</b>

        if time_elapse >= 5:
            self.timer.stop()
            
        return random_pick