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

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

16.03.2023, 22:08. Показов 854. Ответов 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
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru