Russian Qt Forum
Ноябрь 23, 2024, 22:15 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Как прекратить цикл for после закрытия приложения  (Прочитано 6678 раз)
Ilya_181
Новичок

Offline Offline

Сообщений: 33


Просмотр профиля
« : Август 11, 2017, 10:50 »

Как прекратить выполнение цикла for, foreach после закрытия приложения.
Код
C++ (Qt)
void MainWindow::func(QDir dir)
{
   foreach (QFileInfo fileInfo, dir.entryInfoList())
   {
       QApplication::processEvents();
 
           QTextCursor cursor = ui->textEdit->textCursor();
           cursor.insertText(fileInfo.absoluteFilePath());
 
           if(fileInfo.isDir() && fileInfo.baseName() != "" && fileInfo.baseName() != "." && fileInfo.baseName() != "..")
           func(QDir(fileInfo.absoluteFilePath()));
 
    }
}
 
void MainWindow::on_pushButton_clicked()
{
   func(some_dir);
   QMessageBox::information(this, "Title","Конец!");
}

Если несколько раз вызвать слот (on_pushButton_clicked()), функция вызовется несколько раз, а там еще рекурсия. Если преждевременно закрыть приложение, мало того что будет продолжаться выполнение кода, так еще QMessageBox будет периодически мигать.
Что сделать, чтобы по желанию пользователя можно было прекратить любое выполнение участка кода?
« Последнее редактирование: Август 12, 2017, 12:08 от Ilya_181 » Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #1 : Август 11, 2017, 11:23 »

Закрывайте приложение через
Код
C++ (Qt)
QApplication::quit()
Записан

Ilya_181
Новичок

Offline Offline

Сообщений: 33


Просмотр профиля
« Ответ #2 : Август 11, 2017, 11:52 »

Закрывайте приложение через QApplication::quit()

Если я правильно понял, это не работает.
Код
C++ (Qt)
MainWindow::~MainWindow()
{
   QApplication::quit();
   delete ui;
}
 
--------------------------------------------------------------------------------
void MainWindow::closeEvent(QCloseEvent *event)
{
   Q_UNUSED(event);
   QApplication::quit();
   QMainWindow::closeEvent(event); // если закомментировать тут, все-равно  результат отрицательный
}
Записан
qate
Супер
******
Offline Offline

Сообщений: 1177


Просмотр профиля
« Ответ #3 : Август 11, 2017, 12:42 »

завести переменную stop_now = false
по команде пользователя или в деструкторе MainWindow присвоить её true
в func проверять её, и сразу выход из func
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #4 : Август 11, 2017, 12:47 »

>" Если преждевременно закрыть приложение, мало того что будет продолжаться выполнение кода, так еще QMessageBox будет периодически мигать."
Если приложение закрыть, то ни какой код уже не будет выполнятся.

У тебя проблема где-то в другом месте.
Записан

Юра.
Ilya_181
Новичок

Offline Offline

Сообщений: 33


Просмотр профиля
« Ответ #5 : Август 12, 2017, 11:40 »

У тебя проблема где-то в другом месте.
Проблема здесь QApplication::processEvents();. Но processEvents() нужен для того чтобы приложение реагировало на действия пользователя во время выполнения цикла. Если его закомментировать программа зависает пока не выполнится код. А такое поведение программы не нужно.

Более того, если вызвать слот дважды, нажать на кнопку два раза, код программы выполниться дважды. Видимо за время между первым нажатием кнопки и вторым успевает выполниться строка QApplication::processEvents(); в цикле. То есть я нажимаю первый раз кнопку, мы попадаем в цикл, и когда я нажму еще раз кнопку, QApplication::processEvents(); запомнит событие и выполнит нажатие кнопки после окончания цикла, что в свою очередь, повлечет выполнение кода еще раз.

И если закрыть окно, QApplication::processEvents(); продолжает выполнять код.
« Последнее редактирование: Август 12, 2017, 12:07 от Ilya_181 » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Август 12, 2017, 13:01 »

Собсно "закоытие приложения" здесь ни при чем, с тем же успехом в processEvents может вызваться другой код который не позволит func (весьма невнятное имя) выполняться корректно. Это общая, фундаментальная (не побоюсь этого слова) проблема которая не имеет какого-то четкого, однозначного решения. Рецепты что я знаю

- сделать func "модальным", самое простое вызвать ее из модального окна

- навесить фильтр на QApplication который будет взводить флажок (напр при событии закрытия), а в func проверять его напр
Код
C++ (Qt)
QApplication::processEvents();
if (funcAbortFlag) return;

Для полноты картины заметим что популярная рекомендация "выноси в поток" здесь по существу ничего не меняет - все равно обеспечивать флажок.
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #7 : Август 14, 2017, 08:49 »

Ilya_181, Не менял ли ты настройку quitOnLastWindowClosed у QApplication?

И ещё:
приведи код функции main()
Записан

Юра.
Ilya_181
Новичок

Offline Offline

Сообщений: 33


Просмотр профиля
« Ответ #8 : Август 14, 2017, 18:49 »

Ilya_181, Не менял ли ты настройку quitOnLastWindowClosed у QApplication?

И ещё:
приведи код функции main()

Ничего нигде не менял.
Код
C++ (Qt)
       #include "mainwindow.h"
       #include <QApplication>
 
       int main(int argc, char *argv[])
       {
           QApplication a(argc, argv);
           MainWindow w;
           w.show();
 
           w.move(444,55);
           return a.exec();
       }
-----------------------------------------------------------------------------------------------------------
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
 
#include <QtWidgets>
#include <QWidget>
#include <QMessageBox>
#include <QTextEdit>
#include <QPushButton>
#include <QDir>
#include <QTextCursor>
#include <QVBoxLayout>
#include <QApplication>
 
class MainWindow : public QWidget
{
   Q_OBJECT
 
 
public:
   explicit MainWindow(QWidget *parent = 0) : QWidget(parent)
   {
       lay->addWidget(pushButton);
       lay->addWidget(textEdit);
       setLayout(lay);
       connect(pushButton, &QPushButton::clicked,this, &MainWindow::on_pushButton_clicked);
   }
   ~MainWindow(){}
 
QPushButton *pushButton = new QPushButton;
QTextEdit *textEdit = new QTextEdit;
QVBoxLayout *lay = new QVBoxLayout;
 
 
   void func(QDir dir)
   {
       foreach (QFileInfo fileInfo, dir.entryInfoList())
       {
           QApplication::processEvents();
 
               QTextCursor cursor = textEdit->textCursor();
               cursor.insertText(fileInfo.absoluteFilePath());
 
               if(fileInfo.isDir() && fileInfo.baseName() != "" && fileInfo.baseName() != "."
                                                               && fileInfo.baseName() != "..")
               func(QDir(fileInfo.absoluteFilePath()));
 
        }
   }
 
public slots:
   void on_pushButton_clicked()
   {
       func(QDir("D:/Programing/4.8/chapter41"));
       QMessageBox::information(this, "Title","Конец!");
   }
 
};
 
#endif // MAINWINDOW_H
 
 

добавил еще .h фаил. Запускаю и все выше описанное происходит. Можно скопировать код и запустить и проверить. Только каталог помять.
« Последнее редактирование: Август 14, 2017, 20:17 от Ilya_181 » Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #9 : Август 15, 2017, 07:48 »

Так как выбран подход явного управления обработкой событий, то вполне уместным будет и использование флага - признака завершения программы.
Он может быть как глобальным (паттерн синглтон в помощь), так и членом класса MainWindow, в зависимости от пространства имен в котором его нужно использовать.
Если пользователь желает прервать выполнение цикла то достаточно выставить флаг в значение true, а в цикле (и в любом другом месте) установить его проверку.
С точки зрения работоспособности программы - все будет работать, с точки зрения "правильной" архитектуры - все нужно делать по-другому  Подмигивающий.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #10 : Август 15, 2017, 09:57 »

Самое простое - заменить processEvents на модальный QProgressDialog (см примерчик в доке)
 
..и использование флага - признака завершения программы.
Мол, "и так можно" Улыбающийся Ну хорошо, а как иначе-то?

..с точки зрения "правильной" архитектуры - все нужно делать по-другому  Подмигивающий.
Расскажите, др способы (кроме озвученных выше) мне неизвестны
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.324 секунд. Запросов: 23.