在 pyqt5 中使用多个 windows 进行多线程更新

Multithreading updating with multiple windows in pyqt5

我正在尝试让一个计时器运行,我可以用它来更新多个 windows 中的值与 pyqt5。到目前为止,主 window 使用按钮打开另一个 windows,但是当我按下任一按钮时,它会崩溃。

from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QLabel, QVBoxLayout, QWidget,  QLineEdit
from PyQt5.QtCore import QRunnable, pyqtSlot, QTimer, QThreadPool
import sys

timer = QTimer()
timer.setInterval(1000) 

timer.start()

class Worker(QRunnable):

    def __init__(self, fn, *args, **kwargs):
        super(Worker, self).__init__()

        self.fn = fn
        self.args = args
        self.kwargs = kwargs

    @pyqtSlot()
    def run(self):

        self.fn(*self.args, **self.kwargs)

class AnotherWindow(QWidget):

    def __init__(self):
        super().__init__()
        self.x = 0
        layout = QVBoxLayout()
        self.label = QLabel("Another Window")
        layout.addWidget(self.label)
        self.line = QLineEdit(self)
        layout.addWidget(self.line)       
        self.setLayout(layout)
        timer.timeout.connect(self.update_line)
        
    def update_line(self):
        self.x += 1
        self.line.setText(str(self.x))

class AnotherWindow2(QWidget):

    def __init__(self):
        super().__init__()
        self.x = 0
        layout = QVBoxLayout()
        self.label = QLabel("Another Window2")
        layout.addWidget(self.label)
        self.line = QLineEdit(self)
        layout.addWidget(self.line)       
        self.setLayout(layout)
        timer.timeout.connect(self.update_line)
        
    def update_line(self):
        self.x += 3
        self.line.setText(str(self.x))
        
class MainWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        l = QVBoxLayout()
        button1 = QPushButton("Push for Window 1")
        button1.clicked.connect(self.show_new_window)
        l.addWidget(button1)

        button2 = QPushButton("Push for Window 2")
        button2.clicked.connect(self.show_new_window2)
        l.addWidget(button2)

        w = QWidget()
        w.setLayout(l)
        self.setCentralWidget(w)

        self.threadpool = QThreadPool()
        print("Multithreading with maximum %d threads" % self.threadpool.maxThreadCount())

    def show_new_window(self):
        worker = Worker(self.open_AnotherWindow)
        self.threadpool.start(worker)
        
    def open_AnotherWindow(self):
        self.w = AnotherWindow()
        self.w.show()

    def show_new_window2(self, checked):
        worker2 = Worker(self.open_AnotherWindow2)
        self.threadpool.start(worker2)
        
    def open_AnotherWindow2(self, checked):
        self.w2 = AnotherWindow2()
        self.w2.show()


app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()

打印出线程数。我也试过把

        self.timer = QTimer()
        self.timer.setInterval(1000) 
        self.timer.timeout.connect(self.update_line)
        self.timer.start()

在每个 AnotherWindow(2) init 函数中,但这也会崩溃。也许计时器应该以某种方式位于 mainwindow 中?尽管它的结果没有显示在那里。我看过关于多线程和 multiwindows 的教程,但没有看到关于每个线程都访问相同数据的 window 的教程。

为什么要使用多线程?线程不是神奇的解决方案,相反,如果不知道它们的缺点,那么它们带来的问题多于解决方案。在您的情况下,这是不必要的,因为您没有任何耗时的任务会阻塞 GUI。底线:在必要时使用工具,而不是在你想要的时候使用。

另一方面,您正在从 Qt 禁止的另一个线程创建 GUI,因为它不是线程安全的。

class AnotherWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.x = 0
        layout = QVBoxLayout()
        self.label = QLabel("Another Window")
        layout.addWidget(self.label)
        self.line = QLineEdit(self)
        layout.addWidget(self.line)
        self.setLayout(layout)
        timer = QTimer(self)
        timer.timeout.connect(self.update_line)
        timer.start()

    def update_line(self):
        self.x += 1
        self.line.setText(str(self.x))


class AnotherWindow2(QWidget):
    def __init__(self):
        super().__init__()
        self.x = 0
        layout = QVBoxLayout()
        self.label = QLabel("Another Window2")
        layout.addWidget(self.label)
        self.line = QLineEdit(self)
        layout.addWidget(self.line)
        self.setLayout(layout)
        timer = QTimer(self)
        timer.timeout.connect(self.update_line)
        timer.start()

    def update_line(self):
        self.x += 3
        self.line.setText(str(self.x))


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        l = QVBoxLayout()
        button1 = QPushButton("Push for Window 1")
        button1.clicked.connect(self.show_new_window)
        l.addWidget(button1)

        button2 = QPushButton("Push for Window 2")
        button2.clicked.connect(self.show_new_window2)
        l.addWidget(button2)

        w = QWidget()
        w.setLayout(l)
        self.setCentralWidget(w)

    def show_new_window(self):
        self.w = AnotherWindow()
        self.w.show()

    def show_new_window2(self):
        self.w2 = AnotherWindow2()
        self.w2.show()


app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()