I have a QTableView widget which is filled with the help of QStandardItemModel.
In every two seconds the function containing these two classes is called using QTimer and next 50 entries are given.
The function runs properly after every two seconds but the values arent refreshed in the window displayed.
Thanks in advance for any help.
Code :
void Box::create_frame()
{
k=0;
tablegroup = new QGroupBox(tr("Table"));
QVBoxLayout *layout = new QVBoxLayout;
table = new QTableView(this);
table->setUpdatesEnabled(false);
cout << "recent check" <<endl;
QStandardItemModel *mode = new QStandardItemModel(1,2,this);
mode->setHorizontalHeaderItem(0, new QStandardItem(QString("ID")));
mode->setHorizontalHeaderItem(1, new QStandardItem(QString("DATA")));
map<int,QString>::iterator it;
for(it=dataa.begin();it!=dataa.end();it++)
{
for(int i=0;i<=1;i++)
{
QStandardItem *item;
item = new QStandardItem();
item->setEditable(true);
if(i==0)
{
item->setData(((*it).first), Qt::DisplayRole);
mode->setItem(k,i,item);
}
else
{
item->setData(((*it).second), Qt::DisplayRole);
mode->setItem(k,i,item);
}
}
k++;
}
//setUpdatesEnabled(false);
table->setUpdatesEnabled(true);
cout << "create frame check" << endl;
table->setModel(mode);
layout->addWidget(table);
tablegroup->setLayout(layout);
}
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(refresh()));
timer->start(2000);
}
void dataThread::run()
{
boost::posix_time::seconds delay(2);
int g=0;
int h=50;
while(1)
{
while(g<h)
{
dataa.insert(pair<int,QString>(g+1,"HELLO"));
g++;
}
boost::this_thread::sleep(delay);
h=h+50;
}
}
First, it's late here so maybe I'm overlooking something but from your run loop, it doesn't look like you are actually adding any data to your table's model rather you're just adding entries to your dataa vector/list.
Maybe you should add this to your run loop
while( g < h )
{
dataa.insert(pair<int,QString>(g+1,"HELLO"));
QStandardItem *item;
item = new QStandardItem();
item->setEditable(true);
item->setData( g+1, Qt::DisplayRole );
// You need the model here
table->model()->setItem( h + g, 0, item );
item = new QStandardItem();
item->setData( "Hello", Qt::DisplayRole );
// You need the model again here
table->model->setItem( h + g, 1, item );
++g;
}
Again its late but I think you get the idea. You're currently not changing the model that your table is set to, rather just changing your dataa vector/list.
Related
I use "VXYModelMapper" and "QStandardItemModel" in plot chart. I use blow codes but append model to VXYModelMapper is very slow.
VXYModelMapper {
model: myChartClass.newMyChartModel
series: lineSeries
xColumn: 0
yColumn: 1
}
void MyChartClass::setMyChartModel(QStandardItemModel *model)
{
newMyChartModel= model;
emit myChartModelChanged(model);
}
QStandardItemModel* lineModel=new QStandardItemModel(npcArray.size(), 2);
foreach(const QJsonValue & val, npcArray){
double xVal=val.toObject().value("x").toDouble();
double yVal=val.toObject().value("y").toDouble();
QStandardItem *item1 = new QStandardItem(QString::number(xVal));
lineModel->setItem(i, 0, item1);
QStandardItem *item2 = new QStandardItem(QString::number(yVal));
lineModel->setItem(i, 1, item2);
i+=1;
}
//To this line everything is very good and fast
QElapsedTimer timer;
timer.start();
myChartClass->setMyChartModel(lineModel);
qDebug() << "The slow operation took" << timer.elapsed() << "millisecond";
Output: The slow operation took 123045 millisecond. Total point
count: 5188
It is very slow :(
Update:
I use QTimer but not benefit. :(
lineModel=new QStandardItemModel(0, 2);
myChartClass->setMyChartModel(lineModel);
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(30);
void MyChartClass::update(){
int toIndex=fromIndex+100;
if(toIndex>=npcArray.size()){
toIndex=npcArray.size()-1;
}
for(int i=fromIndex;i<toIndex;i++){
double xVal=npcArray[i].toObject().value("x").toDouble();
double yVal=npcArray[i].toObject().value("y").toDouble();
QStandardItem *item1 = new QStandardItem(QString::number(xVal));
lineModel->setItem(i, 0, item1);
QStandardItem *item2 = new QStandardItem(QString::number(yVal));
lineModel->setItem(i, 1, item2);
}
fromIndex=toIndex;
}
so i have been browsing the previous questions before about this issue, but i could not find a solution for my code.
cpp file of dialog
------------------------------------------------
#include "everesult.h"
#include "ui_everesult.h"
everesult::everesult(QWidget *parent) :
QDialog(parent),
ui1(new Ui::everesult)
{
ui1->setupUi(this);
}
everesult::~everesult()
{
delete ui1;
}
void everesult::setmodel(QStandardItemModel *model)
{
ui1->listView->setModel(model);
}
void everesult::on_buttonBox_clicked(QAbstractButton *button)
{
EveReprocess M_;
QModelIndex Selectedindex = ui1->listView->currentIndex();
QModelIndex StationIdsindex = ui1->listView->model()->index(0, 1);
int typeID = 0;
int stationID = 0;
stationID = ui1->listView->model()->data(StationIdsindex, Qt::DisplayRole).toInt();
typeID = ui1->listView->model()->data(Selectedindex, Qt::DisplayRole).toInt();
M_.GetMaterials(typeID, stationID);
}
--------------------------------------------------
Getmaterial and replyFinished from main window.
--------------------------------------------------
void EveReprocess::GetMaterials(int typeId, int stationid)
{
//get typeid from material list
this->modelMaterial = new QSqlQueryModel();
modelMaterial->setQuery(QString("SELECT tm.quantity, tm.materialTypeID, t.typeName FROM invTypeMaterials tm INNER JOIN invTypes t ON t.TypeID = tm.materialTypeId WHERE tm.TypeID=%1 ").arg(typeId));
if (!modelMaterial->query().exec())
qDebug() << modelMaterial->query().lastError();
//Set eve Central Url with typeids
QUrl url = QUrl("http://api.eve-central.com/api/marketstat?");
QUrlQuery q;
int numRows = modelMaterial->rowCount();
for (int row = 0; row < numRows; ++row)
{
QModelIndex index = modelMaterial->index(row, 1);
q.addQueryItem( QString("typeid"), QString::number(modelMaterial->data(index, Qt::DisplayRole).toInt()));
}
q.addQueryItem( QString("usesystem"), QString::number(stationid));
//set created url and connect
url.setQuery(q);
qDebug() << url;
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply *)));
manager->get(QNetworkRequest(url) );
}
void EveReprocess::replyFinished(QNetworkReply *reply)
{
qDebug() << "replyFinished called";
if ( reply->error() != QNetworkReply::NoError ) {
qDebug() << "Request failed, " << reply->errorString();
emit replyFinished(false);
return;
}
qDebug() << "Request succeeded";
//process with xmlreader and get values
processSearchResult( reply);
}
some of the code is here, i think it should be somewhere here, as the rest works fine.
this issue showed up after i use a dialog to let user pick a int from a list.
below is the function that calls the dialog that i have made for this. sorry about code format wil clean it up after it is working
void EveReprocess::Search_TypeId(QString ItemName, QString SystemName)
{
QList<int> TypeIdList;
QList<int> StationIdList;
modelIds = new QStandardItemModel(10,2,this);
if !(db.isOpen()) return;
this->queryItem = new QSqlQuery;
queryItem->prepare("SELECT typeID FROM invTypes WHERE invTypes.typeName LIKE ? AND invTypes.groupID NOT IN (268,269,270)AND published= 1");
ItemName.prepend("%");
ItemName.append("%");
queryItem->bindValue(0, ItemName);
this->queryStation = new QSqlQuery;
queryStation->prepare("SELECT solarSystemID FROM mapSolarSystems WHERE mapSolarSystems.solarSystemName LIKE ?");
SystemName.prepend("%");
SystemName.append("%");
queryStation->bindValue(0, SystemName);
if(!queryStation->exec() || !queryItem->exec() )
{
qDebug() << queryItem->lastError().text();
qDebug() << queryItem->lastQuery();
qDebug() << queryStation->lastError().text();
qDebug() << queryStation->lastQuery();
}
while( queryStation->next())
{
StationIdList.append(queryStation->value(0).toInt());
}
while(queryItem->next())
{
TypeIdList.append(queryItem->value(0).toInt());
}
for (int i = 0; i < StationIdList.count(); ++i)
{
modelIds->setItem(i,1,new QStandardItem(QString::number(StationIdList.at(i))));
}
for (int i = 0; i < TypeIdList.count(); ++i)
{
modelIds->setItem(i,0,new QStandardItem(QString::number(TypeIdList.at(i))));
}
//
everesult Dialog;
Dialog.setmodel(modelIds);
Dialog.exec();
}
Before you proceed any further, some of your code is allows SQL injections. Even when it's not a security hole, it'll still lead to bugs. Instead of using string substitution in SQL queries, you should be using bindings.
Your problem is here:
everesult Dialog;
Dialog.setmodel(modelIds);
Dialog.exec();
The exec() is a blocking function - it blocks the main event loop until the dialog is dismissed. Thus the signals from the threaded network access manager never get delivered to your objects.
You should display the dialog box asynchronously, like so:
everesult * dialog = new everesult;
dialog->setModel(modelIds);
dialog->show();
connect(dialog, SIGNAL(accepted()), dialog, SLOT(deleteLater());
connect(dialog, SIGNAL(rejected()), dialog, SLOT(deleteLater());
Note that it's misleading to have type names starting with lower case and variable names starting with upper case. Qt's convention is the opposite, and it's useful to retain it unless you have a good reason to do otherwise.
DO Parameter Binding in SQL Queries
QSqlQuery query("SELECT .. WHERE tm.TypeID=:typeid");
query.bindValue(":typeid", typeId);
QSqlQueryModel model;
model.setQuery(query);
DON'T DO String Substitution in SQL Queries
setQuery(QString("SELECT ... WHERE tm.TypeID=%1 ").arg(typeId));
I want to pass selected QRadioButton's value from one Window to another. I am confused with the function declaration to accept the text value in Second Window, here is my code.
Window1.cpp
void SelectOS :: processNextButton(){
if(ui->win32->isChecked()){
QString loc = "WIN/32Bit";
SelectSoftware *ss = new SelectSoftware (loc);
this->hide();
ss->show();
}
else
{
//QMessageBox:warning();
}
}
Window2.h
public:
SelectSoftware(const QString &text, QWidget *parent=0);
Window2.cpp
SelectSoftware::SelectSoftware(const QString &text, QWidget *parent):QMainWindow(parent),ui(new ui::SelectSoftware)
{
QString softpath = text;
qDebug << softpath;
}
But when I call
ss = new SelectSoftware();
or
ss= new SelectSoftware(const QString &text, QWidget *parent);
in Window2.cpp, I get the error : no matching function for call to SelectSoftware::SelectSoftware()
Where am I wrong?
UPDATE
Window2.cpp
#include "selectsoftware.h"
#include "ui_selectsoftware.h"
SelectSoftware *ss;
QStringList selectedModuleList;
SelectSoftware::SelectSoftware(const QString &text, QWidget *parent) :
QMainWindow(parent),
ui(new Ui::SelectSoftware)
{
ui->setupUi(this);
softpath = text;
setWindowPosition();
getSoftwareDetails();
initializeUi();
}
SelectSoftware::~SelectSoftware()
{
delete ui;
}
void SelectSoftware::setWindowPosition()
{
QDesktopWidget *desktop = QApplication::desktop();
int x = (desktop->width() - size().width())/2;
int y = (desktop->height() - size().height())/2;
move(x, y-50);
setFixedSize(size().width(), size().height());
}
void SelectSoftware::cancel()
{
qApp->exit(0);
}
void SelectSoftware::showMainPage()
{
ss = new SelectSoftware(softpath); // here its creating problem, not going forward and app is crashing!!!
for(int j = 0; j < softwareList.size(); j++){
if(checkBox[j]->isChecked()){
if(!comboBox[j]->currentIndex()){
QMessageBox::warning(this, "Select version !", "Select version number for all selected software");
return;
}
}
}
for(int i = 0; i < softwareList.size(); i++){
if(checkBox[i]->isChecked()){
ss->selectedSoftList.push_back(checkBox[i]->text());
ss->selectedVerList.push_back(comboBox[i]->currentText());
}
}
if(!ss->selectedSoftList.size()){
QMessageBox::warning(this, "No product Selected !", "Select one");
return;
}
else{
SelectionPage* sp = new SelectionPage;
this->hide();
sp->show();
}
}
void SelectSoftware::test(const int id)
{
if(checkBox[id]->isChecked()){
comboBox[id]->setEnabled(true);
comboBox[id]->addItem(" Select anyone ");
QString path = qApp->applicationDirPath() + "/products/" + checkBox[id]->text();
QDir dir;
dir.cd(path);
dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot);
QFileInfoList list = dir.entryInfoList();
for (int i = 0; i < list.size(); ++i) {
QFileInfo fileInfo = list.at(i);
comboBox[id]->addItem(fileInfo.fileName());
}
}else{
comboBox[id]->clear();
comboBox[id]->setDisabled(true);
}
}
void SelectSoftware::getSoftwareDetails()
{
QString fileName = qApp->applicationDirPath() + "/abc/" + SOFTWARELIST;
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)){
QString msg = "Could not find the file " + fileName;
errorExit(msg);
}
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
processLine(line.toLower());
}
}
void SelectSoftware::processLine(QString str)
{
QStringList list = str.split(",");
QDir path = qApp->applicationDirPath() + "/products/" + list[0];
if(path.exists() && (list.size() == 2)){
QString tmp = list[0];
tmp = tmp.toLower();
softwareList.push_back(tmp);
}
}
void SelectOption::initializeUi()
{
this->setWindowTitle("Window2");
QGridLayout *gridLayout1 = new QGridLayout();
gridLayout1->setMargin(5);
gridLayout1->setSpacing(5);
QSignalMapper* signalMapper = new QSignalMapper();
for(int i = 0; i < list.size(); i++){
radioButton[i] = new QRadioButton();
radioButton[i]->setText(softwareList[i]);
signalMapper->setMapping(radioButton[i], i);
gridLayout1->addWidget(radioButton[i], i/1, i%1);
connect(radioButton[i], SIGNAL(clicked()),signalMapper, SLOT(map()));
}
connect(signalMapper, SIGNAL(mapped(const int &)),this, SIGNAL(radioChecked(const int &)));
connect(this, SIGNAL(radioChecked(const int &)),this, SLOT(test(const int)));
QGridLayout *gridLayout2 = new QGridLayout();
gridLayout2->setMargin(5);
gridLayout2->setSpacing(5);
for(int j = 0; j < list.size(); j++){
comboBox[j] = new QComboBox();
comboBox[j]->setDisabled(true);
gridLayout2->addWidget(comboBox[j], j/1, j%1);
}
QPushButton *nextButton = new QPushButton("Next >");
nextButton->setDefault(true);
connect(nextButton, SIGNAL(clicked()), this, SLOT(showMainPage()));
QPushButton *backButton = new QPushButton("< Back");
backButton->setDefault(true);
connect(backButton, SIGNAL(clicked()), this, SLOT(showSelectOS()));
QPushButton *cancelButton = new QPushButton("Cancel");
cancelButton->setDefault(true);
connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancel()));
QHBoxLayout *hboxlayout;
hboxlayout = new QHBoxLayout();
hboxlayout->addLayout(gridLayout1);
hboxlayout->addLayout(gridLayout2);
QHBoxLayout *layout;
layout = new QHBoxLayout();
layout->addStretch(10);
layout->addWidget(nextButton);
layout->addWidget(backButton);
layout->addWidget(cancelButton);
layout->addStretch(10);
QVBoxLayout *mainLayout;
mainLayout = new QVBoxLayout();
mainLayout->addLayout(hboxlayout);
mainLayout->addLayout(layout);
ui->centralwidget->setLayout(mainLayout);
}
QVector<QString> SelectSoftware::getSelectedSoftware()
{
return ss->selectedSoftList;
}
QVector<QString> SelectSoftware::getSelectedVersion()
{
return ss->selectedVerList;
}
QStringList SelectSoftware::getSelectedModules()
{
return selectedModuleList;
}
First of all - use signals and slots, Luke
Second of all, you cannot call ss = new SelectSoftware();, since you haven't declared SelectSoftware constructor without parameters, and calling ss= new SelectSoftware(const QString &text, QWidget *parent); is illegal in C++.
SelectSoftware *ss = new SelectSoftware (loc); is correct, though.
1. In void SelectSoftware::processLine(QString str) addressing to list[0] without checking that list is not empty might be dangerous. I recomend you to add:
if (!list.size())
return;
right after initialization.
2. In void SelectOption::initializeUi() what is list? Are you sure list.size() <= softwareList.size()? If not, it's a potential problem.
3. What is radioButton? I don't see it's initialization. If it is QList < QRadioButton * >, than radioButton[i] = new QRadioButton(); is a bad one and you should do this:
radioButton.append(new QRadioButton());
4. Same goes to comboBox.
Each of the list can cause the crash of your application. And I could easily miss something.
I'm new to Qt and need some help with the following:
I would like to create a GUI containing a Table Widget that is populated by information coming from a tab delimited text file. In my GUI, the user would first browse for the text file and then it would then show the contents in the Table Widget. I've done the browse part, but how do I load the data from the text file into the Table Widget?
It's two steps, parse the file, and then push it into the widget.
I grabbed these lines from the QFile documentation.
QFile file("in.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
while (!file.atEnd()) {
QByteArray line = file.readLine();
process_line(line);
}
Your process_line function should look like this:
static int row = 0;
QStringList ss = line.split('\t');
if(ui->tableWidget->rowCount() < row + 1)
ui->tableWidget->setRowCount(row + 1);
if(ui->tableWidget->columnCount() < ss.size())
ui->tableWidget->setColumnCount( ss.size() );
for( int column = 0; column < ss.size(); column++)
{
QTableWidgetItem *newItem = new QTableWidgetItem( ss.at(column) );
ui->tableWidget->setItem(row, column, newItem);
}
row++;
For more information about manipulating QTableWidgets, check the documentation. For new users using the GUI builder in Qt Creator, it is tricky figuring it out at first.
Eventually I would recommend to switching to building the GUI the way they do in all their examples... by adding everything by hand in the code instead of dragging and dropping.
Sorry...
void squidlogreader_::process_line(QString line)
{
static int row = 0;
QStringList ss = line.split('\t');
if(ui->tableWidget->rowCount() < row + 1)
ui->tableWidget->setRowCount(row + 1);
if(ui->tableWidget->columnCount() < ss.size())
ui->tableWidget->setColumnCount( ss.size() );
for( int column = 0; column < ss.size(); column++)
{
QTableWidgetItem *newItem = new QTableWidgetItem( ss.at(column) );
ui->tableWidget->setItem(row, column, newItem);
}
row++;
}
void squidlogreader_::on_pushButton_clicked()
{
QFile file("in.txt");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
return;
while (!file.atEnd()) {
QString line = file.readLine();
process_line(line);
}
I need to implement a table in Qt that shows a QComboBox on each row on a particular column.
Based on this question: QStandardItem + QComboBox I succesfully managed to create a QItemDelegate. In that example the QComboBox contents are defined statically on ComboBoxDelegate class, but in my case I need to define the QComboBox contents within the function where the QStandardItemModel is created.
The model is defined inside a MainWindow class method:
void MainWindow::fooHandler() {
QStandardItemModel* mymodel = new QStandardItemModel;
ui->tablePoint->setModel(mymodel);
ComboBoxDelegate* delegate=new ComboBoxDelegate;
ui->tablePoint->setItemDelegateForColumn(2,delegate);
QStringList Pets;
Pets.append("cat");
Pets.append("dog");
Pets.append("parrot");
// So far this is how I tried to store data under `Qt::UserRole` in "mymodel":
QModelIndex idx = mymodel->index(0, 2, QModelIndex());
mymodel->setData(idx,QVariant::fromValue(Pets), Qt::UserRole);
//Now i fill the table with some values...
QList< QStandardItem * > items;
items.clear();
items << new QStandardItem("col0");
items << new QStandardItem("col1");
items << new QStandardItem("parrot");
items << new QStandardItem("col3");
mymodel->appendRow(items);
items.clear();
items << new QStandardItem("col0");
items << new QStandardItem("col1");
items << new QStandardItem("cat");
items << new QStandardItem("col3");
mymodel->appendRow(items);
}
Then I should be able to recover the ComboBox contents from the delegate class:
void ComboBoxDelegate::setEditorData(QWidget *editor,
const QModelIndex &index) const
{
QString value = index.model()->data(index, Qt::EditRole).toString();
QComboBox *cBox = static_cast<QComboBox*>(editor);
if(index.column()==2) {
QModelIndex idx = index.model()->index(0, 2, QModelIndex());
cBox->addItem( index.model()->data(idx,Qt::UserRole).toStringList().at(0) );
cBox->addItem( index.model()->data(idx,Qt::UserRole).toStringList().at(1) );
cBox->addItem( index.model()->data(idx,Qt::UserRole).toStringList().at(2) );
}
cBox->setCurrentIndex(cBox->findText(value));
}
The project compiles well but when I click on a cell to change the QComboBox value the program crashes and I got an "Invalid parameter passed to C run time function."
My problem was that I was trying to use mymodel->setdata() before I append rows to the model.
So If at first I should do:
QList< QStandardItem * > items;
items.clear();
items << new QStandardItem("col0");
items << new QStandardItem("col1");
items << new QStandardItem("parrot");
items << new QStandardItem("col3");
mymodel->appendRow(items);
and ONLY then...
QModelIndex idx = mymodel->index(0, 2, QModelIndex());
mymodel->setData(idx,QVariant::fromValue(Pets), Qt::UserRole);
This solved the issue.
Thank you all.