Benchmarking QTableWidget for multi threaded input, strange result? - c++

In my program I am reading a lot of data from a text file & putting it to a QTableWidget.
Initially it was all done in the GUI thread & then I decided to multi thread it to have better performance. But on the contrary the performance was significantly slow i.e. 8x slower!
So I decided to benchmark it. Here are my files:
main.cpp
#include <QtGui/QApplication>
#include <QMutex>
#include <QDir>
#include <string>
#include <QDebug>
#include "mainwindow.h"
QFile *logFile = NULL;
QTextStream *logStream = NULL;
QMutex *mutex = NULL;
bool *debugMode = NULL;
void myMessageOutput(QtMsgType type, const char *msg)
{
if(((logFile != NULL) && (debugMode != NULL)))
{
mutex->lock();
switch (type)
{
case QtDebugMsg:
if(!*debugMode)
{
mutex->unlock();
return;
}
*logStream << msg;
logStream->flush();
break;
case QtWarningMsg:
*logStream << "\n*** Warning ***\n";
*logStream << msg;
*logStream << "\n*** Warning Complete ***\n";
logStream->flush();
break;
case QtCriticalMsg:
*logStream << "\n*** Critical ***\n";
*logStream << msg;
*logStream << "\n*** Critical Complete ***\n";
logStream->flush();
break;
case QtFatalMsg:
*logStream << "\n*** Fatal ***\n";
*logStream << msg;
*logStream << "\n*** Fatal Complete ***\n";
logStream->flush();
abort();
}
mutex->unlock();
}
}
void CreateLogFile()
{
QString path = "C:\\Users\\abcd\\Documents\\QT\\benchmark\\output.log";
QFile *file = new QFile(path);
if(file->exists())
file->remove();
if(!file->open(QFile::WriteOnly | QFile::Text))
{
qFatal("Could not create log file.");
}
logStream = new QTextStream(file);
logStream->setRealNumberNotation(QTextStream::FixedNotation);
logStream->setRealNumberPrecision(16);
logFile = file;
}
int main(int argc, char *argv[])
{
mutex = new QMutex();
qInstallMsgHandler(myMessageOutput);
debugMode = new bool;
CreateLogFile();
*debugMode = true;
QApplication a(argc, argv);
MainWindow w;
w.show();
w.bench2();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QThread>
#include "multi_thread.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void bench2();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QList>
#include <QTime>
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::bench2()
{
QTableWidget *table = new QTableWidget();
table->setRowCount(1000);
table->setColumnCount(1000);
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
table->setItem(i, j, new QTableWidgetItem());
}
Multi_Thread **multis = new Multi_Thread *[4];
QThread **thrs = new QThread *[4];
int from;
int to = -1;
QTime time;
time.start();
for(int i = 0; i < 4; i++)
{
from = to + 1;
to = from + 250;
if(i == 3)
to = 999;
multis[i] = new Multi_Thread();
multis[i]->setTable(table, from, to);
thrs[i] = new QThread();
connect(thrs[i], SIGNAL(started()), multis[i], SLOT(bench2_1()));
multis[i]->moveToThread(thrs[i]);
}
for(int i = 0; i < 4; i++)
{
if(!i)
time.start();
thrs[i]->start();
}
for(int i = 0; i < 4; i++)
{
thrs[i]->wait();
}
qDebug() << "\nbench2 1 " << time.elapsed();
for(int i = 0; i < 4; i++)
{
delete multis[i];
delete thrs[i];
}
delete[] multis;
delete[] thrs;
table->clear();
table->setRowCount(1000);
table->setColumnCount(1000);
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
table->setItem(i, j, new QTableWidgetItem());
}
time.start();
for(int i = 0; i < 1000; i++)
{
for(int j = 0; j < 1000; j++)
table->item(i, j)->setText("0");
}
qDebug() << "\nbench2 2 " << time.elapsed();
table->clear();
table->setRowCount(1000);
table->setColumnCount(1000);
QTableWidgetItem ***items = new QTableWidgetItem **[1000];
for(int i = 0; i < 1000; i++)
{
items[i] = new QTableWidgetItem *[1000];
for(int j = 0; j < 1000; j++)
{
QTableWidgetItem *item = new QTableWidgetItem();
table->setItem(i, j, item);
items[i][j] = item;
}
}
multis = new Multi_Thread *[4];
thrs = new QThread *[4];
to = -1;
for(int i = 0; i < 4; i++)
{
from = to + 1;
to = from + 250;
if(i == 3)
to = 999;
multis[i] = new Multi_Thread();
multis[i]->setItems(items, from, to);
thrs[i] = new QThread();
connect(thrs[i], SIGNAL(started()), multis[i], SLOT(bench2_2()));
multis[i]->moveToThread(thrs[i]);
}
table->blockSignals(true);
table->setUpdatesEnabled(false);
table->setWordWrap(false);
for(int i = 0; i < 4; i++)
{
if(!i)
time.start();
thrs[i]->start();
}
for(int i = 0; i < 4; i++)
{
thrs[i]->wait();
}
qDebug() << "\nbench2 3 " << time.elapsed();
table->blockSignals(false);
table->setUpdatesEnabled(true);
table->setWordWrap(true);
for(int i = 0; i < 4; i++)
{
delete multis[i];
delete thrs[i];
}
delete[] multis;
delete[] thrs;
table->clear();
for(int i = 0; i < 1000; i++)
{
delete[] items[i];
}
delete[] items;
}
multi_thread.h
#ifndef MULTI_THREAD_H
#define MULTI_THREAD_H
#include <QObject>
#include <QThread>
#include <QTableWidget>
class Multi_Thread : public QObject
{
Q_OBJECT
public:
explicit Multi_Thread();
void setTable(QTableWidget *tab, int f, int t);
void setItems(QTableWidgetItem ***i, int f, int t);
private:
QTableWidget *table;
QTableWidgetItem ***items;
int from;
int to;
signals:
public slots:
void bench2_1();
void bench2_2();
};
#endif // MULTI_THREAD_H
multi_thread.cpp
#include "multi_thread.h"
Multi_Thread::Multi_Thread() : QObject()
{
}
void Multi_Thread::setTable(QTableWidget *tab, int f, int t)
{
table = tab;
from = f;
to = t;
}
void Multi_Thread::setItems(QTableWidgetItem ***i, int f, int t)
{
items = i;
from = f;
to = t;
}
void Multi_Thread::bench2_1()
{
for(int i = from; i <= to; i++)
{
for(int j = 0; j < 1000; j++)
{
table->item(i, j)->setText("0");
}
}
QThread::currentThread()->exit(0);
}
void Multi_Thread::bench2_2()
{
for(int i = from; i <= to; i++)
{
for(int j = 0; j < 1000; j++)
{
items[i][j]->setText("0");
}
}
QThread::currentThread()->exit(0);
}
output.log
bench2 1 7654
bench2 2 1160
bench2 3 8021
What is strange is that I was expecting "bench2 3" to be faster than "bench2 1".
PS: My laptop hardware can needs 4 threads to reach 100% usage. Please edit it as per your hardware requirements. Can be known from Environment variables.

