PDA

View Full Version : Error when trying to update TableView



Ferric
12th January 2010, 04:50
Hi,

I am new to Qt programming and Im having problems trying to insert new data into a QTableView, via a QStandardItemModel,

Specifically, I am having trouble trying to update the table from within a function "void Loader::addChannelToTable() "



#include <QtGui>
#include "loader.h"
#include <QString>
#include <QTextStream>
#include "qextserialport.h"
#include "addDialog.h"
#include <QtGui/QApplication>
#include <QCoreApplication>
#include <QString>
#include <QTextStream>
#include <QThread>
#include <QTime>
#include <QtGlobal>
#include <qdatetime.h>
#include <QByteArray>
#include <QBitArray> // probably shouldnt use as RS232 works with bytes.
#include <QStandardItem>
#include <QStandardItemModel>
#include <QVariant>
#include <QModelIndex>


Loader::Loader(QWidget *parent)
: QWidget(parent)
{


QTableView *channelsView = new QTableView();
QStandardItemModel *model = new QStandardItemModel(4,2);

// for (int row = 0; row < 4; ++row) {
// for (int column = 0; column < 2; ++column) {
// QStandardItem *item = new QStandardItem(QString("%0, %1").arg(row).arg(column));
// //QStandardItem *item = new QStandardItem(QString("row %0, column %1").arg(row).arg(column));
// model->setItem(row, column, item); //This item is put in the model by using the setItem(int, int, QStandardItem*) method.
// }
// } //When I uncomment this section the Table is updated

channelsView->setModel(model);


QLabel *titleLabel = new QLabel(tr("COMMUNICATIONS"));
QLabel *descriptionLabel = new QLabel(tr("Determines Distribution"));
QLabel *netNameLabel = new QLabel(tr("Net Name:"));
QLabel *currentChannelsLabel = new QLabel(tr("Descriptionfor Net:"));
QLabel *cloningLabel = new QLabel(tr("Enable Cloning"));
netNameLine = new QLineEdit;
currentChannelsText = new QTextEdit;
QPushButton *saveButton = new QPushButton(tr("Save Configuration Data As..."));
QPushButton *uploadButton = new QPushButton(tr("Upload Configuration "));
QPushButton *quitButton = new QPushButton(tr("Quit"));
QPushButton *addChannelButton = new QPushButton(tr("Add Channel")); // the 'tr' is for translate...
QPushButton *removeChannelButton = new QPushButton(tr("Remove Channel"));
QCheckBox *cloningEnabled = new QCheckBox();
QHBoxLayout *secondLayout = new QHBoxLayout();
secondLayout->addWidget(saveButton);
secondLayout->addWidget(uploadButton);
secondLayout->addWidget(quitButton);

QHBoxLayout *thirdLayout = new QHBoxLayout();
thirdLayout->addWidget(cloningLabel);
thirdLayout->addWidget(cloningEnabled);

QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(titleLabel, 0, 1); //The title widget (WInDows GadgET) is situated at row 0, column 1, in the grid layout.
mainLayout->addWidget(descriptionLabel, 1, 1, Qt::AlignTop);
mainLayout->addWidget(netNameLabel, 4, 0);
mainLayout->addWidget(netNameLine, 4, 1);
mainLayout->addLayout(thirdLayout,5,1);
mainLayout->addWidget(addChannelButton, 6, 1);
mainLayout->addWidget(removeChannelButton, 7, 1);
mainLayout->addWidget(channelsView, 8, 1);
mainLayout->addWidget(currentChannelsLabel, 8, 0, Qt::AlignTop);
mainLayout->addLayout(secondLayout,9,1);
setLayout(mainLayout);
setWindowTitle(tr("Unit Loader"));

QObject::connect(quitButton, SIGNAL(clicked()),
this, SLOT(close()));

QObject::connect(uploadButton, SIGNAL(clicked()),
this, SLOT(calculateRandomCode()));

QObject::connect(uploadButton, SIGNAL(clicked()),
this, SLOT(send()));

QObject::connect(addChannelButton, SIGNAL(clicked()), // So I click the addChannel button and the addChannel Dialog opens
this, SLOT(addChannelDialog())); // So I click the addChannel button and the addChannel Dialog opens
}


void Loader::addChannelDialog() // the addChannelDialog SLOT or Function..
{
AddDialog *dialog = new AddDialog(this); // Creates a new object; *dialog of class AddDialog
dialog->show(); //Shows the dialog..

QObject::connect(dialog, SIGNAL(addThisChannel()),
this, SLOT(addChannelToTable()));
}

void Loader::addChannelToTable() // I want this SLOT to be activated when the addButton (from the AddDialog::dialog object) is clicked.

{
QMessageBox::information(
this,
tr("Yes,"),
tr("It works.") );

for (int row = 0; row < 4; ++row) {
for (int column = 0; column < 2; ++column) {
QStandardItem *item = new QStandardItem(QString("%0, %1").arg(row).arg(column));
model->setItem(row, column, item); //This item is put in the model by using the setItem(int, int, QStandardItem*) method.
}
} // I think my problem is in the line above or below.

channelsView->setModel(model);
}



void Loader::send()


{
}



void Loader::calculateRandomCode()
{

}





My code compiles and runs, but as soon as I get to the part where I can run "void Loader::addChannelToTable() " the information box "yes it works" is displayed, then windows shows and error screen and I am forced to close my program.


When I update the table from within the



Loader::Loader(QWidget *parent)
: QWidget(parent)
{
//
}


section it works fine.



Thanks for reading, any help would be greatly appreciated

kichi
12th January 2010, 06:21
In addChannelToTable(), you are using variables model and channelsView.
but in Loader(), you are defined model and channelsView as local pointer.

I'm sorry in poor English.

Ferric
12th January 2010, 09:15
Ah, I think I understand what you mean, I need to define model and channelsView as a global pointer maybe? or something else?

kichi
12th January 2010, 13:19
Ah, I think I understand what you mean, I need to define model and channelsView as a global pointer maybe? or something else?

Yes. I think you should declare model and channelsView as class member.


// Loader.h
class Loader {
Q_OBJECT
public:
Loader::Loader(QWidget *parent = 0);

// ...

private:
QTableView *channelsView; // pointer data member
QStandardItemModel *model;
};



// Loader.cpp
Loader::Loader(QWidget *parent)
: QWidget(parent), channelsView(0), model(0) // initialization.
{


channelsView = new QTableView(); // constraction
model = new QStandardItemModel(4,2);

// ....

};

void Loader::addChannelToTable() // I want this SLOT to be activated when the addButton (from the AddDialog::dialog object) is clicked.
{
QMessageBox::information(
this,
tr("Yes,"),
tr("It works.") );

if (!channelsView || !model) { // check whether pointers are not 0.
return;
}

for (int row = 0; row < 4; ++row) {
for (int column = 0; column < 2; ++column) {
QStandardItem *item = new QStandardItem(QString("%0, %1").arg(row).arg(column));
model->setItem(row, column, item); //This item is put in the model by using the setItem(int, int, QStandardItem*) method.
}
} // I think my problem is in the line above or below.

//channelsView->setModel(model); // This is not necessary, because setModel() has been called in Loader().
// channelsView has already referred to the model.
}

Ferric
12th January 2010, 20:49
Thanks a lot, it works now, if you have time could you please tell me the reasoning behind the following lines of code:

[code]
if (!channelsView || !model) { // check whether pointers are not 0.
return;
}

Thanks

kichi
13th January 2010, 05:23
Thanks a lot, it works now, if you have time could you please tell me the reasoning behind the following lines of code:

[code]
if (!channelsView || !model) { // check whether pointers are not 0.
return;
}



I apologize you annoying.
In this case, the code is not necessary.

This check is necessary, in the following case.

Always initialize the pointer with 0, before using the pointer.
Always assign 0 to the pointer which is referring to nothing.
Make the pointer refer to object with "new", when it becomes necessary.
Delete the pointer to object, when it becomes unnecessary, and assign 0 to the pointer.
"new" may throw std::bad_alloc when the memory becomes insufficient. so always use "try" keyword, and "catch" the exception. In particular, never throw any exceptions out of constractor.
Always check the pointer whether it is not 0, before which is used.


If you don't need std::bad_exception, you can write the following code.


QTableView *channelsView = new(nothrow) QTableView();

"new(nothrow)" does not throw std::bad_exec, and if there is not enough memory, it returns 0.
but I have rarely seen this using up to now, on the Web.

I'm sorry in poor English.

Ferric
13th January 2010, 09:41
Ah I think I understand what you are saying, Thanks once again : ]