Pyqt сделать окно неактивным

Обновлено: 26.04.2024

Hey folks, This tutorial will help you to close a window in PyQt5 in Python. This can be achieved by using a simple method of the QWidget class. We will use that method and learn how to achieve our goal in a few ways. So for this, we are going to use some libraries of Python namely: PyQt5 and sys.

How to close a window in PyQt5

To close a window in PyQt5 we use the .close() method on that window. We can simply achieve this by calling the .close() method whenever we want to close the window or by some following ways:

  1. Calling the .close() method whenever needed.
  2. Binding to a PushButton to trigger the .close() method.
  3. Creating a QAction and adding it to the window to trigger the .close() method.

Calling the .close() method whenever needed

Create your PyQt5 application and just call the .close() method whenever that window needs closing. For example:

The above program creates a simple PyQt5 application with a QLabel as its central widget and then finally, closes it. So the window will be created, the widget will be added but it won’t be displayed as it was closed as soon as it was created.

NOTE: The above-mentioned program is just a demonstration on how to use .close() method when needed to close a window. It’s not a full-flexed application. So nothing will be displayed as mentioned earlier.

Binding to a PushButton to trigger the .close() method

In this way of closing the window, we create a QPushButton() and then bind a function(to close the window) to it which is triggered when that button is clicked. For example:

The above program creates a simple PyQt5 application with a QPushButton() as its central widget and then binds a function to trigger on click. The function is a simple lambda function that calls the self.close() method.It’s bound to QPushButton() using the .clicked.connect() method.So when the button is clicked the window closes.

Creating a QAction and adding it to the window to trigger the .close() method

In this way of closing the window, we create a QAction() and then add that action to the window we want to close using the .addAction() method. For example:

The above program creates a simple PyQt5 application with a QLabel as its central widget. Then a QAction() is created with some parameters like the name of the action, shortcut and triggered. Where shortcut is the key or key sequence that is needed to be pressed to trigger that action. Also, the triggered parameter is where the function to call on that action being triggered is specified. Then that action is added to the window which needs to be closed using the .addAction() So when the shortcut specified(i.e. Ctrl+q ) is pressed, as expected, the window closes.

One response to “Close a window in PyQt5 in Python”

Thanks Buddy it’s help me a lot.. past 2 days i am continuously try to figure out how to close MainWindow and your “self.close” method work Completely fine with my code.


В первом материале мы рассказали о создании первого окна, о сигналах, слотах и событиях, а также о виджетах. Сегодня, к старту курса по Fullstack-разработке на Python, делимся продолжением — о макетах, работе с панелями инструментов и меню при помощи QAction, дополнительных и диалоговых окнах. За подробностями приглашаем под кат.

Макеты

Ранее мы создали окно и добавили в него виджет. Нужно добавить ещё виджеты и определить, где они окажутся. Для этого в Qt используются макеты. Доступны 4 базовых макета, приведённые в этой таблице:

Горизонтальный линейный макет

Вертикальный линейный макет

Индексируемая сетка X на Y

Уложенные друг на друга по оси Z виджеты

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

В Qt есть три макета расположения виджетов: VBoxLayout, QHBoxLayout и QGridLayout. И есть QStackedLayout, позволяющий размещать виджеты один над другим в одном месте, одновременно отображая только один макет. Сначала понадобится простая схема приложения, в котором мы будем экспериментировать с различными макетами. Сохраните следующий код в файле app.py:

Чтобы упростить визуализацию макетов, создадим простой пользовательский виджет, который отображает сплошной цвет. Так будет легче различать добавляемые в макет виджеты. На верхний уровень добавьте код нового класса:

В этом коде мы пишем подкласс QWidget для пользовательского виджета Color, при создании которого принимаем один параметр — color (str). Сначала устанавливаем .setAutoFillBackground в True, чтобы фон виджета автоматически заполнялся цветом окна. Затем получаем текущую палитру (по умолчанию это глобальная палитра рабочего стола) и меняем текущий цвет QPalette.Window на новый QColor, который соответствует переданному значению color. Мы применяем эту палитру к виджету. Результат — виджет, заполненный сплошным цветом (каким именно — указывается при его создании).

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

Сначала протестируем новый виджет Color, используя его для заполнения всего окна одним цветом. По завершении добавим его в QMainWindow с помощью .setCentralWidget и получим окно со сплошным красным цветом:

