Как сделать модальным окно в qt с остановом действий останавливает выполнение кода

Добавил пользователь Алексей Ф.
Обновлено: 05.10.2024

Мне удалось достичь 1 и 3, сделав диалог модальным, и я могу достичь 1 и 2, используя флаг окна Qt :: WindowStaysOnTopHint. Но мне не удается заставить все три работать - возможно ли это?

Если ответы зависят от ОС, я в основном работаю на Mac, но я бы предпочел решение, которое также применимо к Windows и Linux. Спасибо!

4 ответа

Вы можете попытаться использовать QGuiApplication::applicationStateChanged . Таким образом, вы получите уведомление, если пользователь входит или выходит из вашего приложения. Просто динамически добавляйте и удаляйте флаг Qt::WindowStaysOnTopHint для своего окна. Если у вас несколько окон, вы можете использовать QGuiApplication::focusWindowChanged вместе с первым.

Правка . Чтобы сделать диалоговое окно немодальным, либо установите NULL в качестве родительского, либо установите Свойство windowModality для Qt::NonModal и отображения диалога с помощью show , а не open или exec

Пример кода в подклассе QDialog:

QWidget по умолчанию достаточно для ваших нужд.

Если вы создадите QWidget с parent для вашего главного окна, оно будет поверх других виджетов. Вам просто нужно создать его последним или правильно сложить с помощью QWidget :: Повышать ().

Это окно всегда будет сверху: self.setWindowFlags(QtCore.Qt.Dialog | QtCore.Qt.WindowStaysOnTopHint)

Или вы можете передать свои существующие флаги: self.setWindowFlags( self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)

Я могу воспроизвести исходную проблему, только если QDialog создан с родителем NULL. В противном случае для соответствия требованиям 1, 2 и 3 достаточно следующих строк.

Похожие вопросы

Популярные теги

Когда мы вызываем QApplication::exec(), тем самым начинаем цикл обработки событий Qt. При запуске пpилoжeния Qt генерирует несколько событий для отображения на экране виджетов. После этого начинает выполняться цикл обработки событий: постоянно проверяется их возникновение, и эти события отправляются к объектам QObject данного приложения.

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

Одно из решений заключается в применении многопоточной обработки: один процесс для работы с интерфейсом пользователя приложения и другой процесс для выполнения операции сохранения файла (или любой другой длительной операции). В этом случае интерфейс пользователя приложения сможет реагировать на события в процессе выполнения операции сохранения файла. Мы рассмотрим способы обеспечения такого режима работы в главе 18.

Более простое решение заключается в выполнении частых вызовов функции QApplication::processEvents() в программном коде сохранения файла. Данная функция говорит Qt о необходимости обработки ожидающих в очереди событий и затем возвращает управление вызвавшей ее функции. Фактически функция QApplication::exec() представляет собой не более чем вызов функции processEvents() в цикле while.

Ниже приводится пример того, как мы можем сохранить работоспособность интерфейса пользователя при помощи функции processEvents(), причем за основу взят программный код сохранения файла в приложении Spreadsheet:

01 bool Spreadsheet::writeFile(const QString &fileName)

03 QFile file(fileName);

