1

I want to read some text from file and display in QTextEdit. File is about 2 MB. I have created QObject class and connect signals and slots with thread. The problem is it still freezes window even when the thread is running.

My code:

QObject class:

void TestReader::readTestFile()
{
    QFile dbFile;
    QTextStream dbTextStream;
    dbFile.setFileName(":Test/Test.txt");
    dbFile.open(QFile::ReadOnly);
    dbTextStream.setDevice(&dbFile);
    QString data;

    while (!dbTextStream.atEnd()) {
        data = dbTextStream.readLine();
        emit testData(data);
    }

    emit finished();
}

GUI window:

readerThread = new QThread();
reader = new TestReader();
reader->moveToThread(readerThread);
connect(readerThread, &QThread::started, reader, &TestReader::readTestFile);
connect(reader, &TestReader::testData, this, &TestWindow::loadTestData);
connect(reader, &TestReader::finished, readerThread, &QThread::quit, Qt::DirectConnection);
readerThread->start();

How to fix it? Thanks in advance for your help.

Update: I have decided to use QtConcurrent.

Code:

dbFile.setFileName(":Test/Test.txt");
dbFile.open(QIODevice::ReadOnly);
dbTextStream.setDevice(&dbFile);
dbTextStream.setCodec("windows-1251");
QFuture<QString> myData = QtConcurrent::run(this, &TestWindow::loadTestData);
ui->plainTextEdit->appendPlainText(myData.result());

QString TestWindow::loadTestData()
{
  QString data = dbTextStream.readAll();
  return data;
}

No errors, no warnings but it blocks window (GUI) for seconds.

Cobra91151
  • 610
  • 4
  • 14
  • In the second call to `connect()` why do you connect `reader` to `this` ? – Benjamin T Mar 19 '17 at 12:30
  • I connect to function `loadTestData` where I append text: `ui->textEdit->append(data);` – Cobra91151 Mar 19 '17 at 12:32
  • What is `this`? Is it also a `TestReader` ? Where is `TestReader::testData` emitted ? Is `databaseData`connected to something ? – Benjamin T Mar 19 '17 at 12:36
  • It should be emitting `testData(data);`(edited), `this` is `TestWindow` class (GUI) window. I can also connect like this: `connect(reader, &DatabaseReader::databaseData, ui->textEdit, &QTextEdit::append);`. But the window still not responding. – Cobra91151 Mar 19 '17 at 12:41
  • I think `QTextEdit` can't handle a lot of lines that's why window is not responding. – Cobra91151 Mar 19 '17 at 13:06
  • I'm not sure reading a 2MB file line by line and appending each line to a widget is a wise thing to do to optimize performances. – Benjamin T Mar 19 '17 at 15:28
  • So what is your solution? – Cobra91151 Mar 19 '17 at 15:34
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/138472/discussion-between-benjamin-t-and-cobra91151). – Benjamin T Mar 19 '17 at 16:26
  • Ok. Let's discuss it in a chat. – Cobra91151 Mar 19 '17 at 16:43
  • @Cobra91151 I didn't do it in Qt but in gtkmm we solved this by a timeout signal which read the file piecewice (say in 8 KByte blocks). It needed noticable time until large files were fully loaded but the GUI stayed responsive. In Qt, I would it probably solve this similar. (Multi threading in C++ is always a little bit dangerous for sporadic, hard to find errors. If there is a solution without I'd like to prefer this...) – Scheff's Cat Mar 19 '17 at 19:50
  • I will consider your suggestion. Thanks. – Cobra91151 Mar 19 '17 at 20:17

1 Answers1

1

Use QPlainTextEdit. From the QT documentation:

QPlainTextEdit is an advanced viewer/editor supporting plain text. It is optimized to handle large documents and to respond quickly to user input.

Hopefully this will help you.

Ervin Szilagyi
  • 14,274
  • 2
  • 25
  • 40
  • Thanks but the window still not responding. – Cobra91151 Mar 19 '17 at 14:06
  • To be honest, I don't really know if Qt does have anything else more sophisticated for displaying large amount of text. I guess you have a overwrite some text editing widget and implement some kind a caching logic. Probably you should display only what is necessary at the moment and if the user scrolls, for example, you reload your widget and display more text. – Ervin Szilagyi Mar 19 '17 at 14:15
  • I think the other option is to implement `QtConcurrent::run`. – Cobra91151 Mar 19 '17 at 14:26