Запускаем. Появится полностью красное окно, при этом виджет расширяется, заполняя всё доступное пространство.

Далее рассмотрим каждый из макетов Qt по очереди. Обратите внимание: макеты будут добавляться в окно, находясь в фиктивном QWidget.

QVBoxLayout: вертикально расположенные виджеты

В макете QVBoxLayout виджеты размещаются один над другим. При добавлении виджет отправляется в низ столбца.

QVBoxLayout, заполняемый сверху вниз

QVBoxLayout, заполняемый сверху вниз

Добавим виджет в макет. Чтобы добавить макет в QMainWindow, нужно применить его к фиктивному QWidget, а затем использовать .setCentralWidget, чтобы применить виджет и макет к окну. Цветные виджеты расположатся в макете, находящемся в QWidget, в окне. Сначала просто добавляем красный виджет, как раньше:

Теперь вокруг красного виджета видна рамка. Это интервал между макетами — позже посмотрим, как его настроить.

Если добавить в макет ещё цветных виджетов, они разместятся вертикально в порядке добавления:

QHBoxLayout: горизонтально расположенные виджеты

Макет QHBoxLayout такой же, только виджеты здесь размещаются горизонтально. Виджет добавляется с правой стороны.

QHBoxLayout, заполняемый слева направо

QHBoxLayout, заполняемый слева направо

Просто меняем макет QVBoxLayout на QHBoxLayout. Виджеты теперь располагаются слева направо:

Вложенные макеты

Есть более сложные макеты, состоящие из вложенных друг в друга макетов. Такие вложения делаются в макете с помощью .addLayout. Ниже мы добавляем QVBoxLayout в основной макет QHBoxLayout. Если добавить в QVBoxLayout несколько виджетов, они примут вертикальное расположение в первом слоте макета-предка:

Запускаем. Виджеты должны располагаться в 3 столбцах горизонтально, причём в первом столбце тоже будет 3 расположенных вертикально виджета. Попробуйте!

Установим интервал между макетами с помощью .setContentMargins, а между элементами — с помощью .setSpacing:

Ниже показаны вложенные виджеты с отступами и интервалами между макетами. Поэкспериментируйте с цифрами, чтобы освоиться:

QGridLayout: виджеты в сетке

Несмотря на все достоинства QVBoxLayout и QHBoxLayout, очень сложно добиться ровного расположения виджетов разного размера, если использовать эти макеты, например, для размещения нескольких элементов формы. Проблему решает QGridLayout.

В QGridLayout показываются позиции сетки для каждого местоположения

В QGridLayout показываются позиции сетки для каждого местоположения

Элементы в сетке QGridLayout размещаются особым образом. Для каждого виджета указывается его положение в строке и столбце. Если пропустить элементы, они останутся пустыми. При этом с QGridLayout не нужно заполнять все позиции в сетке.

QGridLayout с незаполненными слотами

QGridLayout с незаполненными слотами

QStackedLayout: несколько виджетов в одном месте

Последним рассмотрим макет QStackedLayout. В нём элементы размещаются друг за другом. Можно выбрать, какой виджет показывать. QStackedLayout используется для слоёв векторной графики в графическом приложении или для имитации интерфейса вкладок. Есть и виджет-контейнер QStackedWidget с точно таким же принципом работы. Он применяется, когда с помощью .setCentralWidget стопка виджетов добавляется прямо в QMainWindow.

QStackedLayout — здесь оказывается видимым только самый верхний виджет, который первым добавляется в макет QStackedLayout — здесь выбран 2-й виджет (обозначен цифрой 1) и выдвинут вперёд

Именно с помощью QStackedWidget работают представления с вкладками. В любой момент времени видимым оказывается только одна вкладка (таб). С помощью .setCurrentIndex() или .setCurrentWidget() определяется, какой виджет отображать в тот или иной момент: здесь элемент задаётся по индексу в порядке добавления виджетов или по самому виджету.

Вот краткое демо с использованием QStackedLayout вместе с QButton при реализации интерфейса в виде вкладок:

Пользовательский интерфейс в виде вкладок, реализованный с помощью QStackedLayout

Пользовательский интерфейс в виде вкладок, реализованный с помощью QStackedLayout

В Qt есть TabWidget, предоставляющий такой макет «из коробки», хотя и в виде виджета. Вот демо вкладки, воссоздаваемой с помощью QTabWidget:

Интерфейс в виде вкладок с использованием QTabWidget

Интерфейс в виде вкладок с использованием QTabWidget

Видите? Немного проще и красивее! Расположение вкладок устанавливается по сторонам света, а возможность их перемещения — с помощью .setMoveable. Панель вкладок на macOS отличается от других: по умолчанию они здесь даны в виде кружков и обычно используются в панелях конфигурации. Для документов включается режим документа — здесь создаются тонкие вкладки, похожие на вкладки других платформ. Эта опция относится только к macOS:

QTabWidget в режиме документа на macOS

QTabWidget в режиме документа на macOS

Позже мы рассмотрим другие виджеты сложнее.

Продолжить изучение Python вы сможете по книге автора этих статей или на наших курсах:

Панели инструментов, меню и QAction

Рассмотрим элементы стандартного пользовательского интерфейса, которые вы наверняка видели во многих приложениях: панели инструментов и меню. Также изучим чёткую систему Qt для минимизации дублирования различных частей пользовательского интерфейса — QAction.

Панели инструментов

Панель инструментов — один из самых часто встречающихся элементов пользовательского интерфейса. Это панели с иконками и/или текстом, используемые в приложении для выполнения стандартных задач, доступ к которым через меню затруднителен. Этот функционал пользовательского интерфейса есть почти во всех приложениях. Хотя некоторые сложные приложения, в частности в пакете Microsoft Office, перешли на контекстные ленточные интерфейсы, для большинства создаваемых приложений обычно достаточно стандартной панели инструментов.

Стандартные элементы графического интерфейса

Стандартные элементы графического интерфейса

Начнём со «скелета» простого приложения и его настройки. Сохраните этот код в файле app.py (в нём прописан весь импорт для последующих этапов):

Если вы переходите с PyQt5 на PyQt6, QAction в новой версии доступен через модуль QtGui.

Добавление панели инструментов

Панель инструментов в Qt создаётся из класса QToolBar. Добавим панель в приложение, создав сначала экземпляр класса, а затем вызвав .addToolbar в QMainWindow. Передав первым параметром QToolBar строку, задаём имя панели инструментов: по нему эта панель идентифицируется в пользовательском интерфейсе:

Запускаем. Появится тонкая серая полоска наверху окна. Это панель инструментов. Нажмите правую кнопку и выберите имя панели, чтобы отключить её.

Окно с панелью инструментов

Окно с панелью инструментов

Но как теперь вернуть панель инструментов? После её удаления негде нажать правой кнопкой, чтобы снова её добавить. Поэтому нужно или оставлять одну панель неудалённой, или иметь альтернативный интерфейс, чтобы включать и выключать панели.

Сделаем панель чуть интереснее. Вместо добавления виджета QButton используем дополнительный функционал Qt — класс QAction для описания абстрактных пользовательских интерфейсов.

С его помощью внутри одного объекта определяется несколько элементов интерфейса, с которыми пользователь сможет взаимодействовать. Например, опция «Вырезать» есть в меню «Правка», и в панели инструментов (значок ножниц) и доступна по комбинации клавиш Ctrl-X (Cmd-X на Mac).

Вот первый добавленный QAction:

Сначала создаём функцию, принимающую сигнал от QAction (так мы проверяем её работоспособность). Затем определяем сам QAction. Когда создаётся экземпляр, передаётся метка для действия и/или иконка.

Также нужно передать любой QObject (это предок действия). Передаём self как ссылку на главное окно. Как ни странно, для QAction элемент-предок передаётся в последнем параметре.

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

Запускаем! Появится кнопка с определённой нами меткой. Нажимаем её, и пользовательская функция выдаст click («Нажатие») и статус кнопки.

Панель инструментов с кнопкой QAction

Панель инструментов с кнопкой QAction

Почему сигнал всегда false? Переданный сигнал указывает, нажата ли кнопка. В нашем случае она не допускает нажатия, поэтому всегда false. Скоро покажем, как включить возможность её нажатия.

Добавляем строку состояния. Создаём объект строки состояния, вызывая QStatusBar, и передаём его в .setStatusBar. Настройки этого statusBar (строки состояния) менять не нужно: просто передаём её в одной строке при создании:

Запускаем. Наводим курсор мыши на кнопку панели инструментов и видим в строке состояния текст статуса.

Текст строки состояния обновляется при наведении курсора на actions (действия)

Текст строки состояния обновляется при наведении курсора на actions (действия)

Теперь сделаем QAction переключаемым: при первом нажатии он включается, при повторном — отключается. Для этого просто вызываем setCheckable(True) в объекте QAction:

Запускаем и нажимаем кнопку — её состояние переключается из нажатого в ненажатое. При этом пользовательская функция слота теперь чередует вывод True и False.

Включённая кнопка на панели инструментов

Включённая кнопка на панели инструментов

Есть .toggled, который сигнализирует только при включении/отключении кнопки. Эффект тот же, поэтому в .toggled особой надобности нет.

Добавим к кнопке иконку. Скачаем отличный набор красивых иконок Fugue 16 х 16 пикселей Юсукэ Камияманэ, которые придадут приложениям приятный профессиональный вид. Это бесплатно — при распространении приложения требуется только ссылка на автора.

Набор иконок Fugue от Юсукэ Камияманэ

Набор иконок Fugue от Юсукэ Камияманэ

Выбираем изображение (я выбрал файл bug.jpg) и копируем его в папку с исходным кодом. Создаём объект QIcon, передав имя файла классу, например QIcon('bug.jpg'). Если поместить файл в другую папку, нужен полный относительный или абсолютный путь к нему. Наконец, чтобы добавить иконку и кнопку в QAction, просто передаём её первым параметром при создании QAction.

Также нужно указать размер иконок, иначе вокруг них будет множество отступов. Сделаем это, вызвав функцию .setIconSize() с объектом QSize:

Запускаем. QAction теперь в виде иконки. Всё должно работать точно так же, как и раньше.

Кнопка действий теперь с иконкой

Кнопка действий теперь с иконкой

Внимание! Чтобы определить, что отображать на панели инструментов: иконку, текст или иконку с текстом, в Qt используются стандартные настройки ОС. Выбрать можно и самостоятельно с помощью .setToolButtonStyle. Этот слот принимает из пространства имён Qt такие флаги:

Начал изучать PyQt4, и никак не могу найти информацию, как сделать элемент QLineEdit не активным, чтобы в нем нельзя было писать.
Есть кнопка
ok = QtGui.QPushButton(“ok”)
Есть строка для редактирования
ipEdit = QtGui.QLineEdit()

При нажатии на кнопку, QLineEdit() должна становиться не активной.
У родителя - QWidget, нашел метод setDisabled, но если его просто прописать в QtCore.SLOT(), то не работает.
Думаю нужно свой слот создать, как это сделать ?

PyQT. Сделать не активным QLineEdit (новичок)

Отредактировано (Окт. 9, 2011 17:35:44)

PyQT. Сделать не активным QLineEdit (новичок)

Так я конечно пробовал, вылетает ошибка.

Отредактировано (Окт. 10, 2011 16:55:02)

PyQT. Сделать не активным QLineEdit (новичок)

На данный момент я нашел один вариант сделать QLineEdit не активной:

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

PyQT. Сделать не активным QLineEdit (новичок)

Уж layout сами изобразите

PyQT. Сделать не активным QLineEdit (новичок)

Спасибо, Ваш вариант работает, такого синтаксиса я еще не видел, изучаю дальше!

PyQT. Сделать не активным QLineEdit (новичок)

Я принял к сведению вариант truporez.
Скажите чем плох мой вариант! укажите правильный стиль.
Интересует именно использование глобальных переменных, есть ли минусы

Отредактировано (Окт. 11, 2011 11:31:02)

PyQT. Сделать не активным QLineEdit (новичок)

Ой-ёй. Уберите global напрочь. Сохраняйте ссылки на объекты в самом экземпляре через self, процедурный, Вы, наш.

PyQT. Сделать не активным QLineEdit (новичок)

Переписал, так в чем минусы global, перед self ?

PyQT. Сделать не активным QLineEdit (новичок)

Очевидно главная проблема в том, что это глобальные переменные, не принадлежащие объекту. Если вы создадите еще один объект таким способом, получите разнообразные глюки.
Вам бы книжки по ООП почитать, ну и по самому python.

Первый: Как сделать родительское окно полностью неактивным (не принимающим ввод от пользователя и не дающим переключить себя на топлевел) при вызове дочернего?
Второй: Как запретить изменение размера для окна?

Отредактировано (Ноя. 2, 2009 20:02:42)

Два нубских вопроса по PyQt4

1)вроде никак
но можно сделать его setDisabled(True)
2) setFixedSize

Два нубских вопроса по PyQt4

Enchantner Тебе похоже надо просто сделать модальный диалог

