QMessageBox срабатывает только если окно программы находится в фокусе
Необходимо реализовать функции напоминания для пользователя.
Пользователь устанавливает текстовую информацию в поле , выбирает дату и время когда напомнить и это заносится в файл.json,
откуда в последующем считывается и про достижении нужного срока создается QMessageBox с напоминанием.
Сложность заключается в том, что при переводе фокуса на другое окно функция не срабатывает, до момента пока пользователь не вернётся обратно к программе.
Интересует как это победить и чтобы напоминания срабатывали даже есть пользователь переключился на другие приложения?
main.py:
import json
import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QLineEdit, QDateTimeEdit, QPushButton, \
QMessageBox, QApplication
from PyQt6.QtCore import Qt, QDateTime, QTimer
from PyQt6.QtGui import QIcon
RECORDS_FILE = 'records.json'
class ReminderApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Reminder App")
self.setWindowIcon(QIcon('AH2_icon.png'))
layout = QVBoxLayout()
# Текстовое поле для ввода информации
self.info_input = QLineEdit()
layout.addWidget(QLabel("Тестовая информация:"))
layout.addWidget(self.info_input)
# Выбор даты и времени для напоминания
self.datetime_picker = QDateTimeEdit()
self.datetime_picker.setCalendarPopup(True)
self.datetime_picker.setDateTime(QDateTime.currentDateTime())
layout.addWidget(QLabel("Дата и время напоминания:"))
layout.addWidget(self.datetime_picker)
# Кнопка для создания напоминания
self.reminder_button = QPushButton("Создать напоминание")
self.reminder_button.clicked.connect(self.create_reminder)
layout.addWidget(self.reminder_button)
self.setLayout(layout)
# Таймер для проверки напоминаний
self.timer = QTimer()
self.timer.timeout.connect(self.check_reminders)
self.timer.start(1000) # каждую секунду
def create_reminder(self):
info = self.info_input.text()
datetime = self.datetime_picker.dateTime().toString('yyyy-MM-dd HH:mm:ss')
# Сохранение записи в базу данных
save_record(info, datetime)
# Очистка тестового поля
self.datetime_picker.clear()
def check_reminders(self):
records = load_records()
current_datetime = QDateTime.currentDateTime()
for record in records:
reminder_datetime = QDateTime.fromString(record['datetime'], 'yyyy-MM-dd HH:mm:ss')
if current_datetime >= reminder_datetime:
# Всплывающее окно для напоминания
reminder_msg_box = QMessageBox()
reminder_msg_box.setWindowTitle("Напоминание")
reminder_msg_box.setText("Напоминаю: " + record['info'])
reminder_msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)
reminder_msg_box.exec()
# Удаление выполненного напоминания из базы данных
records.remove(record)
# Сохранение обновленной базы данных
save_records(records)
def save_record(info, datetime):
records = load_records()
records.append({"info": info, "datetime": datetime})
save_records(records)
def save_records(records):
with open(RECORDS_FILE, 'w') as file:
json.dump(records, file)
def load_records():
try:
with open(RECORDS_FILE, 'r') as file:
records = json.load(file)
except FileNotFoundError:
records = []
return records
if __name__ == '__main__':
app = QApplication(sys.argv)
window = ReminderApp()
window.show()
sys.exit(app.exec())
Ответы (2 шт):
Могу предложить использовать уведомления, если пишите для окон. Вот можете рассмотреть мой шуточный код, а дальше доработать и адаптировать если он вам подойдёт.
import ctypes
from ctypes import Structure, c_uint, sizeof, byref
from ctypes.wintypes import HWND, UINT
import random
class NOTIFYICONDATA(Structure):
_fields_ = [
("cbSize", c_uint),
("hWnd", HWND),
("uID", UINT),
("uFlags", UINT),
("uCallbackMessage", UINT),
("hIcon", HWND),
("szTip", ctypes.c_wchar * 128),
("dwState", UINT),
("dwStateMask", UINT),
("szInfo", ctypes.c_wchar * 256),
("uVersion", UINT),
("szInfoTitle", ctypes.c_wchar * 64),
("dwInfoFlags", UINT),
("guidItem", ctypes.c_byte * 16),
("hBalloonIcon", HWND),
]
class PatsanNotification:
def __init__(self):
title = "Patsan Notification"
self.nid = NOTIFYICONDATA()
self.nid.cbSize = sizeof(NOTIFYICONDATA)
self.nid.hWnd = None
self.nid.uID = 0
self.nid.uFlags = 0x00000010 | 0x00000001 | 0x00000200
self.nid.uCallbackMessage = 1024
self.nid.szTip = title
self.nid.szInfoTitle = title
self.nid.dwState = 0
self.nid.dwStateMask = 0
self.nid.uVersion = 2000
self.nid.dwInfoFlags = 1
self.shell32 = ctypes.windll.shell32
self.text_list = ["Сильный пацан знает, что его сила в том, чтобы не злоупотреблять ею.",
"Друзья – это семья, которую мы сами выбираем.",
"Победа, которая достигнута честным путем, вдвойне сладка.",
"Ваша первая обязанность – к самому себе быть честным. Мораль – это прежде всего самоконтроль.",
"Если не можешь быть хорошим примером, будь забавным предостережением.",
"Хорошо там, где нас нет, а там, где мы, там не очень."
]
def show_notification(self):
random_text = random.choice(self.text_list)
self.nid.szInfo = random_text
self.shell32.Shell_NotifyIconW(0, byref(self.nid))
if __name__ == "__main__":
# Создаем объект класса PatsanNotification
patsan_notifier = PatsanNotification()
patsan_notifier.show_notification()
Попробуйте так:
import json
import sys
'''
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, \
QLineEdit, QDateTimeEdit, QPushButton, QMessageBox, QApplication
from PyQt6.QtCore import Qt, QDateTime, QTimer
from PyQt6.QtGui import QIcon
'''
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *
RECORDS_FILE = 'records.json'
class ReminderApp(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Reminder App")
self.setWindowIcon(QIcon('AH2_icon.png'))
layout = QVBoxLayout()
# Текстовое поле для ввода информации
self.info_input = QLineEdit()
# +++
self.label = QLabel("Тестовая информация:") # +
layout.addWidget(self.label)
layout.addWidget(self.info_input)
# Выбор даты и времени для напоминания
self.datetime_picker = QDateTimeEdit()
self.datetime_picker.setCalendarPopup(True)
self.datetime_picker.setDateTime(QDateTime.currentDateTime())
# +++
self.datetime_picker.setDisplayFormat("yyyy-MM-dd HH:mm:ss") # +
layout.addWidget(QLabel("Дата и время напоминания:"))
layout.addWidget(self.datetime_picker)
# Кнопка для создания напоминания
self.reminder_button = QPushButton("Создать напоминание")
self.reminder_button.clicked.connect(self.create_reminder)
layout.addWidget(self.reminder_button)
self.setLayout(layout)
# Таймер для проверки напоминаний
self.timer = QTimer()
self.timer.timeout.connect(self.check_reminders)
self.timer.start(1000)
def create_reminder(self):
info = self.info_input.text()
datetime = self.datetime_picker.dateTime().toString(
'yyyy-MM-dd HH:mm:ss')
# Сохранение записи в базу данных
save_record(info, datetime)
# Очистка тестового поля
self.datetime_picker.clear()
# +++
self.datetime_picker.setFocus() # +
def check_reminders(self):
records = load_records()
current_datetime = QDateTime.currentDateTime()
# +++
self.label.setText(
f'Текущая дата и время: {current_datetime.toString("yyyy-MM-dd hh:mm:ss")}')
for record in records:
reminder_datetime = QDateTime.fromString(
record['datetime'], 'yyyy-MM-dd HH:mm:ss')
if current_datetime >= reminder_datetime:
# Всплывающее окно для напоминания
# reminder_msg_box = QMessageBox()
# -------------------------------------------> vvvv <-----------------------------
reminder_msg_box = QMessageBox(self) # !!! +++
reminder_msg_box.setWindowTitle("Напоминание")
reminder_msg_box.setText(
f"Напоминаю: {record['info']} \n{record['datetime']}")
reminder_msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)
# reminder_msg_box.exec()
# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
reminder_msg_box.setWindowFlags( # !!! +++
Qt.WindowStaysOnTopHint | Qt.Tool) # !!! +++
reminder_msg_box.show() # !!! +++
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Удаление выполненного напоминания из базы данных
records.remove(record)
# Сохранение обновленной базы данных
save_records(records)
def save_record(info, datetime):
records = load_records()
records.append({"info": info, "datetime": datetime})
save_records(records)
def save_records(records):
with open(RECORDS_FILE, 'w') as file:
json.dump(records, file)
def load_records():
try:
with open(RECORDS_FILE, 'r') as file:
records = json.load(file)
except FileNotFoundError:
records = []
return records
if __name__ == '__main__':
app = QApplication(sys.argv)
app.setStyle(QStyleFactory.create("Fusion")) # +
app.setFont(QtGui.QFont("Times", 12, QtGui.QFont.Bold)) # +
window = ReminderApp()
window.resize(400, 200) # +
window.show()
sys.exit(app.exec())

