【问题标题】:QFileSystemWatcher does not emit fileChanged() in console applicationQFileSystemWatcher 不在控制台应用程序中发出 fileChanged()
【发布时间】:2015-04-22 20:07:09
【问题描述】:

在我的文件 console.h/.cpp 我有一个小类,它只要求用户输入一些文本,然后再次打印文本,直到用户输入“退出”(参见方法consoleMain())。但是,在 main.cpp 我也有一个 QFileSystemWatcher 监视文件 MyTextFile.txt 并在文本文件更改时调用 Console::slotFileChanged(QString)。不幸的是,QFileSystemWatcher 不起作用。当我更改文本文件时,Console::slotFileChanged(QString) 永远不会执行。据我所知,QFileSystemWatcher 仅在主事件循环已启动时才有效,我的代码也是如此。 当我在 main.cpp 中禁用 QTimer::singlaShot 并将其替换为 emit console.signalStart() 不会进入主事件循环,但我看到QFileSystemWatcher 的消息(“文件已更改!”)在我输入“退出”后。 问题是:是否可以让用户与控制台交互并让 FileWatcher 在并行更改文本文件时发出信号? (我也尝试将QFileSystemWatcher 放入控制台类并在堆上创建它;不幸的是它没有改变任何东西)

这是我的代码:

console.h

#ifndef CONSOLE_H
#define CONSOLE_H

#include <iostream>
#include <QObject>
#include <QFileSystemWatcher>

class Console: public QObject
{
    Q_OBJECT

public:

    Console(QObject *parent = 0);
    ~Console();

signals:

    void signalStart();
    void signalEnd();

public slots:

    void consoleMain();
    void slotFileChanged(QString text);
    void slotEmit();
};

#endif // CONSOLE_H

console.cpp

#include "console.h"

Console::Console(QObject *parent): QObject(parent)
{
}

Console::~Console()
{
}

void Console::consoleMain()
{
    bool isRunning = true;
    std::string in;

    while (isRunning)
    {
        std::cout << ">" << std::flush;
        std::getline(std::cin, in);

        if (in.compare("quit") == 0)
            isRunning = false;
        else
            std::cout << "You have entered: " << in << std::endl;
    }

    emit signalEnd();
}

void Console::slotFileChanged(QString text)
{
    Q_UNUSED(text);
    std::cout << "File changed!" << std::endl;
}  

void Console::slotEmit()
{
    emit signalStart();
}

ma​​in.cpp

#include "console.h"
#include <QCoreApplication>
#include <QTimer>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QFileSystemWatcher watcher(&a);
    watcher.addPath("C:/MyTextFile.txt");

    Console console(&a);

    QObject::connect(&console, SIGNAL(signalStart()), &console, SLOT(consoleMain()));
    QObject::connect(&console, SIGNAL(signalEnd()), &a, SLOT(quit()));
    QObject::connect(&watcher, SIGNAL(fileChanged(QString)), &console, SLOT(slotFileChanged(QString)));

    QTimer::singleShot(0, &console, SLOT(slotEmit()));
    //emit console.signalStart();

    std::cout << "Enter main event loop now" << std::endl;
    return a.exec();
}

【问题讨论】:

  • 你明确地调用consoleMain。直到它完成运行,它才会运行。据我所知,Qt 几乎没有控制台支持。可能最简单的解决方法是让一个线程坐在控制台上,主事件循环在另一个线程上运行,并让控制台发送消息以与主事件循环通信?谷歌找到了stackoverflow.com/a/18889631/1774667 答案,这似乎是通过消息传递输入的字符,您必须手动重新组合。

标签: c++ qt console qfilesystemwatcher


【解决方案1】:

好的,解决了。我已经使用不同的线程尝试了 Yakk 的想法(感谢 Yakk 的想法)。我不得不引入一个名为MyObjectQObject 的新子类。在它的构造函数中,我为控制台对象创建了Console 和一个新的QThreadQFileSystemWatcher 是在 main.cpp 中创建的,也是 MyObjcet 的一个实例。见以下代码:

myobject.h

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include "console.h"
#include <QThread>
#include <QCoreApplication>

class MyObject : public QObject
{
    Q_OBJECT

public:

    MyObject(QObject *parent = 0);
    ~MyObject();

private:

    QThread *thread;
    Console *console;

signals:

    void signalStart();

public slots:

    void slotFileChanged(QString text);
    void slotEnd();
};

#endif // MYOBJECT_H

myobject.cpp

#include "myobject.h"

MyObject::MyObject(QObject *parent): QObject(parent)
{
    console = new Console;

    thread = new QThread(this);
    console->moveToThread(thread);
    thread->start();

    connect(this, SIGNAL(signalStart()), console, SLOT(consoleMain()));
    connect(console, SIGNAL(signalEnd()), this, SLOT(slotEnd()));
    emit signalStart();
}

MyObject::~MyObject()
{
    thread->quit();
    thread->wait();
}

void MyObject::slotFileChanged(QString text)
{
    console->displayChangedFileText(text);
}

void MyObject::slotEnd()
{
    QCoreApplication::exit(0);
}

ma​​in.cpp

#include "myobject.h"
#include <QTimer>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QFileSystemWatcher *watcher = new QFileSystemWatcher(&a);
    watcher->addPath("C:/MyTextFile.txt");

    MyObject *object = new MyObject(&a);

    QObject::connect(watcher, SIGNAL(fileChanged(QString)), object, SLOT(slotFileChanged(QString)));

    std::cout << "Enter main event loop now" << std::endl;
    return a.exec();
}

console.h/.cpp 未更新,只有 Console::slotFileChanged(QString)Console::displayChangedFileText(QString) 替换。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-11
    • 2014-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    相关资源
    最近更新 更多