使用connect

时间:2017-08-02 21:18:30

标签: c++ qt

我偶然发现了一个让我有点困惑的问题。

在这个小部件的构造函数中,我调用了一个填充表的函数fillQualityReport()

RepackProcess::RepackProcess(DataBase *d, QPrinter *p, QWidget *parent) : QMdiSubWindow(parent), ui(new Ui::RepackProcess)
{
  ui->setupUi(this);
  data=d;
  printer=p;
  loadDropDownMenus();
  fillQualityReport();
  connect(ui->quality,SIGNAL(cellChanged(int,int)),this,SLOT(updateTotalLosses()));
}

以下是填写质量报告的功能:

void RepackProcess::fillQualityReport()
{
  int commodity;
  QSqlQuery query, defects;
  query.prepare("select * from commodity where (name=:name)"); // Looking for the commodity id
  query.bindValue(":name",ui->Commodity->currentText());
  query.exec();
  query.next();
  commodity=query.value(0).toInt();
  query.prepare("select * from quality where (id_commodity=:commodity)");
  query.bindValue(":commodity",commodity);
  query.exec();
  query.next();
  query.last();
  totalQualityDefects = query.at()<0 ? 0 : query.at()+1;
  ui->quality->setColumnCount(2);       // Setting the column and row counts for the table
  ui->quality->setRowCount(totalQualityDefects);
  ui->quality->setHorizontalHeaderLabels(QString("Defect;Percent").split(";"));
  ui->quality->setColumnWidth(0,60);
  ui->quality->setColumnWidth(1,60);
  query.first();      // Movind the pointer of the query back to before the first record
  query.previous();
  int currentRow=0;
  while (query.next()) {    // Filling the table with the defect names
      defects.prepare("select name from defects where (id=:id)");
      defects.bindValue(":id",query.value(2).toInt());
      defects.exec();
      defects.next();
      ui->quality->setItem(currentRow,0,new QTableWidgetItem(defects.value(0).toString()));
      ui->quality->setItem(currentRow,1,new QTableWidgetItem(QString::number(0.00,'f',2)));
      ui->quality->item(currentRow,1)->setTextAlignment(Qt::AlignRight|Qt::AlignVCenter);
      currentRow++;
    }
}

这里是质量报告发生变化时更新表格的那个:

void RepackProcess::updateTotalLosses()
{
  totalLoss=0;
  QSqlQuery query;
  query.prepare("select * from commodity where name=:name");
  query.bindValue(":name",commodityLabel);
  query.exec();
  query.next();
  int commodityId=query.value(0).toInt();
  for(int x=0; x<totalQualityDefects;x++)
    {
      qDebug()<<x;
      QString defect=ui->quality->item(x,0)->text();
      qDebug()<<defect;
      query.prepare("select * from defects where name=:name");
      query.bindValue(":name",defect);
      query.exec();
      query.next();
      int defectId = query.value(0).toInt();
      query.prepare("select * from quality where (id_commodity=:commodity and id_defects=:defects)");
      query.bindValue(":commodity",commodityId);
      query.bindValue(":defects",defectId);
      query.exec();
      query.next();
      qDebug()<<query.lastError();
      if(ui->quality->item(x,1)->text().toFloat()<query.value(3).toFloat())
        {
          totalLoss += ui->quality->item(x,1)->text().toFloat() * query.value(4).toFloat();
        }
      else if(ui->quality->item(x,1)->text().toFloat()<query.value(5).toFloat())
        {
          totalLoss += ui->quality->item(x,1)->text().toFloat() * query.value(6).toFloat();
        }
      else
        {
          totalLoss += ui->quality->item(x,1)->text().toFloat() * query.value(8).toFloat();
        }
    }
  ui->totalLoss->setText(QString::number(totalLoss,'f',2));
}

我的问题如下,使用构造函数上的connect函数,填写表时出错。在我看来,程序在表完全填充之前调用更新函数,程序在表的第二行崩溃。当表格被填满时,连接会通知数据发生变化并触发更新,该更新知道表格中的行数

如果我取出连接并更换一个按钮进行更新工作没有问题。我正在查看表格视图中的所有信号,但找不到仅在屏幕上访问数据时触发的信号。

很抱歉这篇长篇文章,但你总是要求代码。

#ifndef REPACKPROCESS_H
#define REPACKPROCESS_H

#include <QWidget>
#include <QMdiSubWindow>
#include <QPrinter>

#include "database.h"

namespace Ui {
  class RepackProcess;
}

class RepackProcess : public QMdiSubWindow
{
  Q_OBJECT

public:
  explicit RepackProcess(DataBase *d, QPrinter *p, QWidget *parent = 0);
  ~RepackProcess();

  void fillQualityReport(void);  // This function will resize and change the quality table for imput
  void loadDropDownMenus(void); // This function reads the tables and adds the selection to the drop down.

  void updateRepackCost(void);  // This function updates the costs table when parameters are changed
  void updateSheetCalculation(void); // This function updates all the calculations of the sheet


private slots:
  void on_Commodity_activated(const QString &arg1);
  void on_Warehouse_activated(const QString &arg1);
  void on_Format_activated(const QString &arg1);
  void on_totalCases_valueChanged(int arg1);
  void updateTotalLosses(int col, int row);  // This function updates the estimated total loses

  void on_updateLoss_clicked();

private:
  Ui::RepackProcess *ui;
  DataBase *data;
  QPrinter *printer;

  QSqlRelationalTableModel *costsModel;

  QString countryLabel, commodityLabel, modeLabel, warehouseLabel, formatLabel;

  int totalCases;  // This is the total number of cases that started the process
  float totalLoss; // Thi is the percentage of total loses in the process.
  int totalQualityDefects; // This is the number of defect that are showing on the quality report.

};

#endif // REPACKPROCESS_H

1 个答案:

答案 0 :(得分:0)

这句话你可能是对的:

  

在我看来,该程序之前正在调用更新函数   表完全

由于您更改了一个单元格:
connect(ui->quality,SIGNAL(cellChanged(int,int)),this,SLOT(updateTotalLosses()));
使用,因此调用updateTotalLosses()

要解决此问题,请使用以下方法阻止自身发出信号:

ui->quality->blockSignals(true);
ui->quality->blockSignals(false);

所以你需要做这样的事情:

fillQualityReport()
{
    ui->quality->blockSignals(true);
    ... // your code
    ui->quality->blockSignals(false);
}

updateTotalLosses()
{
    ui->quality->blockSignals(true);
    ... // your code
    ui->quality->blockSignals(false);
}