Я хочу создать простой графический интерфейс браузера для учебных целей с PyQt5. Я хочу, чтобы в строке состояния был текст «Online». Если пользователь щелкнет в другом месте в браузере, и приложение потеряет фокус, в строке состояния появится сообщение, указывающее на это, и через несколько секунд браузер изменит URL-адрес на Google.

Если я запускаю следующий код, все работает нормально, как и ожидалось, когда приложение теряет фокус, оно переходит в Google. Однако сообщение «Приложение потеряло фокус ...» не появляется в строке состояния. Он просто пропускает эту строку. Если я удалю строки seturl и time.sleep, сценарий изменит текст, как ожидалось.

Почему он пропускает эту строку? (Строка 55)

import sys
import time
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtCore import *
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QMessageBox, QFrame ,QMainWindow, QLabel
from PyQt5.QtWebEngineWidgets import *

class VLine(QFrame):
    # a simple VLine, like the one you get from designer
    def __init__(self):
        super(VLine, self).__init__()
        self.setFrameShape(self.VLine|self.Sunken)

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setFocus()
        app.focusChanged.connect(self.on_focusChanged)

        self.browser = QWebEngineView()
        self.browser.setContextMenuPolicy(Qt.PreventContextMenu)
        self.browser.setUrl(QUrl('http://stackoverflow.com'))
        self.setCentralWidget(self.browser)
        self.showMaximized()
        self.date = QDate.currentDate()
        
        font =  QFont('Arial', 16, QFont.Bold)
        self.statusBar().setFont(font)

        timer = QTimer(self)
        timer.timeout.connect(self.showTime)
        timer.start(1000)

        self.lbl1 = QLabel(self)
        self.lbl1.setStyleSheet('border: 0; color:  red;')
        self.lbl1.setFont(font)
        

        self.statusBar().reformat()
        self.statusBar().setStyleSheet('border: 0; background-color: #FFF8DC;')
        self.statusBar().setStyleSheet("QStatusBar::item {border: none;}") 
        
        self.statusBar().addPermanentWidget(VLine())    # <---
        self.statusBar().addPermanentWidget(self.lbl1)
        self.statusBar().addPermanentWidget(VLine())

    def showTime(self):
        current_time = QTime.currentTime()
        label_time = current_time.toString('hh:mm:ss')
        self.statusBar().showMessage('Time: ' + label_time + ' || Date: ' + self.date.toString('dd.MM.yyyy'))
    
    def on_focusChanged(self):
        if self.isActiveWindow() == False:
            print(f"\nwindow is the active window: {self.isActiveWindow()}")
            self.lbl1.setText('Application lost focus. Returning to Google in 5 seconds')
            time.sleep(5)
            self.browser.setUrl(QUrl('http://google.com'))
            self.lbl1.setText('Online')
        else:
            print(f"window is the active window: {self.isActiveWindow()}")
            self.lbl1.setText('Online')

app = QApplication(sys.argv)
QApplication.setApplicationName('Browser')
window = MainWindow()
app.exec_()
0
Alex TheWebGroup 20 Май 2021 в 14:05

1 ответ

Лучший ответ

Вы не понимаете, как работает сигнал focusChanged: он излучает сигнал об изменении фокуса внутри программы.

Вам нужно переопределить changeEvent из окна и перехватить тип события ActivationChange.

class MainWindow(QMainWindow):
    # ...
    def changeEvent(self, event):
        if event.type() == event.ActivationChange:
            # ...

Тем не менее, НИКОГДА не добавляйте функцию блокировки в основной поток.

Удалите time.sleep и никогда не думайте снова использовать его для такого рода вещей.

Добавьте функцию для этого перенаправления и создайте QTimer, который вы можете запускать при потере фокуса (и останавливать, если восстанавливаете его снова до истечения тайм-аута).

class MainWindow(QMainWindow):
    def __init__(self):
        # ...
        self.focusLostTimer = QTimer(
            interval=5000, singleShot=True, timeout=self.focusRedirect)

    def focusRedirect(self):
        self.browser.setUrl(QUrl('http://google.com'))

    def changeEvent(self, event):
        if event.type() == event.ActivationChange:
            if not self.isActiveWindow():
                self.focusLostTimer.start()
            else:
                self.focusLostTimer.stop()
3
musicamante 20 Май 2021 в 11:30