Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
PyQt5

Всплывающий QListView почему то является модальным окном

16.03.2023, 22:08. Показов 834. Ответов 6

Студворк — интернет-сервис помощи студентам
При нажатии на кнопку должен появляться всплывающий QListView (с флагом Qt.Popup), но он почему то блокирует действия главного окна (нажатие на крестик, возможность свернуть окно). Как мне сделать, чтобы всплывающий QListView не блокировал нажатия на главное окно?

Вот код:
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
from PyQt5 import QtCore
from PyQt5.QtWidgets import (QApplication, QWidget, QHBoxLayout,
                             QLineEdit, QListView, QToolButton)
from PyQt5.QtCore import Qt, QAbstractListModel, pyqtSignal, pyqtSlot, QPoint
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtWidgets import QDialog
from PyQt5.QtWidgets import QListWidget
from PyQt5.QtWidgets import QMainWindow
 
class View(QListView):
    def __init__(self):
        super().__init__()
        self.setWindowFlags(Qt.Popup)
 
class myMenu(QWidget):
    def __init__(self):
        super().__init__()
        self.btn = QToolButton()
        self.view = View()
        layout = QHBoxLayout(self)
        layout.addWidget(self.btn)
        self.btn.clicked.connect(self.open_menu)
 
    def open_menu(self):
        self.view.show()
 
app = QApplication([])
win = QMainWindow()
 
w = myMenu()
win.setCentralWidget(w)
win.show()
app.exec()
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
16.03.2023, 22:08
Ответы с готовыми решениями:

Подскажите с модальным окном
всем привет. подскажите как сделать именно в этом скрипте чтобы окно можно было закрыть не только нажав крестик но и вне окна кликнув на...

Пример с модальным окном
Вобщем запутался я с модальными окнами, примеров в интернете пруд пруди а что-то подходящего который помог бы не нашёл.. Вобщем пришёл вас...

Страница с модальным окном
Здравствуйте. У меня есть сайт, который постороен на модальных окнах. В каждой старницы один задний план, но модальные окна разные. Возник...

6
52 / 9 / 4
Регистрация: 17.12.2018
Сообщений: 17
17.03.2023, 06:51
'''Проблема здесь заключается в использовании флага `Qt.Popup` для настройки окна `QListView`. Этот флаг делает виджет модальным, что означает, что он блокирует все взаимодействия с другими виджетами, включая родительское окно, пока он открыт.

Чтобы решить эту проблему, вы можете использовать флаг `Qt.Tool` вместо `Qt.Popup`, который также создает всплывающее окно, но не делает его модальным. Вот исправленный код:
'''

Code
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
from PyQt5 import QtCore
from PyQt5.QtWidgets import (QApplication, QWidget, QHBoxLayout,
                             QLineEdit, QListView, QToolButton)
from PyQt5.QtCore import Qt, QAbstractListModel, pyqtSignal, pyqtSlot, QPoint
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtWidgets import QDialog
from PyQt5.QtWidgets import QListWidget
from PyQt5.QtWidgets import QMainWindow
 
class View(QListView):
    def init(self):
        super().init()
        self.setWindowFlags(Qt.Tool)  # заменили флаг Qt.Popup на Qt.Tool
 
class myMenu(QWidget):
    def init(self):
        super().init()
        self.btn = QToolButton()
        self.view = View()
        layout = QHBoxLayout(self)
        layout.addWidget(self.btn)
        self.btn.clicked.connect(self.open_menu)
 
    def open_menu(self):
        self.view.show()
 
app = QApplication([])
win = QMainWindow()
 
w = myMenu()
win.setCentralWidget(w)
win.show()
app.exec()

#Теперь всплывающее окно `QListView` не будет блокировать главное окно, и вы сможете свободно взаимодействовать с ним.
1
17.03.2023, 11:40

Не по теме:

Fervuld, ну, чатжпт ты пользоваться научился, поздравляю

0
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
17.03.2023, 20:54  [ТС]

Не по теме:

iSmokeJC, а что собственно Fervuld, нарушил???



Добавлено через 3 минуты
Fervuld,
Цитата Сообщение от Fervuld Посмотреть сообщение
Qt.Tool
Мне не совсем подходит это т.к. мне нужно, чтобы QListView был без рамок, закрывался при нажатии ЛКМ на любой другой участок экрана, а также чтобы не отображался в панели задач (мне нужно, чтобы оно отображалось так же, как меню, открывающееся при нажатии ПКМ по рабочему столу)
0
290 / 205 / 68
Регистрация: 18.09.2019
Сообщений: 407
Записей в блоге: 58
18.03.2023, 18:09
Лучший ответ Сообщение было отмечено DarkShaddow как решение

Решение

Цитата Сообщение от DarkShaddow Посмотреть сообщение
При нажатии на кнопку должен появляться всплывающий QListView (с флагом Qt.Popup), но он почему то блокирует действия главного окна (нажатие на крестик, возможность свернуть окно). Как мне сделать, чтобы всплывающий QListView не блокировал нажатия на главное окно?
Надо было сесть и читать документацию https://doc.qt.io/qt-5/qt.html#WindowType-enum
Qt::Popup 0x00000008 | Window
Указывает, что виджет является всплывающим окном верхнего уровня, т. е. является модальным, но имеет системную рамку окна, подходящую для всплывающих меню.

Qt::Window 0x00000001
Указывает, что виджет является окном, обычно с рамкой оконной системы и строкой заголовка, независимо от того, есть ли у виджета родитель или нет. Обратите внимание, что невозможно снять этот флаг, если у виджета нет родителя.


Существует также ряд флагов, которые можно использовать для настройки внешнего вида окон верхнего уровня. Они не влияют на другие окна:

Qt::FramelessWindowHint 0x00000800
Создает окно без полей. Пользователь не может перемещать или изменять размер окна без полей через оконную систему. В X11 результат флага зависит от оконного менеджера и его способности понимать подсказки Motif и/или NETWM. Большинство существующих современных оконных менеджеров могут справиться с этим.
плюс ПОДРОБНОЕ ОПИСАНИЕ здесь и тогда могло бы получиться следующее решение:
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
from PyQt5 import QtCore
from PyQt5.QtWidgets import (QApplication, QWidget, QHBoxLayout,
                             QLineEdit, QListView, QToolButton)
from PyQt5.QtCore import Qt, QAbstractListModel, pyqtSignal, pyqtSlot, QPoint
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtWidgets import QDialog
from PyQt5.QtWidgets import QListWidget
from PyQt5.QtWidgets import QMainWindow
 
class View(QListView):
    def __init__(self, parent=None):
        super(View, self).__init__(parent)
        self.setWindowFlags(Qt.FramelessWindowHint|Qt.Window)
    def focusOutEvent(self, e):
        e.accept()
        self.hide()
 
class myMenu(QWidget):
    def __init__(self, parent=None):
        super(myMenu, self).__init__(parent)
        self.btn = QToolButton(self)
        self.view = View()
        layout = QHBoxLayout(None)
        layout.addWidget(self.btn)
        self.setLayout(layout)
        self.btn.clicked.connect(self.open_menu)
    def open_menu(self):
        # QtCore.QTimer.singleShot(3000, lambda: self.view.hide())
        # предохранитель - вещь не лишняя, но может и отсутствовать
        self.view.show()
        self.view.setFocus()
 
app = QApplication([])
win = QMainWindow()
 
w = myMenu()
win.setCentralWidget(w)
win.show()
app.exec()
1
7 / 7 / 0
Регистрация: 03.10.2020
Сообщений: 164
18.03.2023, 19:38  [ТС]
iamvic, спасибо, в целом это решило проблему. Только в идеале данное окно не должно отображаться в панели задач, поэтому я заменил Qt.Window на Qt.Tool, но после этого метод setFocus() перестал фокусироваться на окне инструментов.

Цитата Сообщение от iamvic Посмотреть сообщение
Qt::Popup 0x00000008 | Window
Указывает, что виджет является всплывающим окном верхнего уровня, т. е. является модальным
Если это так, то я не понимаю почему в коде ниже хоть и указано, что окно является Popup, но данное окно не является модальным (по крайне мере легко закрывается при расфокусировке).

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
import time
 
from PyQt5 import QtCore
from PyQt5.QtWidgets import (QApplication, QWidget, QHBoxLayout,
                             QLineEdit, QListView, QToolButton, QMainWindow)
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt, QAbstractListModel, pyqtSignal, pyqtSlot, QPoint
from PyQt5.QtGui import QIcon, QFont
from PyQt5.QtWidgets import QDialog
from PyQt5.QtWidgets import QListWidget
 
style_sheet = '''
QListView {
    background-color:white;
    font-size:16px;
    font-family:Comic Sans MS;
}
QListView::item:alternate {
    background:#f7f7f7;
}
QListView::item::hover {
    background: #0ff;
}
'''
 
class Timer():
    def __init__(self):  # таймер
        self.st = time.time()
 
    def end(self):
        return float("%.2f" % (time.time() - self.st))
 
class ListModel(QAbstractListModel):
    def __init__(self):
        super().__init__()
        self._data = []
        self._checklist = []
 
    def rowCount(self, index):
        return len(self._data)
 
    def data(self, index, role):
        row = index.row()
        if role == Qt.DisplayRole:
            return self._data[row]
        elif role == Qt.DecorationRole:
            return QIcon('Dark_rc/checkbox_checked.png') if self._checklist[row] else QIcon('Dark_rc/checkbox_unchecked.png')
 
    def flags(self, index):
        return Qt.ItemIsEnabled  # | Qt.ItemIsSelectable
 
    def load(self, lst):
        self.beginResetModel()
        self._data = lst
        self._checklist = [False] * len(lst)
        self.endResetModel()
 
    def get(self):
        return ', '.join(x for x, y in zip(self._data, self._checklist) if y)
 
class View(QListView):
    def __init__(self):
        super().__init__()
        self.setStyleSheet("padding: 0px; margin: 0px;")
        # self.setWindowFlags(Qt.Popup)
        # self.setWindowFlags(Qt.FramelessWindowHint)
        self.window = QDialog()
        self.setAlternatingRowColors(True)
        self.setStyleSheet(style_sheet)
        self.model = ListModel()
        self.setModel(self.model)
 
