Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/11: Рейтинг темы: голосов - 11, средняя оценка - 4.73
 Аватар для adamblack
4 / 2 / 2
Регистрация: 19.10.2021
Сообщений: 40

Pyside2 Создание виджета уведомления в стиле Gnome на Windows

30.10.2021, 15:47. Показов 2486. Ответов 3

Студворк — интернет-сервис помощи студентам
Всем доброго здравия

Решил написать простое решение для кастомных уведомлений на windows в стиле gnome.
За основу взял чужое решение, исправил ошибки и переделал под себя.
Прошу помощи в нахождении ошибки в коде. При вызове функции hide() процесс продолжает выполнение.
Python
1
2
3
4
5
6
7
def hide(self):
        # Если виджет прозрачный, то скрываем его
        print('hide')
        self.timer.stop()
        self.animation.stop()
        self.close()
        #exit()
Тобишь self.close() срабатывает, но не завершает процесс.

p.s. в hide поставил в конце exit(), но это не решение если я буду прикручивать данный класс куда нибудь.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# This Python file uses the following encoding: utf-8
import sys
import os
 
from PySide2.QtWidgets import QWidget, QLabel, QGridLayout, QApplication 
from PySide2.QtCore import QTimer, QPropertyAnimation, Qt, QRect
from PySide2.QtGui import QPainter, QBrush, QColor, QBackingStore
 
class Info(QWidget):
    def __init__(self, head="Неизвестный источник", text = "", parent = None):
        super().__init__(parent)
 
        self.text = text
        self.head = head
        self.label = QLabel(head)                # Label с сообщением
        self.label2 = QLabel(text)
        self.adjustSize()
        self.layout = QGridLayout()                  # Размещение для лейбла
        self.animation = QPropertyAnimation(self)    # Свойство анимации для всплывающего сообщения
                         # Свойства полупрозрачности виджета
        self.timer = QTimer()                        # Таймер, по которому виджет будет скрыт
 
        self.setWindowFlags(Qt.FramelessWindowHint |       # Отключаем оформление окна
                   Qt.Tool |                               # Отменяем показ в качестве отдельного окна
                   Qt.WindowStaysOnTopHint)                # Устанавливаем поверх всех окон
        self.setAttribute(Qt.WA_TranslucentBackground)     # Указываем, что фон будет прозрачным
        self.setAttribute(Qt.WA_ShowWithoutActivating)     # При показе, виджет не получается фокуса автоматически
 
 
        self.animation.setTargetObject(self)                 # Устанавливаем целевой объект анимации
        self.animation.setPropertyName(b'windowOpacity')       # Устанавливаем анимируемое свойство
 
        # Настройка текста уведомления
        self.label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) # Устанавливаем по центру
        #self.label2.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) # Устанавливаем по центру
        # И настраиваем стили
        self.label.setStyleSheet("QLabel { color : white; "
                            "margin-top: 6px;"
                            "margin-bottom: 6px;"
                            "margin-left: 10px;"
                            "margin-right: 10px;"
                            "padding-bottom: 5px;"
                            "font-weight: 600;"
                            "border: none;"
                            "border-bottom: 1px solid white;"
                            "border-radius: 5px; }")
        self.label2.setStyleSheet("QLabel { color : white; "
                            "margin-top: 6px;"
                            "margin-bottom: 6px;"
                            "margin-left: 10px;"
                            "margin-right: 10px; }")
 
        # Производим установку текста в размещение, ...
        self.layout.addWidget(self.label, 0, 0)
        self.layout.addWidget(self.label2, 1, 0)
        self.setLayout(self.layout)  # которое помещаем в виджет
        self.adjustSize()
        # По сигналу таймера будет произведено скрытие уведомления, если оно видимо
        self.timer.timeout.connect(self.hideAnimation)
 
    def paintEvent(self, event):
        painter = QPainter(self)        
        painter.setRenderHint(QPainter.Antialiasing)    # Включаем сглаживание
 
        # Подготавливаем фон. rect() возвращает внутреннюю геометрию виджета уведомления, по содержимому
        roundedRect = QRect()
        roundedRect.setX(self.rect().x() + 5)
        roundedRect.setY(self.rect().y() + 5)
        roundedRect.setWidth(self.rect().width() - 10)
        roundedRect.setHeight(self.rect().height() - 10)
 
        # Кисть настраиваем на чёрный цвет в режиме полупрозрачности 180 из 255
        painter.setBrush(QBrush(QColor(0,0,0,180)))
        painter.setPen(Qt.NoPen)     # Край уведомления не будет выделен
 
        # Отрисовываем фон с закруглением краёв в 10px
        painter.drawRoundedRect(roundedRect, 6, 6) 
 
    def show(self):
        self.setWindowOpacity(0.0)          # Устанавливаем прозрачность в ноль
 
        self.animation.setDuration(350)     # Настраиваем длительность анимации
        self.animation.setStartValue(0.0)   # Стартовое значение будет 0 (полностью прозрачный виджет)
        self.animation.setEndValue(1.0)     # Конечное - полностью непрозрачный виджет
 
        self.setGeometry(QApplication.desktop().availableGeometry().width() - 36 - self.width() + QApplication.desktop().availableGeometry().x(),
                    QApplication.desktop().availableGeometry().height() - 36 - self.height() + QApplication.desktop().availableGeometry().y(),
                    self.width(),
                    self.height())
 
        QWidget.show(self)              # Отображаем виджет, который полностью прозрачен
 
        self.animation.start()      # И запускаем анимацию
        self.timer.start(3000)      # А также стартуем таймер, который запустит скрытие уведомления через 3 секунды
 
 
    def hideAnimation(self):
        self.timer.stop()                   # Останавливаем таймер
        self.timer.timeout.disconnect(self.hideAnimation)
        self.animation.setDuration(750)     # Настраиваем длительность анимации
        self.animation.setStartValue(1.0)   # Стартовое значение будет 1 (полностью непрозрачный виджет)
        self.animation.setEndValue(0.0)     # Конечное - полностью прозрачный виджет
        self.timer.timeout.connect(self.hide)
        self.timer.start(3000)
        self.animation.start()              # И запускаем анимацию
 
 
    def hide(self):
        # Если виджет прозрачный, то скрываем его
        print('hide')
        self.timer.stop()
        self.animation.stop()
        self.close()
        #exit()
 
    def __repr__(self):
        return 'Info class'
 
