Не обновляется таблица QTableWidget, если произвести изменения в файле, откуда берется информация для таблицы
Всем привет. Пишу программку одну, где использую таблицу при помощи 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);
}
Ответы (2 шт):
Кроссплатформенный вариант
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.
Всем большое спасибо ! В итоге решил свою проблему переходом на 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();
}