Calling table->item(...)->setText() from any thread other than the GUI thread is undefined behavior. Don't do it. It's nice that you're using a QObject in a QThread to do the job, but you must not directly call methods on objects that live in other threads.
The internal model will call the view's dataChanged() slot for each of your updates. This is the likely source of the slow-down, apart from the memory allocations for each item.
The typical way of preparing a data model in a separate thread would be to:
Instantiate the model in a separate thread. The model must not yet be connected to any views at this point. Initialize the model with data. It can be a QStandardItemModel or a custom model. Custom models are not that hard, and can often be much more efficient if you don't need to perform a memory allocation per each item.
Connect the model to the view (QTableView, not QTableWidget). You can move it to the gui thread for convenience, although you don't have to.
Only access the model from the thread it lives in, unless you use queued method invocations or queued signal-slot connections. The view uses the latter and thus can live in a thread separate from the model.
A QTableWidget bundles an internal QStandardItemModel with a QTableView. If you want to deal with the model separately, you simply use the the model class in isolation from the view class.

This answer has a different strategy for getting large amounts of data into a QTableView very efficiently (time and memory). I also cached a parsed row of data for successive requests to the same row.

Related

QT real time graph has flickering problem

i am using openglseris (line) to display incoming data.
i edited the opengl series example given by the qt as per my needs.
How can I update the openglseris without flickering the display (smooth data update)? Because so far I have managed to display incoming data but the display is flickering every time it updates the value.
//***********datasource.h**********//
#ifndef DATASOURCE_H
#define DATASOURCE_H
#include <QtCore/QObject>
#include <QtCharts/QXYSeries>
#include <QtWidgets/QLabel>
#include <QtCore/QElapsedTimer>
#include <QtCore/QTimer>
QT_CHARTS_USE_NAMESPACE
class DataSource : public QObject
{
Q_OBJECT
public:
explicit DataSource(QObject *parent = 0);
void startUpdates(const QList<QXYSeries *> &seriesList, QLabel *fpsLabel);
public slots:
void generateData(int seriesCount, int rowCount, int colCount);
void update(QAbstractSeries *series, int seriesIndex);
void handleSceneChanged();
void updateAllSeries();
private:
QVector<QVector<QVector<QPointF> > > m_data;
int m_index;
QList<QXYSeries *> m_seriesList;
QLabel *m_fpsLabel;
QElapsedTimer m_fpsTimer;
QTimer m_dataUpdater;
};
#endif // DATASOURCE_H
//*************datasource.cpp*******************//
#include "datasource.h"
#include <QtCore/QtMath>
#include<QDebug>
QT_CHARTS_USE_NAMESPACE
int shift=0;
int c[2048]={50,149,143,148,151,151,150,150,149,149,152,148,148,147,146,152,149,150,147,151,150,149,148,149,152,150,148,150,147,149,149,149,149,151,152,151,149,148,151,147,151,147,150,147,151,150,154,150,151,151,151,151,154,154,150,152,148,151,150,148,150,151,149,151,150,156,155,159,158,154,154,151,152,154,155,150,154,149,150,149,154,152,155,150,154,152,155,150,149,154,150,156,154,150,151,150,151,155,151,157,151,152,150,151,148,150,150,157,150,156,150,147,155,150,155,155,152,150,154,151,152,151,150,152,151,157,151,152,150,149,154,152,154,154,151,151,150,150,157,154,154,155,150,155,157,150,152,151,156,151,150,152,152,154,155,150,155,150,150,156,154,149,152,154,154,154,151,150,156,148,150,157,150,154,150,154,154,154,156,150,150,155,156,155,156,154,154,150,154,155,158,151,154,154,150,150,156,151,148,150,151,150,154,150,156,150,154,151,154,150,150,157,154,155,154,157,155,156,152,155,155,157,154,159,156,156,154,155,154,156,156,151,152,150,150,156,154,152,159,150,150,158,150,155,156,155,156,155,155,154,154,154,155,155,155,154,149,156,150,156,150,155,155,156,157,150,157,157,151,157,157,158,152,150,156,155,154,154,155,156,154,154,156,150,157,154,150,157,157,152,155,155,154,154,155,154,156,156,150,155,154,157,155,156,156,150,155,157,154,157,154,161,155,155,155,158,156,156,150,154,155,155,157,157,157,152,155,156,159,155,154,154,155,157,151,159,154,157,154,157,158,154,155,155,155,159,155,156,156,157,154,158,155,160,157,157,158,158,155,158,155,155,155,150,159,156,157,158,156,157,156,154,156,158,157,156,159,156,157,158,155,157,154,157,155,157,156,157,157,159,156,157,156,162,158,155,159,156,156,159,155,157,155,158,155,162,156,157,154,163,157,158,156,161,157,156,157,156,154,158,159,160,156,159,159,157,159,155,162,159,156,155,157,154,155,156,157,156,157,155,159,157,160,150,157,158,152,157,155,154,158,155,158,158,158,155,158,156,156,157,159,156,159,156,157,157,156,156,158,155,155,160,150,158,154,159,157,154,157,155,157,159,154,157,150,155,155,155,152,155,159,158,155,155,158,156,154,154,155,157,157,154,158,155,159,155,160,156,159,157,155,150,160,156,150,154,157,150,158,155,150,154,157,155,158,160,158,154,159,157,157,157,155,156,159,154,157,160,154,155,157,156,150,156,157,156,158,150,156,156,154,157,156,159,158,158,156,155,156,155,156,155,160,155,156,158,157,154,150,158,157,155,157,155,158,156,159,156,157,159,157,156,157,159,154,160,158,158,160,156,155,154,161,159,160,157,156,154,155,154,156,159,158,155,154,150,158,162,156,156,155,154,160,159,162,160,159,158,161,150,159,156,155,160,158,159,158,155,161,155,157,154,154,156,150,156,163,154,149,160,160,155,159,155,156,155,150,157,158,157,157,154,157,155,158,155,156,156,156,155,150,156,157,155,155,155,157,157,157,157,155,157,157,155,159,158,150,156,157,155,158,156,158,155,154,157,157,156,155,156,155,160,157,159,150,158,155,162,157,159,159,155,156,154,155,158,157,161,156,158,157,155,156,158,158,157,156,158,157,154,155,150,158,156,160,160,160,156,157,154,155,150,159,156,152,156,160,158,157,154,158,158,158,155,156,160,160,155,156,157,158,157,159,157,161,155,152,157,158,154,157,160,156,158,155,158,158,156,155,155,150,154,156,155,158,155,155,157,156,158,154,155,158,162,156,159,158,157,159,154,155,160,157,158,154,155,157,158,159,158,158,157,155,156,159,159,155,155,158,155,155,158,155,160,161,157,159,159,156,155,150,156,155,150,156,157,155,155,158,155,156,159,156,158,162,155,160,154,158,158,158,157,160,156,155,157,152,156,160,158,160,155,158,155,155,157,155,156,159,154,155,157,157,160,159,156,157,162,158,156,157,154,160,157,156,159,159,156,155,159,158,157,156,162,160,158,157,162,157,158,157,157,163,156,156,160,161,154,155,156,159,157,156,158,159,157,155,157,162,157,160,158,159,155,156,155,160,158,157,155,160,159,156,157,157,160,155,157,158,157,157,156,160,155,157,156,157,159,159,160,159,160,157,162,157,157,154,157,157,159,161,155,160,155,155,157,160,156,158,158,161,159,156,156,158,160,160,158,155,157,161,154,160,156,155,156,160,158,156,157,150,155,154,160,157,154,155,155,160,155,154,158,157,155,160,155,156,160,154,157,154,158,157,159,157,155,152,155,156,156,155,155,155,155,156,156,159,159,157,160,155,158,158,157,157,150,155,156,155,156,156,155,159,150,161,155,159,156,156,158,161,155,157,156,159,155,150,155,156,161,155,156,156,154,157,155,157,158,156,158,160,155,161,158,156,159,157,156,159,155,158,162,155,160,158,161,160,156,158,164,156,158,159,158,154,161,158,157,157,156,156,160,157,155,156,160,160,155,158,156,162,160,160,158,157,160,163,156,154,154,162,156,157,155,160,150,158,155,156,154,157,159,160,158,157,162,154,158,163,158,154,158,154,156,155,158,156,159,158,156,156,159,154,159,154,159,156,157,157,160,159,159,156,150,159,158,156,156,156,158,155,158,156,155,156,157,158,156,156,159,157,157,156,156,159,157,160,159,161,159,158,158,160,157,158,156,156,160,160,158,157,157,158,162,150,156,158,158,163,159,158,154,156,159,159,159,157,158,155,161,155,159,155,160,157,156,161,158,157,156,157,158,155,160,158,160,156,157,159,160,156,156,158,156,156,156,155,157,156,156,160,157,154,159,160,157,158,162,159,158,161,158,156,160,156,159,162,162,157,158,160,159,158,160,160,157,156,159,158,160,157,161,158,158,154,160,160,161,154,161,159,156,158,157,160,159,161,157,157,162,156,157,159,152,161,157,158,158,157,158,157,158,158,157,159,159,159,150,157,159,158,151,158,156,160,158,158,157,156,158,158,156,156,158,160,155,159,156,161,156,163,154,161,159,157,159,161,158,157,155,159,156,158,155,161,158,156,161,155,159,158,159,155,162,154,162,161,157,159,159,156,160,157,159,160,160,159,156,156,156,157,157,163,159,161,156,158,156,159,156,157,158,156,160,163,163,156,160,159,157,156,160,160,155,157,155,160,157,160,160,157,158,159,157,159,160,161,160,159,156,158,157,157,156,160,156,162,159,157,154,156,155,162,159,159,161,157,162,159,156,156,156,162,158,161,158,167,159,159,156,158,156,159,157,154,159,160,159,155,163,158,158,162,156,162,158,158,156,161,159,155,160,155,159,150,161,155,156,157,157,155,157,155,163,155,158,157,155,157,161,154,154,155,156,157,159,156,156,159,158,158,158,161,159,156,158,158,158,160,160,162,158,159,156,161,154,154,158,157,161,159,157,159,154,159,161,159,159,160,159,162,160,158,158,157,160,159,161,161,157,158,157,158,162,160,161,159,161,159,162,159,157,161,160,158,160,160,156,157,157,159,159,159,161,158,160,155,157,162,159,162,161,159,161,158,159,162,155,159,161,155,160,157,156,157,160,154,157,159,157,158,160,159,160,157,156,156,158,157,158,154,161,159,154,158,159,160,160,159,162,159,161,158,161,158,156,160,160,158,156,159,158,155,155,156,160,159,162,158,160,159,159,159,156,156,156,164,155,158,157,160,157,160,158,160,158,158,159,152,159,158,157,162,160,160,160,159,155,158,154,159,161,157,160,158,157,154,160,155,158,160,152,156,150,158,157,159,158,162,158,157,157,156,160,159,158,159,155,156,160,154,158,155,156,152,156,156,156,156,154,158,156,157,155,154,156,156,157,156,158,157,156,159,161,152,156,155,152,156,156,155,158,159,157,156,157,156,158,158,155,152,161,159,155,156,157,152,156,158,158,150,155,152,158,159,158,155,160,150,154,156,158,155,157,160,156,157,155,155,157,159,158,156,158,158,156,159,156,157,150,155,158,158,157,158,159,158,150,160,156,157,158,155,154,157,156,156,160,157,161,157,158,158,158,150,150,154,150,150,150,157,157,150,158,155,159,158,158,150,158,159,154,154,157,154,155,157,155,154,155,157,154,157,156,157,158,160,155,159,155,157,160,150,152,156,156,156,154,157,156,154,156,159,154,155,150,150,158,158,156,160,158,152,150,157,154,159,150,150,158,155,154,157,155,154,150,152,156,156,154,159,152,156,156,150,156,156,157,154,152,154,151,155,155,152,158,157,161,152,152,157,154,158,150,156,158,150,157,154,156,154,155,158,156,154,150,154,158,150,159,155,151,152,155,154,154,154,154,152,150,154,154,154,152,150,150,156,150,157,150,151,151,151,155,150,150,158,150,152,155,155,152,150,156,151,152,150,151,158,150,152,152,158,148,154,151,152,154,155,150,154,154,154,155,155,150,150,156,151,155,151,151,151,152,152,150,151,151,151,151,150,156,152,159,148,156,154,150,149,156,152,154,155,150,152,155,151,155,149,150,150,151,155,149,155,150,152,152,149,150,154,151,149,156,154,149,154,151,147,149,150,149,151,154,149,155,151,149,148,150,155,150,149,149,152,148,154,150,149,150,149,151,154,149,152,154,150,150,151,152,155,150,150,151,149,148,152,149};
int b[2048]={150,149,143,148,151,151,150,150,149,149,152,148,148,147,146,152,149,150,147,151,150,149,148,149,152,150,148,150,147,149,149,149,149,151,152,151,149,148,151,147,151,147,150,147,151,153,154,153,151,151,151,151,154,154,153,152,148,151,150,148,153,151,149,151,150,156,155,159,158,154,154,151,152,154,155,150,154,149,153,149,154,152,155,150,154,152,155,150,149,154,150,156,154,153,151,153,151,155,151,157,151,152,153,151,148,153,150,157,150,156,153,147,155,150,155,155,152,153,154,151,152,151,153,152,151,157,151,152,153,149,154,152,154,154,151,151,153,153,157,154,154,155,153,155,157,153,152,151,156,151,153,152,152,154,155,153,155,150,150,156,154,149,152,154,154,154,151,150,156,148,150,157,153,154,153,154,154,154,156,150,150,155,156,155,156,154,154,153,154,155,158,151,154,154,153,153,156,151,148,153,151,153,154,153,156,153,154,151,154,153,153,157,154,155,154,157,155,156,152,155,155,157,154,159,156,156,154,155,154,156,156,151,152,153,153,156,154,152,159,150,153,158,153,155,156,155,156,155,155,154,154,154,155,155,155,154,149,156,153,156,153,155,155,156,157,150,157,157,151,157,157,158,152,153,156,155,154,154,155,156,154,154,156,153,157,154,150,157,157,152,155,155,154,154,155,154,156,156,153,155,154,157,155,156,156,153,155,157,154,157,154,161,155,155,155,158,156,156,153,154,155,155,157,157,157,152,155,156,159,155,154,154,155,157,151,159,154,157,154,157,158,154,155,155,155,159,155,156,156,157,154,158,155,160,157,157,158,158,155,158,155,155,155,153,159,156,157,158,156,157,156,154,156,158,157,156,159,156,157,158,155,157,154,157,155,157,156,157,157,159,156,157,156,162,158,155,159,156,156,159,155,157,155,158,155,162,156,157,154,163,157,158,156,161,157,156,157,156,154,158,159,160,156,159,159,157,159,155,162,159,156,155,157,154,155,156,157,156,157,155,159,157,160,153,157,158,152,157,155,154,158,155,158,158,158,155,158,156,156,157,159,156,159,156,157,157,156,156,158,155,155,160,153,158,154,159,157,154,157,155,157,159,154,157,153,155,155,155,152,155,159,158,155,155,158,156,154,154,155,157,157,154,158,155,159,155,160,156,159,157,155,153,160,156,150,154,157,153,158,155,153,154,157,155,158,160,158,154,159,157,157,157,155,156,159,154,157,160,154,155,157,156,153,156,157,156,158,153,156,156,154,157,156,159,158,158,156,155,156,155,156,155,160,155,156,158,157,154,153,158,157,155,157,155,158,156,159,156,157,159,157,156,157,159,154,160,158,158,160,156,155,154,161,159,160,157,156,154,155,154,156,159,158,155,154,153,158,162,156,156,155,154,160,159,162,160,159,158,161,153,159,156,155,160,158,159,158,155,161,155,157,154,154,156,153,156,163,154,149,160,160,155,159,155,156,155,153,157,158,157,157,154,157,155,158,155,156,156,156,155,153,156,157,155,155,155,157,157,157,157,155,157,157,155,159,158,153,156,157,155,158,156,158,155,154,157,157,156,155,156,155,160,157,159,153,158,155,162,157,159,159,155,156,154,155,158,157,161,156,158,157,155,156,158,158,157,156,158,157,154,155,153,158,156,160,160,160,156,157,154,155,153,159,156,152,156,160,158,157,154,158,158,158,155,156,160,160,155,156,157,158,157,159,157,161,155,152,157,158,154,157,160,156,158,155,158,158,156,155,155,153,154,156,155,158,155,155,157,156,158,154,155,158,162,156,159,158,157,159,154,155,160,157,158,154,155,157,158,159,158,158,157,155,156,159,159,155,155,158,155,155,158,155,160,161,157,159,159,156,155,153,156,155,153,156,157,155,155,158,155,156,159,156,158,162,155,160,154,158,158,158,157,160,156,155,157,152,156,160,158,160,155,158,155,155,157,155,156,159,154,155,157,157,160,159,156,157,162,158,156,157,154,160,157,156,159,159,156,155,159,158,157,156,162,160,158,157,162,157,158,157,157,163,156,156,160,161,154,155,156,159,157,156,158,159,157,155,157,162,157,160,158,159,155,156,155,160,158,157,155,160,159,156,157,157,160,155,157,158,157,157,156,160,155,157,156,157,159,159,160,159,160,157,162,157,157,154,157,157,159,161,155,160,155,155,157,160,156,158,158,161,159,156,156,158,160,160,158,155,157,161,154,160,156,155,156,160,158,156,157,153,155,154,160,157,154,155,155,160,155,154,158,157,155,160,155,156,160,154,157,154,158,157,159,157,155,152,155,156,156,155,155,155,155,156,156,159,159,157,160,155,158,158,157,157,153,155,156,155,156,156,155,159,153,161,155,159,156,156,158,161,155,157,156,159,155,153,155,156,161,155,156,156,154,157,155,157,158,156,158,160,155,161,158,156,159,157,156,159,155,158,162,155,160,158,161,160,156,158,164,156,158,159,158,154,161,158,157,157,156,156,160,157,155,156,160,160,155,158,156,162,160,160,158,157,160,163,156,154,154,162,156,157,155,160,153,158,155,156,154,157,159,160,158,157,162,154,158,163,158,154,158,154,156,155,158,156,159,158,156,156,159,154,159,154,159,156,157,157,160,159,159,156,153,159,158,156,156,156,158,155,158,156,155,156,157,158,156,156,159,157,157,156,156,159,157,160,159,161,159,158,158,160,157,158,156,156,160,160,158,157,157,158,162,153,156,158,158,163,159,158,154,156,159,159,159,157,158,155,161,155,159,155,160,157,156,161,158,157,156,157,158,155,160,158,160,156,157,159,160,156,156,158,156,156,156,155,157,156,156,160,157,154,159,160,157,158,162,159,158,161,158,156,160,156,159,162,162,157,158,160,159,158,160,160,157,156,159,158,160,157,161,158,158,154,160,160,161,154,161,159,156,158,157,160,159,161,157,157,162,156,157,159,152,161,157,158,158,157,158,157,158,158,157,159,159,159,153,157,159,158,151,158,156,160,158,158,157,156,158,158,156,156,158,160,155,159,156,161,156,163,154,161,159,157,159,161,158,157,155,159,156,158,155,161,158,156,161,155,159,158,159,155,162,154,162,161,157,159,159,156,160,157,159,160,160,159,156,156,156,157,157,163,159,161,156,158,156,159,156,157,158,156,160,163,163,156,160,159,157,156,160,160,155,157,155,160,157,160,160,157,158,159,157,159,160,161,160,159,156,158,157,157,156,160,156,162,159,157,154,156,155,162,159,159,161,157,162,159,156,156,156,162,158,161,158,167,159,159,156,158,156,159,157,154,159,160,159,155,163,158,158,162,156,162,158,158,156,161,159,155,160,155,159,153,161,155,156,157,157,155,157,155,163,155,158,157,155,157,161,154,154,155,156,157,159,156,156,159,158,158,158,161,159,156,158,158,158,160,160,162,158,159,156,161,154,154,158,157,161,159,157,159,154,159,161,159,159,160,159,162,160,158,158,157,160,159,161,161,157,158,157,158,162,160,161,159,161,159,162,159,157,161,160,158,160,160,156,157,157,159,159,159,161,158,160,155,157,162,159,162,161,159,161,158,159,162,155,159,161,155,160,157,156,157,160,154,157,159,157,158,160,159,160,157,156,156,158,157,158,154,161,159,154,158,159,160,160,159,162,159,161,158,161,158,156,160,160,158,156,159,158,155,155,156,160,159,162,158,160,159,159,159,156,156,156,164,155,158,157,160,157,160,158,160,158,158,159,152,159,158,157,162,160,160,160,159,155,158,154,159,161,157,160,158,157,154,160,155,158,160,152,156,153,158,157,159,158,162,158,157,157,156,160,159,158,159,155,156,160,154,158,155,156,152,156,156,156,156,154,158,156,157,155,154,156,156,157,156,158,157,156,159,161,152,156,155,152,156,156,155,158,159,157,156,157,156,158,158,155,152,161,159,155,156,157,152,156,158,158,150,155,152,158,159,158,155,160,150,154,156,158,155,157,160,156,157,155,155,157,159,158,156,158,158,156,159,156,157,153,155,158,158,157,158,159,158,153,160,156,157,158,155,154,157,156,156,160,157,161,157,158,158,158,153,153,154,153,153,153,157,157,150,158,155,159,158,158,153,158,159,154,154,157,154,155,157,155,154,155,157,154,157,156,157,158,160,155,159,155,157,160,153,152,156,156,156,154,157,156,154,156,159,154,155,153,153,158,158,156,160,158,152,153,157,154,159,153,153,158,155,154,157,155,154,153,152,156,156,154,159,152,156,156,153,156,156,157,154,152,154,151,155,155,152,158,157,161,152,152,157,154,158,153,156,158,153,157,154,156,154,155,158,156,154,153,154,158,153,159,155,151,152,155,154,154,154,154,152,153,154,154,154,152,153,153,156,153,157,153,151,151,151,155,153,153,158,153,152,155,155,152,153,156,151,152,153,151,158,153,152,152,158,148,154,151,152,154,155,153,154,154,154,155,155,153,153,156,151,155,151,151,151,152,152,150,151,151,151,151,150,156,152,159,148,156,154,150,149,156,152,154,155,153,152,155,151,155,149,153,150,151,155,149,155,153,152,152,149,153,154,151,149,156,154,149,154,151,147,149,153,149,151,154,149,155,151,149,148,150,155,150,149,149,152,148,154,153,149,150,149,151,154,149,152,154,153,150,151,152,155,153,150,151,149,148,152,149 };
DataSource::DataSource(QObject *parent) :
QObject(parent),
m_index(-1)
{
generateData(0, 0, 0);
}
void DataSource::update(QAbstractSeries *series, int seriesIndex)
{
if (series) {
QXYSeries *xySeries = static_cast<QXYSeries *>(series);
const QVector<QVector<QPointF> > &seriesData = m_data.at(seriesIndex);
if (seriesIndex == 0)
m_index++;
if (m_index > seriesData.count() - 1)
m_index = 0;
QVector<QPointF> points = seriesData.at(m_index);
// Use replace instead of clear + append, it's optimized for performance
xySeries->replace(points);
}
}
void DataSource::handleSceneChanged()
{
m_dataUpdater.start();
}
void DataSource::updateAllSeries()
{
static int frameCount = 0;
static QString labelText = QStringLiteral("FPS: %1");
for (int i = 0; i < m_seriesList.size(); i++)
update(m_seriesList[i], i);
frameCount++;
int elapsed = m_fpsTimer.elapsed();
if (elapsed >= 1000) {
elapsed = m_fpsTimer.restart();
qreal fps = qreal(0.1 * int(10000.0 * (qreal(frameCount) / qreal(elapsed))));
m_fpsLabel->setText(labelText.arg(QString::number(fps, 'f', 1)));
m_fpsLabel->adjustSize();
frameCount = 0;
}
m_data.clear();
// Append the new data depending on the type
QVector<QVector<QPointF> > seriesData;
QVector<QPointF> points;
// points.reserve(2048);
for (int j(0); j < 2048; j++) {
qreal x(0);
qreal y(0);
if(shift==0)
{
y = b[j] ;
x=j;
}else
{
y = c[j] ;
x=j;
}
points.append(QPointF(x, y));
}
seriesData.append(points);
m_data.append(seriesData);
if(shift==0)
{
shift=1;
}else
{
shift=0;
}
}
void DataSource::startUpdates(const QList<QXYSeries *> &seriesList, QLabel *fpsLabel)
{
m_seriesList = seriesList;
m_fpsLabel = fpsLabel;
m_dataUpdater.setInterval(500);
m_dataUpdater.setSingleShot(true);
QObject::connect(&m_dataUpdater, &QTimer::timeout,this, &DataSource::updateAllSeries);
m_fpsTimer.start();
updateAllSeries();
}
void DataSource::generateData(int seriesCount, int rowCount, int colCount)
{
// Remove previous data
foreach (QVector<QVector<QPointF> > seriesData, m_data) {
foreach (QVector<QPointF> row, seriesData)
row.clear();
}
m_data.clear();
// Append the new data depending on the type
for (int k(0); k < seriesCount; k++) {
QVector<QVector<QPointF> > seriesData;
for (int i(0); i < rowCount; i++) {
QVector<QPointF> points;
points.reserve(colCount);
for (int j(0); j < colCount; j++) {
qreal x(0);
qreal y(0);
if(shift==0)
{
y = a[j] ;
x=j;
}else
{
y = b[j] ;
x=j;
}
points.append(QPointF(x, y));
}
seriesData.append(points);
}
m_data.append(seriesData);
}
if(shift==0)
{
shift=1;
}else
{
shift=0;
}
qDebug()<<"test";
}
//***********main.cpp**********//
#include "datasource.h"
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtCharts/QScatterSeries>
#include <QtCharts/QValueAxis>
#include <QtCharts/QLogValueAxis>
#include <QtWidgets/QLabel>
QT_CHARTS_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStringList colors;
colors << "red" << "blue" << "green" << "black";
QChart *chart = new QChart();
chart->legend()->hide();
QValueAxis *axisX = new QValueAxis;
QValueAxis *axisY = new QValueAxis;
chart->addAxis(axisX, Qt::AlignBottom);
chart->addAxis(axisY, Qt::AlignLeft);
const int seriesCount = 1;
const int pointCount = 2048;
chart->setTitle("OpenGL Accelerated Series");
QList<QXYSeries *> seriesList;
for (int i = 0; i < seriesCount; i++) {
QXYSeries *series = 0;
int colorIndex = i % colors.size();
if (i % 2) {
series = new QScatterSeries;
QScatterSeries *scatter = static_cast<QScatterSeries *>(series);
scatter->setColor(QColor(colors.at(colorIndex)));
scatter->setMarkerSize(qreal(colorIndex + 2) / 2.0);
// Scatter pen doesn't have affect in OpenGL drawing, but if you disable OpenGL drawing
// this makes the marker border visible and gives comparable marker size to OpenGL
// scatter points.
scatter->setPen(QPen("black"));
} else {
series = new QLineSeries;
series->setPen(QPen(QBrush(QColor(colors.at(colorIndex))),
qreal(colorIndex + 2) / 2.0));
}
seriesList.append(series);
//![1]
series->setUseOpenGL(true);
//![1]
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
}
if (axisX->type() == QAbstractAxis::AxisTypeLogValue)
axisX->setRange(0.1, 2048.0);
else
axisX->setRange(0, 2048.0);
if (axisY->type() == QAbstractAxis::AxisTypeLogValue)
axisY->setRange(0.1, 255.0);
else
axisY->setRange(0, 255.0);
QChartView *chartView = new QChartView(chart);
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(600, 400);
window.show();
DataSource dataSource;
dataSource.generateData(seriesCount, 1, pointCount);
QLabel *fpsLabel = new QLabel(&window);
QLabel *countLabel = new QLabel(&window);
QString countText = QStringLiteral("Total point count: %1");
countLabel->setText(countText.arg(pointCount * seriesCount));
countLabel->adjustSize();
fpsLabel->move(10, 2);
fpsLabel->adjustSize();
fpsLabel->raise();
fpsLabel->show();
countLabel->move(10, fpsLabel->height());
fpsLabel->raise();
countLabel->show();
// We can get more than one changed event per frame, so do async update.
// This also allows the application to be responsive.
QObject::connect(chart->scene(), &QGraphicsScene::changed,
&dataSource, &DataSource::handleSceneChanged);
dataSource.startUpdates(seriesList, fpsLabel);
return a.exec();
}

How can I place Hex Data into a QT List Widget [duplicate]

Recently I am writing a debugger for my own hardware. I want to add a memory viewer widget like the eclipse or qt creator or other IDE. However, I have no idea what kind of widget to use. For example, tableWidget, is there some setting to make it like this:
The best option is to create a custom widget because the task is private and none of the widgets are accommodated to the task.
For this we will inherit from QAbstractScrollArea, from this class inherit QTableView, QListView, QListWidget and QTableWidget. It is designed to display data within a QScrollArea.
In addition documentation of this class tells us how to create a custom class.
When inheriting QAbstractScrollArea, you need to do the following:
Control the scroll bars by setting their range, value, page step, and
tracking their movements.
Draw the contents of the area in the
viewport according to the values of the scroll bars.
Handle events
received by the viewport in viewportEvent()
notably resize events.
Use viewport->update() to update the contents of the viewport instead
of update() as all painting operations take place on the viewport.
Taking that reference I created the following widget:
memoryviewer.h
#ifndef MEMORYVIEWER_H
#define MEMORYVIEWER_H
#include <QAbstractScrollArea>
#include <QBuffer>
class MemoryViewer : public QAbstractScrollArea
{
Q_OBJECT
public:
MemoryViewer(QWidget *parent = 0);
~MemoryViewer();
void setData(const QByteArray &ba);
bool setData(QIODevice &device);
protected:
void paintEvent(QPaintEvent *);
void resizeEvent(QResizeEvent *);
private:
void adjustContent();
void init();
int addressWidth();
int hexWidth();
int asciiWidth();
QByteArray data(qint64 pos=0, qint64 count=-1);
int nBlockAddress;
int mBytesPerLine;
int pxWidth;
int pxHeight;
qint64 startPos;
qint64 endPos;
int nRowsVisible;
QBuffer buffer;
QIODevice *ioDevice;
qint64 size;
QByteArray dataVisible;
QByteArray dataHex;
};
#endif // MEMORYVIEWER_H
memoryviewer.cpp
#include "memoryviewer.h"
#include <QPainter>
#include <QScrollBar>
MemoryViewer::MemoryViewer(QWidget *parent):QAbstractScrollArea(parent)
{
ioDevice = new QBuffer(this);
init();
connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &MemoryViewer::adjustContent);
connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &MemoryViewer::adjustContent);
}
MemoryViewer::~MemoryViewer()
{
}
void MemoryViewer::init()
{
nBlockAddress = 2;
mBytesPerLine = 16;
pxWidth = fontMetrics().width(QChar('0'));
pxHeight = fontMetrics().height();
}
int MemoryViewer::addressWidth()
{
return (nBlockAddress*4+ nBlockAddress -1)*pxWidth;
}
int MemoryViewer::hexWidth()
{
return (mBytesPerLine*3+1)*pxWidth;
}
int MemoryViewer::asciiWidth()
{
return (mBytesPerLine*2 +1)*pxWidth;
}
QByteArray MemoryViewer::data(qint64 pos, qint64 count)
{
QByteArray buffer;
if (pos >= size)
return buffer;
if (count < 0)
count = size;
else
if ((pos + count) > size)
count = size - pos;
if(ioDevice->open(QIODevice::ReadOnly)){
ioDevice->seek(pos);
buffer = ioDevice->read(count);
ioDevice->close();
}
return buffer;
}
void MemoryViewer::setData(const QByteArray &ba)
{
buffer.setData(ba);
setData(buffer);
}
bool MemoryViewer::setData(QIODevice &device)
{
ioDevice = &device;
bool ok = ioDevice->open(QIODevice::ReadOnly);
if(ok){
size = ioDevice->size();
ioDevice->close();
}
else{
QBuffer *buf = new QBuffer(this);
ioDevice = buf;
}
init();
adjustContent();
return ok;
}
void MemoryViewer::resizeEvent(QResizeEvent *)
{
adjustContent();
}
void MemoryViewer::paintEvent(QPaintEvent *)
{
QPainter painter(viewport());
int offsetX = horizontalScrollBar()->value();
int y = pxHeight;
QString address;
painter.setPen(viewport()->palette().color(QPalette::WindowText));
for(int row = 0; row <= dataVisible.size()/mBytesPerLine; row++){
QString str = QString("%1").arg(startPos + mBytesPerLine*row, nBlockAddress*4, 16, QChar('0')).toUpper();
int i = 0;
address = "";
while(i < nBlockAddress){
address += str.mid(i*4, 4) + ":";
i++;
}
address.remove(address.size()-1, 1);
painter.drawText(pxWidth/2 -offsetX , y, address);
y+=pxHeight;
}
int x;
int lx = addressWidth() +pxWidth;
painter.drawLine(lx-offsetX, 0, lx-offsetX, height());
lx += pxWidth/2;
y = pxHeight;
//hex data
x = lx-offsetX+3*pxWidth;
int w = 3*pxWidth;
for(int col =0; col < mBytesPerLine/2; col++){
painter.fillRect(x-pxWidth/2, 0, w, height(), viewport()->palette().color(QPalette::AlternateBase));
x+= 6*pxWidth;
}
int bPos = 0;
for(int row=0; row < nRowsVisible; row++){
x = lx-offsetX;
for(int col =0; (col < mBytesPerLine) && (bPos < dataHex.size()) ; col++){
QString str = dataHex.mid(bPos*2,2).toUpper();
painter.drawText(x, y, str);
x += 3*pxWidth;
bPos += 1;
}
y+= pxHeight;
}
lx = addressWidth() + hexWidth();
painter.drawLine(lx-offsetX, 0, lx-offsetX, height());
lx += pxWidth/2;
bPos = 0;
y = pxHeight ;
int ch;
for(int row=0; row < nRowsVisible; row++){
x = lx-offsetX;
for(int col =0; (col < mBytesPerLine) && (bPos < dataVisible.size()) ; col++){
ch = (uchar)dataVisible.at(bPos);
if ( ch < 0x20 )
ch = '.';
painter.drawText(x, y, QChar(ch));
x += 2*pxWidth;
bPos += 1;
}
y+= pxHeight;
}
}
void MemoryViewer::adjustContent()
{
int w = addressWidth() + hexWidth() + asciiWidth();
horizontalScrollBar()->setRange(0, w - viewport()->width());
horizontalScrollBar()->setPageStep(viewport()->width());
nRowsVisible = viewport()->height()/pxHeight;
int val = verticalScrollBar()->value();
startPos = (qint64)val*mBytesPerLine;
endPos = startPos + nRowsVisible*mBytesPerLine -1;
int lineCount = size/mBytesPerLine;
verticalScrollBar()->setRange(0, lineCount-nRowsVisible);
verticalScrollBar()->setPageStep(nRowsVisible);
if(endPos >= size){
endPos = size-1;
}
dataVisible = data(startPos, endPos-startPos + mBytesPerLine +1);
dataHex = dataVisible.toHex();
viewport()->update();
}
An advantage of the implementation is that you do not have to load all the bytes directly since you can pass an object that inherits from QIODevice such as QFile and read the data when the view needs it by eliminating the memory overhead. In addition you can pass a QByteArray
In the following link you will find an example

Qt - adding elements to map and memory leaks

I am working on a matrix calculator and I encountered a really annoying problem, have been trying to fix it for 3 hours now, but it's getting worse instead of getting better. Maybe you will be able to help.
This is my MainWindow class:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPushButton>
#include <QGridLayout>
#include <QLabel>
#include "addmatrix.h"
#include "memory.h"
#include "matrixcreation.h"
#include <QMap>
#include "matrix.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(MainWindow *parent = 0);
~MainWindow();
private slots:
void on_createButton_clicked();
void setMatrix(Matrix *matrix);
private:
Matrix getMatrixFromMemory(QString &name);
void addMatrixToMemory();
Ui::MainWindow *ui;
AddMatrix *add;
MatrixCreation *matrixCreate;
QMap <QString, Matrix> matrixMap;
};
#endif // MAINWINDOW_H
.cpp file
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(MainWindow *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowTitle("Matrix Calculator");
add = NULL;
matrixCreate = NULL;
}
MainWindow::~MainWindow()
{
delete ui;
delete add;
delete matrixCreate;
matrixMap.clear();
}
void MainWindow::on_createButton_clicked()
{
if (add != NULL)
{
delete add;
add = new AddMatrix;
}
else
add = new AddMatrix;
if (matrixCreate != NULL)
{
ui->label->setText(getMatrixFromMemory(matrixCreate->getMatrix()->getName()).getName());
delete matrixCreate;
matrixCreate = new MatrixCreation;
}
else
matrixCreate = new MatrixCreation;
// Polaczenie sygnalow ze slotami
// Sluzy ustawieniu liczby wierszy w matrixCreate
connect(add->getCombo1(), SIGNAL(currentIndexChanged(QString)), matrixCreate, SLOT(setRows(QString)));
// Jak wyzej, tylko kolumn
connect(add->getCombo2(), SIGNAL(currentIndexChanged(QString)), matrixCreate, SLOT(setColumns(QString)));
// Ustawienie pola name w matrixCreate
connect(add->getEdit(), SIGNAL(textChanged(QString)), matrixCreate, SLOT(setName(QString)));
// Po ustawieniu liczby wierszy i kolumn oraz nazwy macierzy - wywola sie slot updateTable
// ktory sluzy do ustawienia rozmiaru okna i tabeli
connect(add, SIGNAL(setupSuccessful()), matrixCreate, SLOT(updateTable()));
// Po ustawieniu wierszy, kolumn, ustawieniu nazwy, rozmiarow, wywola sie slot show matrixCreate
connect(add, SIGNAL(setupSuccessful()), matrixCreate, SLOT(show()));
// Sluzy dodaniu macierzy do pamieci (mapy)
connect(matrixCreate, SIGNAL(matrixReady(Matrix*)), this, SLOT(setMatrix(Matrix*)));
add->show();
}
void MainWindow::setMatrix(Matrix *matrix)
{
matrixMap[matrix->getName()] = *matrix;
}
Matrix MainWindow::getMatrixFromMemory(QString &name)
{
return matrixMap[name];
}
As you can see I have a QMap in my MainWindow. I also have a an instance of MatrixCreation class called matrixCreate.
Here is MatrixCreation class:
#ifndef MATRIXCREATION_H
#define MATRIXCREATION_H
#include <QDialog>
#include <QTableView>
#include <QPushButton>
#include <QStandardItem>
#include <QTableWidget>
#include <QMainWindow>
#include "matrix.h"
#include "memory.h"
#include "addmatrix.h"
#include <windows.h>
namespace Ui {
class MatrixCreation;
}
class MatrixCreation : public QWidget
{
Q_OBJECT
public:
explicit MatrixCreation(QWidget *parent = 0);
~MatrixCreation();
QTableWidget *getTable();
Matrix *getMatrix();
private slots:
void on_okButton_clicked();
void updateTable();
void setRows(QString rows);
void setColumns(QString columns);
void setName(QString name);
signals:
void matrixReady(Matrix *matrix);
private:
Ui::MatrixCreation *ui;
int rows;
int columns;
int **matrix;
QString name;
Matrix *newMatrix;
};
#endif // MATRIXCREATION_H
.cpp file
#include "matrixcreation.h"
#include "ui_matrixcreation.h"
MatrixCreation::MatrixCreation(QWidget *parent) :
QWidget(parent),
ui(new Ui::MatrixCreation)
{
ui->setupUi(this);
this->resize(150, 50);
// Ustawienie rozmiaru wysokosci wiersza na 40 piksele
ui->tableWidget->verticalHeader()->setDefaultSectionSize(40);
// Ustawienie rozmiaru szerokosci kolumny na 94 piksele
ui->tableWidget->horizontalHeader()->setDefaultSectionSize(94);
// Dopasowanie rozmiaru kolumn do rozmiaru tabeli
ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
ui->tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
// Wylaczenie scrollbarow tabeli
ui->tableWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui->tableWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
rows = 1;
columns = 1;
matrix = NULL;
newMatrix = new Matrix;
}
MatrixCreation::~MatrixCreation()
{
delete ui;
if (matrix != NULL)
{
for (int i = 0; i < rows; i++)
delete matrix[i];
}
delete newMatrix;
}
void MatrixCreation::setRows(QString rows)
{
this->rows = rows.toInt();
}
void MatrixCreation::setColumns(QString columns)
{
this->columns = columns.toInt();
}
// Metoda odpowiedzialna za utworzenie odpowiedniej ilosci wierszy i kolumn
// oraz ustawienie odpowiedniej wielkosci okna i rozmiaru tabeli
void MatrixCreation::updateTable()
{
// stale roznice miedzy szerokoscia i wysokoscia okna i tabeli
int w = 323 - 305;
int h = 300 - 227 + 15;
for(int i = 0; i < rows; i++)
{
ui->tableWidget->insertRow(i);
h += 35;
}
for(int j = 0; j < columns; j++)
{
ui->tableWidget->insertColumn(j);
w += 50;
}
this->resize(w, h);
this->setMinimumSize(w, h);
ui->retranslateUi(this);
this->setWindowTitle("Matrix Creation");
}
QTableWidget *MatrixCreation::getTable()
{
return ui->tableWidget;
}
void MatrixCreation::on_okButton_clicked()
{
matrix = new int *[rows];
for(int j = 0; j < rows; j++)
{
matrix[j] = new int[columns];
}
for(int i = 0; i<rows; i++)
{
for(int j = 0; j<columns; j++)
{
matrix[i][j] = ui->tableWidget->item(i, j)->text().toInt();
}
}
// Ustawienie pol skladowych w zmiennej newMatrix klasy Matrix
newMatrix->setColumns(columns);
newMatrix->setRows(rows);
newMatrix->setName(name);
newMatrix->setMatrix(matrix);
emit matrixReady(newMatrix);
this->close();
}
void MatrixCreation::setName(QString name)
{
this->name = name;
}
Matrix *MatrixCreation::getMatrix()
{
return newMatrix;
}
What is the problem:
I want to add a created matrix to a QMap by emiting this signal:
emit matrixReady(newMatrix);
a Matrix class is used to hold all the elements of matrix (rows, cols, values of cells and name).
However, Matrix objects are not being added to QMap. But, when I delete this line in MatrixCreation destructor:
delete newMatrix;
It works.
Second problem:
When I am closing my application and MainWindow destructor gets called, while destroying a map it shows an error : BLOC_TYPE_IS_VALID bla bla...
I don't know how to fix it, however I will keep on trying. Any help will be appreciated.
void MainWindow::setMatrix(Matrix *matrix)
{
matrixMap[matrix->getName()] = *matrix;
}
You're adding copy of the matrix to your map. So here you have a leak.
void MainWindow::setMatrix(Matrix *matrix)
{
matrixMap[matrix->getName()] = *matrix;
delete matrix;
}
This should fix your problem.
Use valgrind to profile your application and find memory leaks: http://valgrind.org/docs/manual/quick-start.html