def textSizeCorrection(text):
    maxWidth = 50
    returnText = ""
    size = 0
    for word in text:
        if len(word) > maxWidth:
            if "\n" in word:
                size = 0
            for letter in word:
                returnText += letter
                size += 1
                if size == maxWidth:
                    returnText += "\n"
                    size = 0
        else:
            if "\n" in word:
                returnText += word
                size = len(word)
 
            elif len(word)+size > maxWidth:
                returnText += "\n" + word
                size = len(word)
            elif len(word)+size <= maxWidth:
                returnText += word
                size += len(word)
    return returnText
 
if __name__ == "__main__":
    # app disexec теперь на pyqt
    app = QApplication(sys.argv)
    app.setStyle('Fusion')
 
    head = "System notification: Python"
    text = textSizeCorrection("Hello World! I am a system notification with no unique feature, I just show up and disappear after 3 seconds.\nThe implemsentation is done in the style of Gnome push-notification.".replace(" ", " &|").split("&|"))
 
    window = Info(head,text)
    window.show()  
 
    sys.exit(app.exec_())

UPD: Еще хотел уточнить у опытных. Почему выводится сообщение в консольке:
Code
1
2
3
4
main.py:86: DeprecationWarning: QDesktopWidget.availableGeometry(int screen) const is deprecat
  self.setGeometry(QApplication.desktop().availableGeometry().width() - 36 - self.width() + QA
main.py:87: DeprecationWarning: QDesktopWidget.availableGeometry(int screen) const is deprecat
  QApplication.desktop().availableGeometry().height() - 36 - self.height() + QApplication.desk
Добавлено через 1 час 25 минут
Хотелось бы дополнить вопрос.

Верно ли решение добавить:
Python
1
self.mouseReleaseEvent=lambda event:self.hideAnimation()
Для исчезновения уведомления при нажатии.

Не будет ли конфликтовать два коннекта на одну функцию?

Добавлено через 35 минут
Ладно с функцией исчезновения уведомления по нажатию на виджет я разобрался:

Python
1
2
def mouseReleaseEvent(self, QMouseEvent):
        self.hide()
А вот решить проблему с self.close() до сих пор не получилось
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
30.10.2021, 15:47
Ответы с готовыми решениями:

Не работает команда pyside2-uic (Windows)
Помогите решить проблему, пожалуйста. После установки pyside2 - консоль Windows не видит команду pyside2-uic. Есть ли решение данной...

Как навести мышку на x,y внутри виджета относительно 0,0 виджета (левого верхнего угла виджета)?
Как навести мышку на x,y внутри виджета относительно 0,0 этого виджета (левого верхнего угла виджета)? Или, как получить координаты x,y...

После обновления Windows 7 интерфейс становится в стиле Windows 98
После обновления windows 7, интерфейс становится аля 98. После применения тем ни чего не меняется, при включении режима наилучшего вида...

3
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
30.10.2021, 17:43
Лучший ответ Сообщение было отмечено adamblack как решение

Решение

у вас флаг Qt.Tool стоит
https://qtcentre.org/threads/11713-Qt-Tool
добавьте
Python
1
        self.setAttribute(Qt.WA_QuitOnClose);
если хотите приложение остановить, или флаг уберите
1
 Аватар для adamblack
4 / 2 / 2
Регистрация: 19.10.2021
Сообщений: 40
30.10.2021, 17:52  [ТС]
vic5710, спасибо Вам большое!

А на счет предупреждения в консоле не подскажите?
Цитата Сообщение от adamblack Посмотреть сообщение
UPD: Еще хотел уточнить у опытных. Почему выводится сообщение в консольке:

main.py:86: DeprecationWarning: QDesktopWidget.availableGeometry(int screen) const is deprecat
self.setGeometry(QApplication.desktop(). availableGeometry().width() - 36 - self.width() + QA
main.py:87: DeprecationWarning: QDesktopWidget.availableGeometry(int screen) const is deprecat
QApplication.desktop().availableGeometry ().height() - 36 - self.height() + QApplication.desk
0
963 / 718 / 276
Регистрация: 10.12.2016
Сообщений: 1,764
30.10.2021, 17:56
что-то типа устарело, может быть исключено в будущем
поведение вашего виджета правильное - уведомление не должно закрывать приложение
Python
1
2
3
4
5
6
7
8
9
10
11
12
if __name__ == "__main__":
    # app disexec теперь на pyqt
    app = QApplication(sys.argv)
    app.setStyle('Fusion')
    w = QWidget()#по закрытию закроется приложение
    w.show()
    head = "System notification: Python"
    text = textSizeCorrection("Hello World! I am a system notification with no unique feature, I just show up and disappear after 3 seconds.\nThe implemsentation is done in the style of Gnome push-notification.".replace(" ", " &|").split("&|"))
    window = Info(head,text)
    window.show()
 
    sys.exit(app.exec_())
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.10.2021, 17:56
Помогаю со студенческими работами здесь

Создание категорий меню в Fedora 22 Gnome Shell 3.16
Изначально в Fedora 22 GNOME Shell 3.16 в меню две папки, а добавлять новые приходится через терминал. Для себя написал скрипт, который...

Alt+tab в windows 7 - окно в стиле Windows XP
Доброго времени суток! помогите, пожалуйста, решить следующую проблему: у меня на ноуте windows 7 home basic. раньше все нормально...

Gnome-panel failed to acquire bus name (gnome-panel как добавление ярлыка для рабочего стола)?
Хочу организовать рабочий стол с помощью gnome-panel, используя https://losst.ru/dobavlenie-yarlyka-v-ubuntu Установил gnome-panel ...

Создание виджета
Здравствуйте уважаемые форумчане. Работаем с пакетами UDP, и по воле случая, и по извращенной логике, получаем мы копию экрана в...

Создание виджета
Хочу создать виджет, который состоит из 6-7 частей, при этом на экране отображает 2-3 разные части(как фрагмнеты в активности). При тапе на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Новые блоги и статьи
Вывод данных через динамический список в справочнике
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Функция заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
К слову об оптимизации
kumehtar 01.04.2026
Вспоминаю начало 2000-х, университет, когда я писал на Delphi. Тогда среди программистов на форумах активно обсуждали аккуратную работу с памятью: нужно было следить за переменными, вовремя. . .
Идея фильтра интернета (сервер = слой+фильтр).
Hrethgir 31.03.2026
Суть идеи заключается в том, чтобы запустить свой сервер, о чём я если честно мечтал давно и давно приобрёл книгу как это сделать. Но не было причин его запускать. Очумелые учёные напечатали на. . .
Модель здравосоХранения 6. ESG-повестка и устойчивое развитие; углублённый анализ кадрового бренда
anaschu 31.03.2026
В прикрепленном документе раздумья о том, как можно поменять модель в будущем
10 пpимет, которые всегда сбываются
Maks 31.03.2026
1. Чтобы, наконец, пришла маршрутка, надо закурить. Если сигарета последняя, маршрутка придет еще до второй затяжки даже вопреки расписанию. 2. Нaдоели зима и снег? Не надо переезжать. Достаточно. . .
Перемещение выделенных строк ТЧ из одного документа в другой
Maks 31.03.2026
Реализация из решения ниже выполнена на примере нетипового документа "ВыдачаОборудованияНаСпецтехнику" с единственной табличной частью "ОборудованиеИКомплектующие" разработанного в конфигурации КА2. . . .
Functional First Web Framework Suave
DevAlt 30.03.2026
Sauve. IO Апнулись до NET10. Из зависимостей один пакет, работает одинаково хорошо как в режиме проекта так и в интерактивном режиме. из сложностей - чисто функциональный подход. Решил. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru