[Python] After running a PyQt5 application for an extended period, some buttons stop responding

Discussão em 'Python' iniciado por Stack, Março 26, 2025.

  1. Stack

    Stack Membro Participativo

    I'm running this on a Raspberry Pi. The application transitions through pages in the following order: Page1 → Page2 → Page3.

    On Page1, pressing a button takes you to Page2.

    On Page2, pressing a button starts communication.

    If the communication is successful, it moves to Page3.

    On Page3, after 20 seconds, it automatically returns to Page1.

    On Page1, there is periodic communication (once every few tens of seconds), and the received text is displayed scrolling at the bottom of the screen. Regardless of the current page, the app automatically returns to Page1 after 10 seconds.

    Everything works fine at first, but after about two weeks of continuous operation, the button on Page1 stops responding. However, even when the button is unresponsive, the text at the bottom of the screen still scrolls with the received communication data, so I don’t think the app is completely frozen.

    I've been thinking about the cause for a while, but I still can't figure it out.

    import sys
    import requests
    from PyQt5.QtCore import Qt, QTimer, QRect, QEvent
    from PyQt5.QtGui import QFont, QPixmap, QPainter, QPen, QBrush, QKeyEvent
    from PyQt5.QtWidgets import (
    QApplication,
    QMainWindow,
    QStackedWidget,
    QWidget,
    QLabel,
    QPushButton,
    QVBoxLayout,
    QHBoxLayout,
    QMessageBox,
    )


    class MainWindow(QMainWindow):
    def __init__(self):
    super().__init__()
    self.stacked_widget = QStackedWidget(self)
    self.setCentralWidget(self.stacked_widget)

    self.screen_width = QApplication.desktop().width()
    self.screen_height = QApplication.desktop().height()

    self.pages = {}
    for PageClass in (Page1, Page2, Page3):
    page_instance = PageClass(self)
    self.pages[PageClass.__name__] = page_instance
    self.stacked_widget.addWidget(page_instance)

    self.show_page("Page1")

    self.input_data = ""

    self.remaining_time = 20
    self.inactivity_timer = QTimer(self)
    self.inactivity_timer.timeout.connect(self.countdown)
    self.inactivity_timer.start(1000)

    self.installEventFilter(self)

    def show_page(self, page_name):
    page = self.pages.get(page_name)
    if page is not None:
    self.stacked_widget.setCurrentWidget(page)
    self.reset_timer()

    if page_name == "Page2":
    self.input_data = ""
    self.pages["Page2"].reset_page()

    def reset_timer(self):
    self.remaining_time = 20

    def countdown(self):
    if self.remaining_time > 0:
    self.remaining_time -= 1
    else:
    self.show_page("Page1")

    def return_to_page1(self):
    self.show_page("Page1")

    def eventFilter(self, obj, event):
    if event.type() == QEvent.KeyPress:
    self.reset_timer()
    key_event = event

    current_page = self.stacked_widget.currentWidget()

    if current_page == self.pages["Page2"]:
    if key_event.key() in (Qt.Key_Return, Qt.Key_Enter):
    p2 = self.pages["Page2"]
    p2.process_text(self.input_data)
    self.input_data = ""
    else:
    ch = key_event.text()
    if ch:
    self.input_data += ch

    return super().eventFilter(obj, event)

    elif event.type() == QEvent.MouseButtonPress:
    self.reset_timer()

    return super().eventFilter(obj, event)

    def close_app(self):

    QApplication.quit()


    class BasePage(QWidget):
    def __init__(self, main_window: MainWindow):
    super().__init__()
    self.main_window = main_window
    self.setStyleSheet("background-color: white;")


    class Page1(BasePage):
    def __init__(self, main_window: MainWindow):
    super().__init__(main_window)

    self.v_layout = QVBoxLayout(self)
    self.setLayout(self.v_layout)

    self.background_label = QLabel(self)
    self.background_label.setGeometry(
    0, 0, main_window.screen_width, main_window.screen_height
    )
    self.background_label.setStyleSheet("background-color: white;")
    self.background_label.setScaledContents(True)

    self.msg_label = QLabel("Page1", self)
    self.msg_label.setStyleSheet("background-color: transparent; font-size: 54px;")
    self.msg_label.setAlignment(Qt.AlignCenter)

    self.start_button = QPushButton("start", self)
    self.start_button.setStyleSheet(
    """
    font-size: 54px;
    width: 300px;
    height: 100px;
    background-color: #8B0000;
    color: white;
    border: none;
    border-radius: 20px;
    """
    )
    self.start_button.clicked.connect(lambda: self.main_window.show_page("Page2"))

    self.v_layout.addWidget(self.msg_label, 0, Qt.AlignCenter)
    self.v_layout.addWidget(self.start_button, 0, Qt.AlignCenter)

    self.news_container = QWidget(self)
    self.news_container.setGeometry(
    0, self.main_window.screen_height - 150, self.main_window.screen_width, 80
    )
    self.news_container.setStyleSheet("background-color: transparent;")
    self.news_label = QLabel(self.news_container)
    self.news_label.setGeometry(0, 0, 100, 80)
    self.news_label.setStyleSheet("background-color: transparent; font-size: 54px;")
    self.news_label.setAlignment(Qt.AlignVCenter | Qt.AlignLeft)

    self.news_text = "Test"
    self.text_x = 0
    self.text_width = 0
    self.move_speed = 2

    self.update_news_text()

    self.scroll_timer = QTimer(self)
    self.scroll_timer.timeout.connect(self.start_text_scroll)
    self.scroll_timer.start(30)

    def update_news_text(self):
    try:
    resp = requests.post(
    "https://...",
    timeout=3,
    )
    if resp.ok:
    data = resp.json()
    self.news_text = data.get("news", "Failed")
    else:
    self.news_text = "Failed"
    except Exception as e:
    self.news_text = "Failed"

    self.news_label.setText(self.news_text)
    self.news_label.adjustSize()
    font_metrics = self.news_label.fontMetrics()
    self.text_width = font_metrics.width(self.news_text)
    self.news_label.setFixedWidth(self.text_width)
    self.text_x = -self.text_width
    self.news_label.move(self.text_x, 0)

    def start_text_scroll(self):
    if self.text_x + self.text_width < 0:
    self.update_news_text()
    self.text_x = self.main_window.screen_width
    return


    self.text_x -= self.move_speed
    self.news_label.move(self.text_x, 0)


    class Page2(BasePage):
    def __init__(self, main_window: MainWindow):
    super().__init__(main_window)
    layout = QVBoxLayout(self)
    self.setLayout(layout)
    self.is_processing = False
    self.label = QLabel("Page2\nPlease enter text.", self)
    self.label.setStyleSheet("background-color: transparent; font-size: 54px;")
    layout.addWidget(self.label, 0, Qt.AlignCenter)

    def process_text(self, text):
    if self.is_processing:
    return
    self.is_processing = True
    try:
    response = requests.post(
    "https://",
    timeout=3,
    )

    if response.status_code == 200:
    result = response.text.split(",")
    if result[0] == "success":

    _ = requests.get(
    "http://localhost/",
    timeout=3,
    )
    self.main_window.show_page("Page3")
    except Exception as e:
    self.label = "Please enter it again"
    self.is_processing = False
    # self.main_window.show_page("Page3")

    def reset_page(self):
    self.label.setText("Please enter text")
    self.main_window.barcode_data = ""


    class Page3(BasePage):
    def __init__(self, main_window: MainWindow):
    super().__init__(main_window)
    layout = QVBoxLayout(self)
    self.setLayout(layout)

    self.label = QLabel("page3", self)
    self.label.setStyleSheet("background-color: transparent; font-size: 54px;")
    layout.addWidget(self.label, 0, Qt.AlignCenter)

    def showEvent(self, event):
    super().showEvent(event)
    self.move_to_page1()

    def move_to_page1(self):
    QTimer.singleShot(10000, self.main_window.return_to_page1)


    def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())


    if __name__ == "__main__":
    main()

    Continue reading...

Compartilhe esta Página