Не обновляется таблица QTableWidget, если произвести изменения в файле, откуда берется информация для таблицы

Рейтинг: 0Ответов: 2Опубликовано: 10.05.2023

Всем привет. Пишу программку одну, где использую таблицу при помощи QTableWidget. Информация, которой заполняется таблица, берется из обычного файла. Но если, во время работы программы, сделать изменения в файле, то таблица покажет эти изменения только при перезапуске программы. А мне надо, чтобы таблица могла обновляться без перезапуска программы. Как это исправить ?

Файл list_cart_on_storage.h

class List_cart_on_storage : public QObject
{
 
Q_OBJECT
 
public:
    //Окно со списком
    QWidget window;
    QTableWidget *item = new QTableWidget(0,4);//наша таблица
 
    QVBoxLayout *vbox = new QVBoxLayout();
    QPushButton *btnRedact = new QPushButton("Сохранить");
    QPushButton *btnDelete = new QPushButton("Удалить");
 
    List_cart_on_storage();
 
public slots:
    void Save();
 
};

Файл list_cart_on_storage.cpp

#include "list_cart_on_storage.h"
 
List_cart_on_storage::List_cart_on_storage()
{
 
    Main_menu class_Main_menu;
 
    window.setWindowModality(Qt::ApplicationModal); //Окно стало модальным. т.е. нельзся использовать главное окно, пока открыто это
    window.setWindowTitle("Список картриджей на складе");//Титульник
    window.resize(class_Main_menu.rect.width()*0.5, class_Main_menu.rect.height()*0.5); //Задали размер окна
 
    item->setHorizontalHeaderItem(0,new QTableWidgetItem("ID"));
    item->setHorizontalHeaderItem(1,new QTableWidgetItem("Бухгалтерский номер"));
    item->setHorizontalHeaderItem(2,new QTableWidgetItem("Название"));
    item->setHorizontalHeaderItem(3,new QTableWidgetItem("Кол-во на складе"));
 
    std::ifstream a("List_cart");
    std::string text;
    int int_id;
    int int_buhNum;
    int int_kolvo;
    for(int i=0;!a.eof();i++)
    {
 
        item->insertRow(item->rowCount());
        a >> int_id >> int_buhNum >> text >> int_kolvo;
 
        QTableWidgetItem *q_id = new QTableWidgetItem();
        q_id->setData(Qt::DisplayRole, int_id);
        item->setItem(i,0,q_id);
 
        QTableWidgetItem *q_buhNum = new QTableWidgetItem();
        q_buhNum->setData(Qt::DisplayRole, int_buhNum);
        item->setItem(i,1,q_buhNum);
 
        int length = text.length();
        for(int b=0;b<length;b++) if(text[b]=='`')text[b]=' ';
        QTableWidgetItem *q_text = new QTableWidgetItem(QString::fromStdString(text));
        item->setItem(i,2,q_text);
 
        QTableWidgetItem *q_kolvo = new QTableWidgetItem();
        q_kolvo->setData(Qt::DisplayRole, int_kolvo);
        item->setItem(i,3,q_kolvo);
 
    }
    a.close();
    item->removeRow(item->rowCount()-1); //Костыль
    item->setAlternatingRowColors(true);
    item->setSortingEnabled(true); //Сортировка
    vbox->addWidget(btnRedact);
    vbox->addWidget(btnDelete);
    vbox->addWidget(item);
    window.setLayout(vbox);
 
}

Ответы

▲ 0Принят

Всем большое спасибо ! В итоге решил свою проблему переходом на QTableView. И отображается все нормально, и сортируется нормально, и обновляется нормально Вот мой код

list_cart_on_storage.h

class List_cart_on_storage : public QObject
{
 
Q_OBJECT
 
public:
    //Окно со списком
    QWidget window;
 
    QStandardItemModel *table = new QStandardItemModel();
    QTableView *table_view = new QTableView();
 
    QVBoxLayout *vbox = new QVBoxLayout();
    QPushButton *btnRedact = new QPushButton("Сохранить");
    QPushButton *btnDelete = new QPushButton("Удалить");
 
    List_cart_on_storage();
 
public slots:
    void Save();
    void Paint();
};

list_cart_on_storage.cpp

#include "list_cart_on_storage.h"

List_cart_on_storage::List_cart_on_storage()
{

    QFileSystemWatcher *fwatcher=new QFileSystemWatcher;
    fwatcher->addPath("List_cart");
    Main_menu class_Main_menu;

    window.setWindowModality(Qt::ApplicationModal); //Окно стало модальным. т.е. нельзся использовать гланвое окно, пока открыто это
    window.setWindowTitle("Список картриджей на складе");//Титульник
    window.resize(class_Main_menu.rect.width()*0.5, class_Main_menu.rect.height()*0.5); //Задали размер окна

    Paint();

    vbox->addWidget(btnRedact);
    vbox->addWidget(btnDelete);
    vbox->addWidget(table_view);
    window.setLayout(vbox);


    connect(fwatcher, &QFileSystemWatcher::fileChanged, [this]{Paint();});

}

void List_cart_on_storage::Save()
{

}

void List_cart_on_storage::Paint()
{

    table->setColumnCount(4);
    table->setHorizontalHeaderLabels({"ID","Бухгалтерский номер","Название","Кол-во на складе"});
    table->setRowCount(0);
    table_view->setSortingEnabled(true);
    table_view->setModel(table);

    std::ifstream file("List_cart");
    std::string text;
    int int_id;
    int int_buhNum;
    int int_kolvo;
    QModelIndex index;
    for(int i=0;!file.eof();i++)
        {

            table->insertRow(table->rowCount());
            file >> int_id >> int_buhNum >> text >> int_kolvo;

            table->setData(table->index(i,0,index),int_id,Qt::DisplayRole);
            table->setData(table->index(i,1,index),int_buhNum,Qt::DisplayRole);
            table->setData(table->index(i,3,index),int_kolvo,Qt::DisplayRole);

            int length = text.length();
            for(int b=0;b<length;b++) if(text[b]=='`')text[b]=' ';
            QStandardItem *q_text = new QStandardItem(QString::fromStdString(text));
            table->setItem(i,2,q_text);


        }
    table->removeRow(table->rowCount()-1); //Костыль
    file.close();

}

▲ 1

Кроссплатформенный вариант

class UpdatableTable : public QObject
{
    Q_OBJECT

public:
    UpdatableTable(QString filePath, QObject* parent = nullptr)
        : QObject{parent}
        , file_info_{filePath}
    {  
        updateTable();
        startTimer(100);
    }

protected:
    void timerEvent(QTimerEvent* event) override { 
        const auto lastModified{file_info_.lastModified()};
        if (lastModified != last_modified_) updateTable();
        last_modified_ = lastModified;
        startTimer(100);
    }

private:
    QFileInfo file_info_;
    QDateTime last_modified_;
};

Также можно для этого использовать QTimer::singleShot, либо отдельный std::thread с std::this_thread::sleep_for, либо QThread с QThread::msleep. Но, т.к. Qt нативно работает асинхронно, использовать для этого отдельный поток было бы неразумно.

Платформозависимый вариант

Но наиболее эффективный вариант - использовать платформозависимые инструменты, которые сообщат об изменении с минимальной задержкой и накладными расходами. Под Linux, если не ошибаюсь, это должен быть D-Bus.