05 for (int row = 0; row processEvents();

При использовании этого метода существует опасность того, что пользователь может закрыть главное окно во время выполнения операции сохранения файла или даже выбрать повторно File | Save, что приведет к непредсказуемому результату. Наиболее простое решение заключается в замене вызова

который указывает Qt на необходимость игнорирования событий мышки и клавиатуры.

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

01 bool Spreadsheet::writeFile(const QString &fileName)

03 QFile file(fileName);

05 QProgressDialog progress(this);

07 progress.setLabelText(tr("Saving %1").arg(fileName));

08 progress.setRange(0, RowCount);

10 for (int row = 0; row processEvents();

13 if (progress.wasCanceled())

15 return false;

17 for (int column = 0; column timerId() == myTimerId)

04 while (step hasPendingEvents())

Если фyнкция hasPendingEvents() возвращает true, мы останавливаем процесс и передаем управление обратно Qt. Этот процесс будет возобновлен после обработки Qt всех своих ожидающих событий.

Обработка событий, генерируемых элементами управления формы

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

Обработка событий

Обработка событий Теперь самое время рассмотреть один ключевой вопрос Web-программирования: события, их возникновение и

Обработка зомбированных процессов

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

Обработка событий

Обработка событий Теперь самое время рассмотреть один ключевой вопрос Web-программирования: события, их возникновение и обработка. Понятие события и его обработки Рассматривая примеры Web-сценариев, мы исходили из предположения, что они выполняются при загрузке

Глава 7. Обработка событий

Глава 7. Обработка событий События генерируются оконной системой или Qt в ответ на различные действия. Когда пользователь нажимает или отпускает клавишу или кнопку мышки, генерируется событие клавиши клавиатуры или кнопки мышки; когда окно впервые выводится на экран,

Обработка событий в режиме проектирования

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

Обработка серверных событий

5.6. Обработка событий в сборных видах

5.6. Обработка событий в сборных видах Постановка задачи Необходимо обрабатывать события, происходящие в сборных видах, например

9.2. Обработка событий картографического вида

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

2.4.2. Время установки Windows 7 и время жизни аккумулятора

2.4.2. Время установки Windows 7 и время жизни аккумулятора Если вы устанавливаете Windows 7 на ноутбук или нетбук, желательно подключить его к сети питания. Если это невозможно, тогда лучше не начинать установку Windows. Хотя весь процесс установки занимает около 20–25 минут (во всяком

Обработка событий, возникающих в клипах

Обработка событий, возникающих в клипах Обработчики событий клипов имеют такой формат: onClipEvent(<Событие>) < <Тело обработчика> >Собственно, нам он уже знаком из главы 18. Вот пример такого обработчика: onClipEvent(mouseDown) < this.stop(); >Этот обработчик выполняется в ответ на щелчок

Обработка событий, возникающих в кнопках

Обработка событий, возникающих в кнопках Сценарий-обработчик события, возникающего в кнопке, как мы помним из главы 18, имеет такой формат записи: on(<Событие>) < <Тело обработчика> >Например: on (press) < _root.stop(); >В данном примере обработчик выполняется в ответ на нажатие

4.3.2. Планирование событий

4.3.2. Планирование событий Для планирования события, которое может состояться в определенный день, предварительно следует выполнить два действия: выбрать календарь, щелкнув по его имени мышью в боковой панели, и выбрать один из трех режимов просмотра: день, неделя, месяц,

Пользовательский интерфейс будет полностью реализован на QML, программная часть на Qt.

Для тех, у кого Qt еще не установлен, заходим на страницу загрузки qt.nokia.com/downloads и в разделе "Qt SDK: Complete Development Environment" скачиваем бинарники для своей платформы. И, собственно, устанавливаем.

Запускаем Qt Creator, выбираем пункт меню Файл -> Новый файл или проект. В открывшемся окне Проект Qt C++ -> Gui приложение Qt, далее кнопка Выбрать.

Qt

В новом окне вводим название проекта, указываем путь к проекту, жмем Далее.

В следующем окне снимаем галочку Создать форму, она нам не пригодиться, Далее. И в последнем просто нажимаем кнопку Завершить. Все, каркас нашего приложения создан.

Qt

Первым делом добавим модуль qt-declarative к нашему проекту, для этого, в файле проекта (4Toddler.pro), к строке


Далее изменим базовый класс для нашего главного окна, заменим QMainWindow на QDeclarativeView и включим заголовочный файл QDeclarativeView

class MainWindow : public QDeclarativeView
.
>

От реализации конструктора отрежем, ставшую ненужной, инициализацию базового класса QMainWindow(parent).

Если сейчас собрать и запустить проект то мы увидим пустое окно. Так и должно быть, т.к. мы еще не создали и не инициализировали Qml интерфейс.

Добавим в проект новый QML файл, для этого щелкаем правой клавишей по проекту

image

Добавить новый. , далее выбираем раздел Qt, шаблон Файл Qt QML. Даем ему имя main, затем Далее и Завершить.

image

Мастер создал нам файл, содержащий один элемент Rectangle, он и будет являться основным элементом для нашего пользовательского интерфейса. Добавим несколько новых свойств и зададим их значение

Rectangle
// Идентификатор, по нему будет происходить
// обращение к свойствам этого элемента
id: canvas;

// Цвет фона, черный
color: "black"

// Изменять размер под размеры
// родительского элемента
anchors.fill: parent

// Будет получать фокус ввода
focus: true
>


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

void MainWindow::Init()
// Путь к папке, содержащей QML файлы
QString contentPath;

setFocusPolicy(Qt::StrongFocus);
// Изменять размеры QML объекта под размеры окна
// Возможно делать и наоборот,
// передавая QDeclarativeView::SizeViewToRootObject
setResizeMode(QDeclarativeView::SizeRootObjectToView);

// Загрузить QML файл
setSource(QUrl::fromLocalFile(contentPath + "/main.qml" ));
>

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

Элемент WindowButton мы будем использовать повторно, изменяя лишь определенные свойства у каждого экземпляра. Кнопки у нас будут выполнены в виде иконок, каждой из них мы будем задавать путь к файлу иконки и изменять обработчик нажатия левой клавишей мыши. Ниже приведен готовый код элемента с комментариями

// При нажатии вызвать метод callback
onClicked: callback()
>
>

// Элемент позволяющий
// распологать элементы горизонтально
Row
// Правый край элемента выравнивается
// по правому краю родительского элемента
anchors.right: parent.right;
// Отступ справа, 4 пикселя
anchors.rightMargin: 4;
// Верхний край эелемента выравнивается
// по верхнему краю родительского элемента
anchors.top: parent.top;
// Отступ сверху, 4 пикселя
anchors.topMargin: 4;

// Отступ между элементами
spacing: 4

WindowButton
// Кнопка возова диалога "О программе"
id: about;

// Путь к файлу с изображением
// в данном случае иконка лежит в той же папке,
// что и QML файл
source: "about.jpg" ;

// Метод, который будет вызываться
// при нажатии на кнопку левой клавишей мыши
// onClicked: callback()
function callback()
>
>

WindowButton
// Кнопка закрытия окна
id: exit;

Чтобы то, что мы сделали заработало нам осталось реализовать оба метода callback для каждой кнопки. Для закрытия окна мы вызовем метод Quit, который реализуем в классе окна. Для этого в объявление класс добавим


Осталось сделать этот метод видимым из QML. В метод Init добавим одну единствунную строку, которая сделает экземпляр нашего окна видимым в QML


Обращаться к этому объекту мы сможем по имени — window, имя это произвольное. Добавим реализацию для кнопки закрытия окна

Обратите внимание, что вызывать можно только те методы, которые объявлены как Q_INVOKABLE, т.е. от же метод Init, главного окна вызвать не удастся.

Image
.
states:[
State
// Произвольное название
name: "hovered" ;
// Указание на то, когда элемент переходит в это состояние
// в данном случае когда нажата левая кнопка мыши
when: mouseArea.pressed;
// Какие свойства будут изменяться в этом состоянии
// в данном случае это будет прозрачность
PropertyChanges < target: button; opacity: 1;>
>,
State
name: "normal"
// В это состояние элемент будет переходить
// когда левая кнопка мыши не нажата
when: mouseArea.pressed == false ;
PropertyChanges < target: button; opacity: 0.7; >
>
]
>

Элемент может переходить в определенное состояние как автоматически при выполнении условия, указанного в when, так и вручную, путем изменения свойства state.

Запустили, нажали, прозрачность изменяется, уже лучше, но не хватает плавности. Добавим следующий код:

Image
.
Behavior on opacity
// Анимация с шагом в 100 миллисекунд
// Раз в 100 миллисекунд прозрачность будет изменяться
// на 0,1
NumberAnimation < duration: 100 >
>
>

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


Запускаем и смотрим, совсем другое дело, плавный переход от полупрозрачного к непрозрачному состоянию.

Окно о программе будет реализовано полностью на QML. Это будет модальное окно, которое будет появляться при нажатии кнопки about. При щелчке левой клавишей мыши в любом месте окна оно будет исчезать. Добавим новый QML файл About.qml в проект.


Я приведу сразу весь код этого окна с пояснениями

// Главный элемент для диалогового окна
Rectangle
id: about

// Функция для отображения окна
// изменяет прозрачность главного элемента
function show()
about.opacity = 1;
>

// Функция для закрытия окна
function hide()
about.opacity = 0;
>

// Прозрачный задний фон
color: "transparent"
// Полностью прозрачен по умолчанию
opacity: 0

// Ширина и высота устанавливаются равными
// ширине и высоте родительского элемента
// в данном случае это элемент с id: canvas
width: parent.width
height: parent.height

// Видимым элемент будет считаться если выполняется условие
// opacity > 0
visible: opacity > 0

// Дочерний элемент, создающий полупрозрачный фон
Rectangle
anchors.fill: parent

// Дочерний элемент создающий который является диалогом
// "О программе. "
Rectangle
id: dialog

// Ширина и высота являются фиксированными
width: 360
height: 230

// Координаты верхнего левого угла вычисляются
// исходя из размеров самого диалога и родителя
// так, чтобы окно располагалось в центре
x: parent.width / 2 - dialog.width / 2;
y: parent.height / 2 - dialog.height / 2;
// Задаем z индекс таким, чтобы он был
// больше z тех элементов, которые должны остаться
// за диалоговым окном
z: 10

Text
text: "4 Toddler"

// Выравнивание элемента по центру
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
>
>

Behavior on opacity
NumberAnimation < duration: 100 >
>

MouseArea
// Элемент полностью заполняет родительский элемент
anchors.fill: parent;

// При клике в любом месте прячем окно
onClicked: hide();
>
>

Свойство может быть не только задано, но и вычислено.

Осталось добавить диалог и код для его отображения при нажатии кнопки about. В файл Main.qml добавим код, в конце элемента canvas

Для того, чтобы окно отображалось добавим строку

в функцию callback кнопки about


Теперь добавим, собственно основной функционал. Начнем с отображения случайной картинки при нажатии любой клавиши. Картинка будет являться эелементом Image, определим этот элемент в отдельном файле. Добавим в проект файл Block.qml

// Новое свойство объекта, необходимое
// для изменения состояния при удалении объекта
property bool remove: false
// При добавлении объекта
property bool show: false

opacity: 0;
fillMode: Image.Stretch;

states: [
State
// Состояние, в которое переходит объект
// тогда, когда нам нужно его удалить
name: "remove" ; when: remove == true ;
PropertyChanges < target: block; opacity: 0 >
StateChangeScript < script: block.destroy(1000); >
>,
State
// Состояние, в которое переходит объект
// тогда, когда нам нужно его отобразить
name: "show" ; when: show == true ;
PropertyChanges < target: block; opacity: 1 >
>
]


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

// Шаблон для создания новых элементов
var component = Qt.createComponent( "block.qml" );

// Максимальное количество элементов
var maxBlocksCount = 10;

// Массив, в котором будут храниться все эелементы
var blocksArray = new Array();

// Функция обработчик нажатия клавиши
function handleKey()
// Координата x - случайно число от 0 до ширины окна
var x = Math .floor( Math .random() * canvas.width);
// Координата y - случайно число от 0 до ширины окна
var y = Math .floor( Math .random() * canvas.height);

// Вызов функции, которая создаст новый элемент
// с указанными координатами
createNewBlock(x, y);
>

// Создание нового элемента
function createNewBlock(x, y)
if (component.status != Component.Ready)
return false ;
>

// Удалить лишние элементы
if (blocksArray.length > maxBlocksCount)
removeAllBlocks();
>

var newBlock = component.createObject(canvas);

if (newBlock == null )
return false ;
>

// Путь к файлу иконки доступен через свойство главного
// окна randomIcon
var iconFile = window.randomIcon;

newBlock.source = ( "Icons/" + iconFile);

newBlock.x = x;
newBlock.y = y;

// Переводим элемент в состояние show
newBlock.show = true ;

// Проигрываем случайный звуковой эффект
window.PlaySound();

// Удаление всех добавленных элементов
function removeAllBlocks()
for ( var i = 0; i true ;
>

Как видно из кода нам еще следует реализовать свойство randomIcon и функицию PlaySound главного окна.

Добавим свойство в объявление класса MainWindow

И объявление функции

QString MainWindow::RandomIcon()
QStringList iconFilesList;
QString searchPath = m_ContentPath + "/Icons/" ;

QDir directory = QDir(searchPath);
QStringList filters;
filters "*.jpg" ;
directory.setNameFilters(filters);
// Получаем список файлов с расширением png
iconFilesList = directory.entryList(QDir::AllEntries);

// Получаем случайный индекс элемента
int fileIdx = qrand() % iconFilesList.count();

// Возвращаем название файла
return iconFilesList.at(fileIdx);
>

void MainWindow::PlaySound()
QStringList soundFilesList;
QDir directory = QDir(m_ContentPath + "/Sounds/" );
QStringList filters;
filters "*.wav" ;
directory.setNameFilters(filters);

// Получаем список файлов с расширением wav
soundFilesList = directory.entryList(QDir::AllEntries);
// Получаем случайный индекс элемента
int fileIdx = qrand() % soundFilesList.count();

// Получаем название файла
QString soundFile = m_ContentPath + "/Sounds/" + soundFilesList.at(fileIdx);
// Проигрываем файл
QSound::play(soundFile);
>

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

и сам обработчик внутри элемента canvas

На этом все — можем запускать и любоваться.




есть окно, унаследованное от QDialog.

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

Как его можно заставить ?



setWindowFlags(Qt::Popup|Qt::Dialog);
для конкретности покажите плиз, как Вы его на данный момент создаете



setWindowFlags(Qt::Popup|Qt::Dialog);
для конкретности покажите плиз, как Вы его на данный момент создаете

тоесть Qt::Popup спасет отца русской демократии ?



Property Documentation
modal : bool
This property holds whether show() should pop up the dialog as modal or modeless.
By default, this property is false and show() pops up the dialog as modeless. Setting his property to true is equivalent to setting QWidget::windowModality to Qt::ApplicationModal.
exec() ignores the value of this property and always pops up the dialog as modal.
Access functions:
bool isModal () const
void setModal ( bool modal )
See also QWidget::windowModality, show(), and exec().



да. на сколько я понял из буржуйского языка, exec, который я использую - отменяет свойство modal.
явная установка помогла

а флагами никак нельзя ?





Странно. возможно это баг Qt.



а я так старался

странно. ну я же не один пытаюсь модально вызвать. неужели никто раньше не замечал ?

Запомнил Лет 10 учил. Похоче англичанини из меня еще тот

archimed7592, рассказыаю прикол.
Недели 2 назад еду в Питер по работе. Сели в поезд часов в 11.
Ну думаю пойду умоюсь, покурю и спать. Выхожу из тамбура - смотру из какого-то купе уходят люди.
Я подхожу - опа - мое купэ. Ну я типа культурный человек:
- Здравствуйте.

Ноль эмоций. Сидят 2 человека: женщина и мужчина. Смотрят на меня квадратными глазами. Я понимаю, что что-то не так. Мой сотрудник говорит:
- Это корейцы и разговаривают они только на английском.

Хорошо он соображал в этом чудном наречии. А прикинь, я бы ехал один
Вот это бы был попадос

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