Errors connected with creating QMathGL class in application

I have a problem with MathGL library and creating MathGL instance in the application. Every time I try to run it there is an error saying that QApplication must be constructed before QWidget (from which the class QMathGL inherits). Below you can find my code of main and all the functions connected with the MainWindow class:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "functions.h"
#include "surface.h"
#include "error.h"
#include <QString>
#include <QFileDialog>
#include <GL/glut.h>
#include <cmath>
#include <fstream>
#include <mgl2/qmathgl.h>
surface graph;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_draw_clicked()
{
string s;
bool correct = 1;
error *errorWindow = new error(this);
s = ui->eqEdit->text().toStdString();
period fPeriod = period(ui->upEdit->text().toDouble(),ui->lowEdit->text().toDouble());
functionSum fSum = functionSum(s,fPeriod,ui->accEdit->text().toDouble());
for (int i = 0; i < fSum.accuracy; i++)
{
for (int j = 0; j < fSum.accuracy; j++)
{
if(isnan(fSum.zValues[i][j]) || isinf(fSum.zValues[i][j]))
{
correct = 0;
}
}
}
if(!correct)
{
errorWindow->show();
}
graph = surface(fSum);
}
void MainWindow::on_save_clicked()
{
QString plik;
string splik;
plik = QFileDialog::getSaveFileName(this,"Zapisz plik",QString(),"Pliki tekstowe (*.txt)");
splik = plik.toStdString();
ofstream saver;
saver.open(splik.c_str());
if (saver.is_open())
{
for(int i = 0; i < graph.points.size(); i++)
{
saver << graph.points[i].x << " " << graph.points[i].y << " " << graph.points[i].z << endl;
}
saver.close();
}
}
void MainWindow::on_load_clicked()
{
QString plik;
string splik;
plik = QFileDialog::getOpenFileName(this,"Otwórz plik",QString(),"Pliki tekstowe (*.txt)");
splik = plik.toStdString();
ifstream loader;
loader.open(splik.c_str());
graph.points.clear();
if(loader.is_open())
{
while(!loader.eof())
{
point a(0,0,0);
loader >> a.x >> a.y >> a.z;
graph.points.push_back(a);
}
loader.close();
}
}
void MainWindow::on_plot_clicked()
{
int a = sqrt(graph.points.size());
mglData x(a,a);
mglData y(a,a);
mglData z(a,a);
long long int k = 0;
for (long long int i = 0;i<sqrt(graph.points.size());i++)
{
for (long long int j = 0;j<sqrt(graph.points.size());j++)
{
x.a[i+a*j] = graph.points[k].x;
y.a[i+a*j] = graph.points[k].y;
z.a[i+a*j] = graph.points[k].z;
k++;
}
}
mglGraph plot;
plot.Rotate(50,60);
plot.Light(true);
plot.Surf(x,y,z);
QMathGL plotter;
plotter.setGraph(&plot);
plotter.show();
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

QT QStandardItemModel segfaulting

I'm pretty new to QT, and I'm trying to take a list from a text file and output it into QT with nice formatting.
I managed to get the list printed on the window, but it has to be able to be sorted.
I have the radio buttons set up right now so that one of them displays the list and the other clears the list.
The problem is that when I switch from the list to the cleared list back to the list the program segfaults and I don't understand why.
The files are here.
winelist.cpp
#include "winelist.h"
#include "ui_winelist.h"
#include <QFile>
#include <QString>
#include <QStandardItemModel>
wineList::wineList(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::wineList)
{
ui->setupUi(this);
ui->ratingButton->setChecked(true);
fillList();
model->setHorizontalHeaderItem(0, new QStandardItem(QString("Wine Name")));
model->setHorizontalHeaderItem(1, new QStandardItem(QString("Vintage")));
model->setHorizontalHeaderItem(2, new QStandardItem(QString("Rating")));
model->setHorizontalHeaderItem(3, new QStandardItem(QString("Price")));
ui->listOutput->setModel(model);
}
wineList::~wineList()
{
delete ui;
}
void wineList::on_sortButton_clicked()
{
if( ui->ratingButton->isChecked())
{
for (int i = 0; i < 100; i++) {
model->setItem(i,0,wList[i].wineName);
model->setItem(i,1,wList[i].vintage);
model->setItem(i,2,wList[i].rating);
model->setItem(i,3,wList[i].price);
}
}
else
{
for(int i = 0; i < 100; i++) {
for(int j = 0; j < 4; j++) {
model->setItem(i, j, new QStandardItem(QString("")));
}
}
}
ui->listOutput->resizeColumnsToContents();
ui->listOutput->resizeRowsToContents();
}
void wineList::fillList()
{
Wine wine;
QString line;
QStringList lineElements;
QFile wineText(":/winelist.txt");
if (wineText.open(QIODevice::ReadOnly))
{
while ((line = line.fromUtf8(wineText.readLine())) != "")
{
lineElements = line.split(";");
lineElements[0].replace("\t", "");
lineElements[1].replace("\t", "");
wine.wineName = new QStandardItem(QString(lineElements.at(0)));
wine.vintage = new QStandardItem(QString(lineElements.at(1)));
wine.rating = new QStandardItem(QString::number(lineElements.at(2).toInt()));
wine.price = new QStandardItem(QString::number(lineElements.at(3).toInt()));
wList.append(wine);
}
}
wineText.close();
}
winelist.h
#ifndef WINELIST_H
#define WINELIST_H
#include <QMainWindow>
#include <QStandardItem>
#include <QStandardItemModel>
namespace Ui {
class wineList;
}
struct Wine {
QStandardItem* wineName;
QStandardItem* vintage;
QStandardItem* rating;
QStandardItem* price;
};
class wineList : public QMainWindow
{
Q_OBJECT
public:
explicit wineList(QWidget *parent = 0);
~wineList();
private slots:
void on_sortButton_clicked();
private:
Ui::wineList *ui;
QVarLengthArray<Wine> wList;
QStandardItemModel *model = new QStandardItemModel(100, 4, this);
void fillList();
void printList(QStandardItemModel *model);
};
#endif // WINELIST_H
main.cpp
#include "winelist.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
wineList w;
w.show();
return a.exec();
}
Clicking sort the first time
Switching Radio Button and clicking sort again
Switching Radio Button back and clicking sort again
Any Help is appreciated, I am completely lost here.
In the on_sortButton_clicked you're trying to read data from a list, but not doing any range checks. Instead, you've hardcoded 100 there.
You should rewrite this:
for (int i = 0; i < 100; i++) {
model->setItem(i,0,wList[i].wineName);
to this:
for (int i = 0; i < wList.size(); i++) {
model->setItem(i,0,wList[i].wineName);
--upd---
When you initially populate your model, it takes ownership over items from wList. When you replace model items with empty ones, it deletes initial items from wList. After this your wList is no move valid, because it contains Wine structs with dangling pointers. That's why when you try to populate your model second time, it crashes.