Два нубских вопроса по PyQt4

1) widget.setWindowModality(Qt.ApplicationModal) - это блочит все приложение, еще есть параметр Qt.WindowModal, который блочит только родительское окно и Qt.NonModal, который ничего не блочит и является умолчательным.

Отредактировано (Ноя. 2, 2009 23:54:20)

Два нубских вопроса по PyQt4

pasaranax
У меня родительское окно типа QMainWindow, а дочернее - QWidget. Твой пример запускается без ошибок, но не работает :) Или я что-то не так делаю…

villager
насчет setFixedSize спасибо большое :)

Отредактировано (Ноя. 3, 2009 00:47:36)

Два нубских вопроса по PyQt4

Enchantner
У меня родительское окно типа QMainWindow, а дочернее - QWidget. Твой пример запускается без ошибок, но не работает smile Или я что-то не так делаю…

Я пробовал с родителем QWidget и ребенком QDialog. Как ты QWidget окном сделал, можешь кусок кода показать? Может применяешь модальность не к тому?

ps: вот мой пример:

Отредактировано (Ноя. 3, 2009 01:57:09)

Два нубских вопроса по PyQt4

сорри…ввел в заблуждение…

Просто я делал интерфейс как в firefox - с закладками, в каждой -QMdiArea,
как ни пробовал - модальные окна в каждой закладке (но при этом QTabBar - доступен) получилось
сделать только с помощью setDisabled предыдущего окна…
может есть решение и попроще?

Два нубских вопроса по PyQt4

Привет. Как у вас сделано: главное окно - это QMainWindow, дочернее - QWidget, работать не будет, потому что( из ассистанта):

A modal window is one that blocks input to other windows. Note that windows that are children of a modal window are not blocked.

QMainWindow - children QWidget.
Если сделать наоборот MainWindow - QWidget, Widget - QMainWindow - то все заработает.
Первое нажатие кнопки устанавливает модальность, далее сколько кнопку ни жать- главное окно будет заблокировано от ввода. Если я, конечно, все правильно понял.:)

Два нубских вопроса по PyQt4

gmorgunov Ты не правильно толкуешь документацию, путаешь одних детей и родителей с другими, тут не в классовом родстве дело. Чуть подправил твой пример:

Два нубских вопроса по PyQt4

Я пытался связать функцию с кнопкой закрытия главного окна (красный крестик в углу окна), но у меня не было никакого успеха. Прямо сейчас мой код выглядит примерно так:

В отдельном «основном» файле у меня есть следующее:

Оба эти решения похожи на мои, но все равно не работают

Несмотря на ответ, который, возможно, сработал для конкретного кода этого пользователя, мои коллеги по PyQt и я до сих пор не можем понять, почему наш код не работает. Есть ли определенное имя кнопки для «Red X box», встроенного в PyQt? Могу ли я подключить его к другой функции, как для других кнопок?

3 ответа

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

Судя по внешнему виду вашего кода, вы на самом деле создаете два QMainWindow , а closeEvent перехватывается за неправильный (предположительно, он скрыт?). То есть self.ui - это QMainWindow , который не отображается и не добавляется в пользовательский интерфейс GUIForm . Вместо этого вы сами используете метод Ui_MainWindow.setupUi() , чтобы добавить виджеты к своему собственному QMainWindow , 'GUIForm`.

Вместо этого вам нужно оставить класс Ui_MainWindow таким, каким он был, когда он был сгенерирован из файла пользовательского интерфейса, а затем изменить свой основной файл python:

Таким образом, вы расширяете поведение автоматически сгенерированного файла пользовательского интерфейса. Это позволяет легко восстановить файл python из файла .ui без необходимости повторного добавления кода (именно поэтому вам никогда не следует изменять автоматически сгенерированный файл Python)

Иногда возникают проблемы при обработке сигналов событий из главного окна.

Вы можете использовать код:

И вы можете написать свой собственный код в функции closeEvent .

Примечание.

app - это имя экземпляра QtGui.QApplication .

Вот демонстрация полного кода:

Надеюсь, это поможет.

Я столкнулся с той же проблемой, когда у меня было диалоговое окно с запросом ввода, прежде чем продолжить операцию. Пользователь может добавить ввод перед обработкой операции, пропустить добавление и обработку в любом случае или отменить операцию, используя кнопку «Отмена» или нажав X диалогового окна.

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

Читайте также: