PDA

View Full Version : Qwt Problem



allensr
21st November 2006, 20:16
I'm having a problem with my app crashing. I have a QTableWidget that has 2 columns that I am populating with a drag and drop event. If I plot everything in the table I have no problem. If I select a few rows and only try to plot them, I crash. Here is my slot that is connected to a "Plot" button. Can anyone tell what I am doing wrong?



void cPlot2d::setup2dPlot()
{
QAbstractItemModel * model = this->mTableWidget->model();
QItemSelectionModel * selectionModel = this->mTableWidget->selectionModel();
QModelIndex index = model->index(0,0);

int totalRowCount = model->rowCount();
bool select(false);

//If user selects any items this model contains it
QItemSelection selection = selectionModel->selection();
QModelIndexList list = selection.indexes();

//Number of items selected
int selectCount = list.count();
int numRowsSelected(0);
for(int i=0;i<selectCount;++i)
{
if(list[i].column()==0)
++numRowsSelected;
}

QwtArray<double> x;
QwtArray<double> y;
QwtArray<double> xSelect;
QwtArray<double> ySelect;

if(totalRowCount > 0)
{
//Has any items been selected
if(selectCount>0)
{
select = true;
for(int i=0; i<selectCount; ++i)
{
//For MVC, get the data out of the model
//Data is stored contiguously in list, so got to figure out what column data is in
//x=0 y=1
if(list.at(i).column() == 0)
{
xSelect.push_back(list.at(i).data().toDouble());
}
else
{
ySelect.push_back(list.at(i).data().toDouble());
}
}
}
//No items selected, load up entire table
else
{

for(int i=0; i<totalRowCount; ++i)
{
//For MVC, get the data out of the model
x.push_back(model->data(index.sibling(i,0)).toDouble());
y.push_back(model->data(index.sibling(i,1)).toDouble());
}
}
// Set up Qwt Plot stuff
QwtPlot * plot(new QwtPlot(this));
plot->setTitle("2D Plot");
// axis titles
plot->setAxisTitle(QwtPlot::xBottom, "x");
plot->setAxisTitle(QwtPlot::yLeft, "y");

// curve
QwtPlotCurve * curve(new QwtPlotCurve("Curve 1"));
curve->attach(plot);
// data
if(select)
{
//User selected data to plot
curve->setData(xSelect, ySelect);
}
else
{
//Plot entire table
curve->setData(x, y);
}
// pen
curve->setPen(QPen(QColor(0, 0, 200)));
// style
curve->setStyle(QwtPlotCurve::Lines);

plot->replot();

cMainWindow::getInstance()->mWorkspace->addWindow(plot)->show();

}
else
{
cout << " NO DATA TO PLOT!! " << endl;
return;
}

} // cPlot2d::setup2dPlot

jpn
23rd November 2006, 10:33
Run the code through a debugger to see where exactly does it crash. QTableWidget has, by the way, convenience methods for manipulating selected items...

allensr
1st December 2006, 16:52
JPN:

I did a few things. One, I used your suggestion in using the convenience methods from TableWidget (changes in code below). When I run it from the command prompt I get:
ASSERT failure in QReadWriteLock::unlock(): "Cannot unlock an unlocked lock", file c:\qt\4.1.4\src\corelib\thread\qreadwritelock.cpp, line 215
QMutex::lock(): Deadlock detected in thread 2552

When I run it through the debugger, it dies when it leaves this method. It looks like its having problem in a destructor -- deleting QModelIndex.



void cPlot2d::setup2dPlot()
{
QAbstractItemModel * model = this->mTableWidget->model();
QItemSelectionModel * selectionModel = this->mTableWidget->selectionModel();
QModelIndex index = model->index(0,0);

int totalRowCount = model->rowCount();
bool select(false);

//If user selects any items this model contains it
QItemSelection selection = selectionModel->selection();
QModelIndexList list = selection.indexes();
QList<QTableWidgetItem *> selected = this->mTableWidget->selectedItems();
QTableWidgetItem *item;

//Number of items selected
int selectCount = list.count();
int numRowsSelected(0);
for(int i=0;i<selectCount;++i)
{
if(list[i].column()==0)
++numRowsSelected;
}

QwtArray<double> x;
QwtArray<double> y;
QwtArray<double> xSelect;
QwtArray<double> ySelect;

if(totalRowCount > 0)
{
//Have any items been selected
if(selectCount>0)
{
select = true;
int i(0);
foreach(item, selected)
{
bool ok;
double value = item->text().toDouble(&ok);
//For MVC, get the data out of the model
//Data is stored contiguously in list, so got to figure out what column data is in
//x=0 y=1
if(list.at(i).column() == 0)
{
if(ok && !item->text().isEmpty())
xSelect.push_back(value);
}
else
{
if(ok && !item->text().isEmpty())
ySelect.push_back(value);
}
++i;
}
// }
}
//No items selected, load up entire table
else
{

for(int i=0; i<totalRowCount; ++i)
{
//For MVC, get the data out of the model
x.push_back(model->data(index.sibling(i,0)).toDouble());
y.push_back(model->data(index.sibling(i,1)).toDouble());
}
}
// Set up Qwt Plot stuff
QwtPlot * plot(new QwtPlot(this));
plot->setTitle("2D Plot");
// axis titles
plot->setAxisTitle(QwtPlot::xBottom, "x");
plot->setAxisTitle(QwtPlot::yLeft, "y");

// curve
QwtPlotCurve * curve(new QwtPlotCurve("Curve 1"));
curve->attach(plot);
// data
if(select)
{
//User selected data to plot
curve->setData(xSelect, ySelect);
}
else
{
//Plot entire table
curve->setData(x, y);
}
// pen
curve->setPen(QPen(QColor(0, 0, 200)));
// style
curve->setStyle(QwtPlotCurve::Lines);

plot->replot();

cMainWindow::getInstance()->mWorkspace->addWindow(plot)->show();

}
else
{
cout << " NO DATA TO PLOT!! " << endl;
return;
}

} // cPlot2d::setup2dPlot

jpn
1st December 2006, 17:01
Sounds like you are manipulating the widget outside the main GUI thread, is this true?

Thread Support in Qt: (http://doc.trolltech.com/4.2/threads.html#qobject-reentrancy)


Although QObject is reentrant, the GUI classes, notably QWidget and all its subclasses, are not reentrant. They can only be used from the main thread.

allensr
1st December 2006, 19:47
Well, Im not sure. I am populating the TableWidget with data from a TreeWidget via a drag and drop. Is that manipulating the widget outside the main GUI thread? Again, I only have problems if I select items in the TableWidget.:confused:

allensr
1st December 2006, 21:04
Not sure why, but removing any reference to QModelIndexList fixed my problems. Now works like a charm. :D

jpn
1st December 2006, 21:13
Ok good, then the problem is not with threads. I was suspecting you tried to do the plotting in a "worker" thread..

To be honest, I can't find any pitfall in your code, but does it make any difference if you revise the function to look something like this:


void cPlot2d::setup2dPlot()
{
int totalRowCount = this->mTableWidget->rowCount();
QList<QTableWidgetItem *> selected = this->mTableWidget->selectedItems();
QTableWidgetItem *item;

QwtArray<double> x;
QwtArray<double> y;

if(totalRowCount > 0)
{
//Have any items been selected
if(selected.count() > 0)
{
foreach(item, selected)
{
bool ok = false;
double value = item->text().toDouble(&ok);
//For MVC, get the data out of the model
//Data is stored contiguously in list, so got to figure out what column data is in
//x=0 y=1
if(item->column() == 0)
{
if(ok && !item->text().isEmpty())
x.push_back(value);
}
else
{
if(ok && !item->text().isEmpty())
y.push_back(value);
}
}
}
//No items selected, load up entire table
else
{
for(int i=0; i<totalRowCount; ++i)
{
//For MVC, get the data out of the model
QTableWidgetItem* item0 = mTableWidget->item(i,0);
QTableWidgetItem* item1 = mTableWidget->item(i,1);
x.push_back(item0->text().toDouble());
y.push_back(item1->text().toDouble());
}
}
// Set up Qwt Plot stuff
QwtPlot * plot(new QwtPlot(this));
plot->setTitle("2D Plot");
// axis titles
plot->setAxisTitle(QwtPlot::xBottom, "x");
plot->setAxisTitle(QwtPlot::yLeft, "y");

// curve
QwtPlotCurve * curve(new QwtPlotCurve("Curve 1"));
curve->attach(plot);
// data
curve->setData(x, y);
// pen
curve->setPen(QPen(QColor(0, 0, 200)));
// style
curve->setStyle(QwtPlotCurve::Lines);

plot->replot();

cMainWindow::getInstance()->mWorkspace->addWindow(plot)->show();

}
else
{
cout << " NO DATA TO PLOT!! " << endl;
return;
}
} // cPlot2d::setup2dPlot


All I did was cleaning up the unnecessary usage of model indexes which you actually shouldn't need while working with convenience views. If it still crashes, could you please post the backtrace from the debugger? And could you tell the exact version of Qt you are using as well?

jpn
1st December 2006, 21:17
Not sure why, but removing any reference to QModelIndexList fixed my problems. Now works like a charm. :D
Ok, great that the problem was solved. ;) Are you by the way using a recent version of Qt? It may even be a known/fixed bug. You can examine Qt related bugs in the Task tracker (http://www.trolltech.com/developer/task-tracker).