简体   繁体   English

您如何在程序的后台运行功能(特别是自动保存功能)? QT/C++

[英]How do you run a function in the background of your program (Specifically an autosave function)? QT / C++

In my code I would like to integrate an auto-save function that runs every couple seconds or so.在我的代码中,我想集成一个每隔几秒左右运行一次的自动保存功能。 I would like this to run in the background because I have other stuff that I am going to be running at the same time.我希望它在后台运行,因为我还有其他东西要同时运行。 So how would I do this?那我该怎么做呢?

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <fstream>
#include <QFile>
#include <QDebug>
using namespace std;

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) {
    ui->setupUi(this);

    // Setup code
    ui->textEdit->setReadOnly(true);
    ui->textEdit->append("Select one of the buttons on the left to pick a log");

}

MainWindow::~MainWindow() {
    delete ui;
}

string lastSavedText[] = {
    " ",

        " "
    };

QString qLastSavedTextHome, qLastSavedTextWork;

This is my first button这是我的第一个按钮

void MainWindow::on_homeButton_clicked() {
    // Preparing text edit
    ui->textEdit->setReadOnly(false);
    ui->textEdit->clear();
    ui->textEdit->setOverwriteMode(true);

    // Loading previously saved text
    QFile file { "home.apl" };
    if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) {
        qDebug() << "Could not open file!";
        return;
    }

    const auto& lastSavedText = file.readAll();
    file.close();

    ui->textEdit->setPlainText( lastSavedText );
}

This is my second one这是我的第二个

void MainWindow::on_workButton_clicked() {
    // Preparing text edit
    ui->textEdit->setReadOnly(false);
    ui->textEdit->clear();
    ui->textEdit->setOverwriteMode(true);

    // Loading previously saved text
    QFile file2 { "work.apl" };
    if ( !file2.open(QIODevice::ReadOnly | QIODevice::Text) ) {
        qDebug() << "Could not open file!";
        return;
    }

    const auto& lastSavedText = file2.readAll();
    file2.close();

    ui->textEdit->setPlainText( lastSavedText );

}

This is the save button I hope to eliminate with an autosave这是我希望通过自动保存消除的保存按钮

void MainWindow::on_saveButton_clicked() {

    // Converts textEdit to string
    QString textEditText = ui->textEdit->toPlainText();
    lastSavedText[0] = textEditText.toStdString();

    // Saving files
    ofstream home;
    home.open("home.apl");
    home << lastSavedText[0];
    home.close();

    ofstream work;
    work.open("work.apl");
    work << lastSavedText[1];
    work.close();
}

There is 2 solutions.有2个解决方案。

Easy one简单的一个

Use simply a timer that will execute the code of your save button.只需使用一个计时器来执行保存按钮的代码。 You can set the timer to execute any period of time.您可以设置计时器以执行任何时间段。

QTimer定时器

But this might cause the software to freeze if this operation takes too much time.但是,如果此操作花费太多时间,这可能会导致软件冻结。 In which case, you can put the function that saves inside a thread.在这种情况下,您可以将保存的函数放在线程中。


Threads线程

You can use threads to do that.您可以使用线程来做到这一点。

Thread, is basically a process that will detach from your main process and can be run at the same time, each thread doing its own work.线程,基本上是一个与主进程分离并可以同时运行的进程,每个线程都做自己的工作。

Note that to communicate between thread, the safest method is to use signals.注意线程间通信,最安全的方法是使用信号。

Qt Threads Documentation Qt 线程文档

Example 例子

void MyObject::startWorkInAThread()
{
    WorkerThread *workerThread = new WorkerThread(this);
    connect(workerThread, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
    connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
    workerThread->start();
}

You can use a QTimer with QtConcurrent::run, and then you get the simplicity with the benefit of running the saving on a different thread you don't need to manage.您可以将 QTimer 与 QtConcurrent::run 一起使用,然后您可以通过在不需要管理的不同线程上运行保存来获得简单性。 Practically, try实际上,尝试

QTimer::singleShot(time, this, Qt::TimerType::CoarseTime, QtConcurrent::run(this,&MainWindow::on_saveButton_clicked));

Here's a first approximation using a background thread (for the sake of brevity, it inherits QThread - for your real application, consider decoupling the QThread base-class from this worker thread object. That will also make it possible to give a father-object for t ).这是使用后台线程的第一个近似值(为简洁起见,它继承了QThread - 对于您的实际应用程序,请考虑将QThread基类与此工作线程对象解耦。这也可以为t )。

class Thread: public QThread {
Q_OBJECT
public:
Thread(QTextEdit *textEdit):textEdit(textEdit) { 
   QTimer *t = new QTimer;
   connect(t, SIGNAL(timeout()), SLOT(saveOnce()));
   t->moveToThread(this);
   t->start(2000);
}

protected:
QTextEdit *textEdit;
std::string lastSavedText[2];

private slots:   
QString text() const { return textEdit->toPlainText(); }  
void saveOnce() {
   QString textEditText;
   QMetaObject::invokeMethod(this, 
      "text", Qt::BlockingQueuedConnection, 
      Q_RETURN_ARG(QString,textEditText));

   lastSavedText[0] = textEditText.toStdString();

   // Saving files
   ofstream home;
   home.open("home.apl");
   home << lastSavedText[0];
   home.close();

   ofstream work;
   work.open("work.apl");
   work << lastSavedText[1];
   work.close();
} 
};

Care must be taken, when taking this approach with BlockingQueuedConnection, that the thread does not call invokeMethod while the main thread is waiting for it to exit - then a deadlock happens because the main-thread cannot process the text() queued call anymore.必须注意,在使用 BlockingQueuedConnection 采取这种方法时,线程不会在主线程等待退出时调用invokeMethod - 然后发生死锁,因为主线程无法再处理text()排队调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM