LINUX.ORG.RU

QT - форма перестает отрисовывать

 , ,


0

1

Доброго времени уважаемые форумчане) Буду очень признателен, если кто-нибудь объяснит мне, в чем суть проблемы. Нашел исходник программы, которая отслеживает обращения к выбранному файлу с помощью Inotify. Исходник консольный. Переделал его для QT сперва заменив printf на qDebug() - все отлично работает. Однако мне нужен GUI - поэтому, заменил дебаг на listwidget.InsertItem(). Как только программа начинает отслеживать изменения файла, форма зависает и перестает отрисовываться и реагировать на нажатия. Посколько qDebug нормально работает, я сделал вывод, что просот не до конца понимаю специфику работы GUI приложений. Подскажите пожалуйста, где я упустил что.

Выкладываю код, при котором GUI зависает:

Код:

void Dialog::on_pushButton_clicked()
{
      char *tar2="/home/eugenes/111";
       char target[FILENAME_MAX];
            int fd;
       int wd;   /* watch descriptor */


       ui->listWidget->insertItem(0, QString("!!!Watching"));
          strcpy (target, tar2);
       fd = inotify_init();
       wd = inotify_add_watch (fd, target, IN_ALL_EVENTS);
       fd = inotify_init();

       while (1) {
          get_event(fd, target);
       }

}

void Dialog::get_event (int fd, const char * target)
{
    ssize_t len, i = 0;
    char action[81+FILENAME_MAX] = {0};
    char buff[BUFF_SIZE] = {0};

    len = read (fd, buff, BUFF_SIZE);

    while (i < len) {
       struct inotify_event *pevent = (struct inotify_event *)&buff[i];
       char action[81+FILENAME_MAX] = {0};

       if (pevent->len)
          strcpy (action, pevent->name);
       else
          strcpy (action, target);

       if (pevent->mask & IN_ACCESS)
          strcat(action, " was read");
       if (pevent->mask & IN_ATTRIB)
          strcat(action, " Metadata changed");
       if (pevent->mask & IN_CLOSE_WRITE)
          strcat(action, " opened for writing was closed");
       if (pevent->mask & IN_CLOSE_NOWRITE)
          strcat(action, " not opened for writing was closed");
       if (pevent->mask & IN_CREATE)
          strcat(action, " created in watched directory");

       if (pevent->mask & IN_MODIFY)
          strcat(action, " was modified");
       if (pevent->mask & IN_OPEN)
          strcat(action, " was opened");


       if (pevent->len) printf ("name=%s\n", pevent->name);


       ui->listWidget->insertItem(0, QString(action));

       i += sizeof(struct inotify_event) + pevent->len;

    }

}  /* get_event */


У меня QuickTime вообще только видео играет. Я и не знал, что он формы рисовать умеет.

anonymous
()

Обработчик не отдает управление:

void Dialog::on_pushButton_clicked()
{
       // ...

       while (1) { // это надо запускать в отдельном потоке
          get_event(fd, target);
       }

}

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 1)

не делай работы в ui-thread.

while (1) {
get_event(fd, target);
}

не даст завершиться обработчику нажатия кнопки -> ui-thread залочен.
ч.и.т.д.

aol ★★★★★
()

QT - форма перестает отрисовывать

       while (1) {
          get_event(fd, target);
       }

What did you expect would happen?

anonymous
()

Для понимания сути происходящего вам необходимо написать свое собственное оконное приложение с циклом обработки сообщений. Иначе и в дальнейшем будет куча проблем.

Как это сделать в linux я, к сожалению, не в курсе. Видимо через X-ы.

P.S. Вам конечно предложат что-то типа QApplicationc::processEvents(), но все же начните с приложения, которое я рекомендовал вам написать выше.

P.P.S. По X-ам вам сможет подсказать geekless

trex6 ★★★★★
()
Ответ на: комментарий от KennyMinigun

Ну, бесконечный цикл нужен, т.к. обращения к файлу необходимо отслеживать пока работает программа. Подскажите пожалуйста, как мне подружить inotify с Qt? Я пробовал сделать это с помощью QApp->processEvents(), который вроде применяют в таких ситуациях, когда функция выполняется долго, а перерисовка необходима чаще. Но результата это не дало.

Anath
() автор топика
Ответ на: комментарий от trex6

Для понимания сути происходящего вам необходимо написать свое собственное оконное приложение с циклом обработки сообщений.

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

anonymous
()
Ответ на: комментарий от Anath

Или проверяй inotify эвенты по таймеру.

anonymous
()
Ответ на: комментарий от aol

не делай работы в ui-thread.

так а где это делать? Если делать вне диалога, а в главном цикле, то наверное ерунда получится.

Если мы сделаем до app.exec(), то бесконечный цикл не даст нам запустить программу, если после - вообще ничего не получим.

Anath
() автор топика
Ответ на: комментарий от Anath

Или как уже написали - запустить отслеживание в другом потоке, сделать всё красиво: слоты-сигналы.

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

KennyMinigun ★★★★★
()
Ответ на: комментарий от Anath

Если делать вне диалога, а в главном цикле, то наверное ерунда получится.

В каком еще главном цикле? UI-поток является основным потоком, я так понимаю, ты его назвал «главным циклом».

так а где это делать?

Очевидно в отдельном потоке. (см. QThread)

А вообще тебе уже дали ссылку на QFileSystemWatcher или как он там, который под капотом юзает inotify.

anonymous
()
Ответ на: комментарий от anonymous

Для понимания сути происходящего вам необходимо написать свое собственное оконное приложение с циклом обработки сообщений.

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

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

trex6 ★★★★★
()
Ответ на: комментарий от Anath

не подходит, к сожалению - он может просто отслеживать удаление или изменение, а мне нужно открытие, закрытие, модификация, изменение метаданных.

Ну так открой его сорцы, посмотри как там все сделано, и допили недостающие функции. Что же ты такой беспомощный?

anonymous
()
Ответ на: комментарий от trex6

Опыт, приобретенный в результате таких манипуляций бесценен.
бесценен

Посмеялсо.

Иначе потом будет еще куча вопросов как да почему.

Какая чушь. Если тебе необходимо писать свои велосипеды, чтобы понять как все работает, это не значит, что и всем остальным необходимо.

anonymous
()
Ответ на: комментарий от anonymous

понять как все работает

тоже не всем необходимо

nokachi
()
Ответ на: комментарий от KennyMinigun

тем более без вызова Application ProcessEvents эта строка вообще бессмысленна и по сути зависон - вот и не рисует

I-Love-Microsoft ★★★★★
()

inotify_init возвращает не что иное, как обычный файловый дескриптор, который можно опрашивать (poll) в рамках цикла обработки сообщений Qt, не замораживая его - завернуть дескриптор в QAbstractSocket и понавешать на него сигналов.

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

yoghurt ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.