QtQFileSystemWatcher:信号fileChanged()只被发射一次

Qt QFileSystemWatcher: signal fileChanged() gets emited only once

本文关键字:一次 被发射 fileChanged QtQFileSystemWatcher 信号      更新时间:2023-10-16

我正在尝试QFileSystemWatcher,但不知何故它没有按预期工作。还是我做错了什么?

我已将QFileSystemWatcher设置为监视单个文件。当我第一次修改文件时,fileChanged()会被发射,这没关系。但当我再次修改文件后,fileChanged()不会再被发射了。

这是源代码:

main.cpp

#include <QApplication>
#include "mainwindow.h"
int main(int argc, char **argv)
{
  QApplication app(argc, argv);
  MainWindow window;
  window.show();
  return app.exec();
}

主窗口.h

#include <QDebug>
#include <QFileSystemWatcher>
#include <QMainWindow>
#include <QString>
class MainWindow : public QMainWindow
{
  Q_OBJECT
public:
  MainWindow();
private slots:
  void directoryChanged(const QString & path);
  void fileChanged(const QString & path);
private:
  QFileSystemWatcher * watcher;
};

mainwindow.cpp

#include "mainwindow.h"
MainWindow::MainWindow()
{
  watcher = new QFileSystemWatcher(this);
  connect(watcher, SIGNAL(fileChanged(const QString &)), this, SLOT(fileChanged(const QString &)));
  connect(watcher, SIGNAL(directoryChanged(const QString &)), this, SLOT(directoryChanged(const QString &)));
  watcher->addPath("path to directory");
  watcher->addPath("path to file");
}
void MainWindow::directoryChanged(const QString & path)
{
  qDebug() << path;
}
void MainWindow::fileChanged(const QString & path)
{
  qDebug() << path;
}

谢谢你的回答。

编辑1

我在Linux下运行了这段代码。

编辑2

实际上,我需要检查某个目录给定的树中的所有MetaPost文件,无论它们是否被修改。我可能会坚持我的替代解决方案,即每秒运行QTimer并手动检查所有文件。QFileSystemWatcher可能在内部以类似的方式执行此操作,但可能更有效。

刚才也遇到了同样的问题。似乎QFileSystemWatcher认为即使只修改了文件,也会删除该文件。至少在Linux文件系统上是这样。我的简单解决方案是:

if (QFile::exists(path)) {
    watcher->addPath(path);
}

将以上内容添加到fileChanged()的处理程序中。根据需要更改单词watcher

我在Linux上使用Qt5时也遇到了同样的问题。找出原因:

有些文本编辑器,如kate,不修改文件的内容,而是用新文件替换原始文件。替换文件将删除旧文件(IN_DELETE_SELF事件),因此qt将停止监视该文件。

一种解决方案是还监视文件目录中的创建事件。

我可以确认您对当前Qt5和Linux的问题。除了Peter给出的答案外,我还通过在插槽函数的末尾添加以下代码来解决这个问题:

QFileInfo checkFile(path);
while(!checkFile.exists())
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
watcher->addPath(path);

请注意,如果您立即添加路径,文件通常还不存在,您会收到警告,并且根本不会添加任何内容,并且观察者会丢失此路径。因此,你必须等待/睡眠,直到文件恢复正常,然后添加它。

还要注意的是,在这个例子中,我使用了C++11,并包含和用于实现睡眠。