class PopupWidget(QWidget):
    state_changed = pyqtSignal(str)
    def __init__(self):
        super().__init__()
        self.setWindowFlags(Qt.Popup)
        self.initView()
        self.view.clicked.connect(self.state_change)  # отслеживается клик по элементу
        self.time_for_open = Timer()
 
    def state_change(self, index):
        self.view.model._checklist[index.row()] ^= True
        self.view.model.layoutChanged.emit()
        self.state_changed.emit(self.view.model.get())
 
    def initView(self):
        self.view = View()
        self.view.setAlternatingRowColors(True)
        hbox = QHBoxLayout(self)
        hbox.setContentsMargins(1, 1, 1, 1)
        hbox.setSpacing(0)
        hbox.addWidget(self.view)
 
    def closeEvent(self, event):
        self.time_for_open = Timer()
 
class MyCheckableComboBox(QWidget):
    def __init__(self):
        super().__init__()
        self.line = QLineEdit()
        self.line.setReadOnly(True)
        self.btn = QToolButton()
        self.setStyleSheet("padding: 0px; margin: 0px;")
        self.btn.setIcon(QIcon('img_rc/array_down.png'))
        self.popup_win = PopupWidget()
 
        hbox = QHBoxLayout(self)
        hbox.setContentsMargins(1, 1, 1, 1)
        hbox.setSpacing(0)
        hbox.addWidget(self.line)
        hbox.addWidget(self.btn)
        self.btn.clicked.connect(self.show_popup)
        self.popup_win.state_changed.connect(lambda x: self.line.setText(x))
 
    def addElements(self, elements):
        self.popup_win.view.model.load(elements)
 
    def show_popup(self):
        if not self.popup_win.isVisible() and self.popup_win.time_for_open.end() >= 0.4:    # если сейчас окно закрыто и с момента закрытия прошло 0.4 секунды
            self.popup_win.setGeometry(100, 200, 100, 100)
            self.popup_win.resize(self.width(), 90)
            self.popup_win.move(self.mapToGlobal(QPoint(0, self.height())))
            self.setFont(self.font())
            self.popup_win.show()
 
app = QApplication([])
win = QMainWindow()
w = MyCheckableComboBox()
win.setStyleSheet(style_sheet)
w.addElements(list('12345678'))
win.setCentralWidget(w)
win.show()
 
app.exec()
1
290 / 205 / 68
Регистрация: 18.09.2019
Сообщений: 407
Записей в блоге: 58
19.03.2023, 12:44
Цитата Сообщение от DarkShaddow Посмотреть сообщение
...в целом это решило проблему. Только в идеале данное окно не должно отображаться в панели задач, поэтому я заменил...
Простите, но всё это чем-то напоминает внезапное внесение "ма-а-аленьких" изменений в почти готовый проект, приводящее к необходимости полного перепроектирования. Вы изначально задавались вопросом "Какие, собственно говоря, окна отображаются на панели задач?" А ведь там отображаются только окна верхнего уровня, т.е. окна, у которых нет родителя. А у Вас все создаваемые окна - верхнего уровня. Даже при написании кода собственных классов Вы не предоставили возможность указать родителя во время создания экземпляра класса. Вариантов-то ровно два - можно всё переделать, а можно на это и забить...

Добавлено через 4 часа 22 минуты
Цитата Сообщение от DarkShaddow Посмотреть сообщение
Если это так, то я не понимаю почему в коде ниже хоть и указано, что окно является Popup, но данное окно не является модальным (по крайне мере легко закрывается при расфокусировке).
Я тут вижу одно различие:
- в первом примере Вы применили Qt.Popup непосредственно к QListView (что, наверное, неправильно; видимо Qt.Popup так не работает, хотя QListView, конечно, наследует QWidget)
- во втором - применили Qt.Popup к чистокровному QWidget, внутри которого был упакован QListView (а вот это правильно, скорее всего, и Qt.Popup отрабатывает, как положено)

Почёт и уважуха
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
19.03.2023, 12:44
Помогаю со студенческими работами здесь

Работа с модальным окном
Парни, всем привет. Подскажите такой момент. У меня есть файл в WP с разметкой модального окна. И есть файл с разметкой и кнопкой при...

Проблемы с модальным окном
Всем привет, есть приложение, сейчас переделываю модалку, и не могу понять как вывести задний фон, прошу помощи , зу любую помощь буду...

Не могу разобраться с модальным окном
Не давно наткнулся на довольно не плохой скрипт отправки форм на E-mail Все бы хорошо, но почему-то при нажатии на ссылку в мозиле...

Делегат + редактор с модальным окном
Всем доброго времени суток. Вопрос, если очень в общем, звучит так: имеется qt-модель (QStandardItemModel), предназначенная для...

Работа с модальным окном confirm
Имеем html код: <a href="admin/del_news.php" id="delete"> <img src="images/admin/del.png" title="Удалить новость" /> ...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США. Нашел на реддите интересную статью под названием «Кто-нибудь знает, где получить бесплатный компьютер или. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru