1

我想从 XML 文件中读取对象,我需要处理 2 个异常:无法打开文件和无法加载文件内容。(格式不正确)我编写了以下函数来从文件中读取内容和 2 个例外情况。问题是,当我运行我的应用程序并且我试图加载与 XML 格式不同的文件时,而不是通知存在异常的友好消息,我有一个调试错误:调用了 abort()。我做得不好是什么?阅读功能

QList<Vehicle> VehicleHelper::readVehicles(QString fileName){
QList<Vehicle> vehicles;
Vehicle newVehicle;
QFile file(fileName);
QDomDocument document;
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
    throw FileCannotBeOpenException();
}
else{
    if(!document.setContent(&file)){
        throw InvalidXMLContentException();
    }
    file.close();
}

QDomElement root = document.firstChildElement();
QDomNodeList carElements = root.elementsByTagName("Car");
for(int i = 0; i < carElements.size(); i++){

    QDomNode carNode = carElements.at(i);

    QDomElement carElement = carNode.toElement();
    QString carID = carElement.attribute("ID");

    //if the idNumber is null, generate one
    if(carID.isEmpty()){
        QUuid newId = Vehicle::generateID();
        newVehicle.setVehicleId(newId);
    }
    else {
        QUuid id;
        try{
            id = QUuid::QUuid(carID);
        } catch(QException &ex){
            continue;
        }


        newVehicle.setVehicleId(id);
    }
  }

函数的调用

void MainWindow::on_actionOpen_triggered()
{
if(isModified){
    QMessageBox msgBox;
    QString message = "There are unsaved changes! Do you proceed? ";
    msgBox.setWindowTitle("Save Changes");
    msgBox.setText(message);
    msgBox.addButton("Don't save",QMessageBox::NoRole);
    msgBox.addButton(QMessageBox::Save);
    msgBox.addButton(QMessageBox::Cancel);
    msgBox.setIcon(QMessageBox::Question);
    int result = msgBox.exec();
    if(result == QMessageBox::Save){
        VehicleHelper::writeVehicles(cars,filename);
        msgBox.close();
    } else {
        QString fileName = QFileDialog::getOpenFileName(this,"Open file");
        if(!fileName.isEmpty()){
            setFileName(fileName);
            QFile file(fileName);
            try {
                cars = VehicleHelper::readVehicles(fileName);
            } catch(FileCannotBeOpenException &ex) {
                QMessageBox msgBox;
                msgBox.setIcon(QMessageBox::Critical);
                msgBox.setWindowTitle("Message!");
                msgBox.setText("Failed to open file");
                msgBox.setDefaultButton(QMessageBox::Ok);
                msgBox.exec();
                return;

            } catch(InvalidXMLContentException &ex){
                QMessageBox msgBox;
                msgBox.setIcon(QMessageBox::Critical);
                msgBox.setWindowTitle("Message!");
                msgBox.setText("Failed to load data!");
                msgBox.setDefaultButton(QMessageBox::Ok);
                msgBox.exec();
                return;
            }

            setTakenNumbersList(cars);
            //set data to the table view
            populate(cars);
       }
    }
 } else {
    QString fileName = QFileDialog::getOpenFileName(this,"Open file");
    if(!fileName.isEmpty()){
        setFileName(fileName);
        QFile file(fileName);
        if(file.open(QFile::ReadOnly | QFile::Text)){
            cars = VehicleHelper::readVehicles(fileName);
            setTakenNumbersList(cars);
            file.close();

            //set data to the table view
            populate(cars);

            ui->actionAdd->setEnabled(true);
            ui->actionBy_name->setEnabled(true);
            ui->actionBy_registration_date->setEnabled(true);
            ui->actionBy_registration_number->setEnabled(true);
            ui->actionBy_revision_date->setEnabled(true);
            ui->actionBy_type->setEnabled(true);
            ui->actionClear_Search->setEnabled(true);
            ui->actionDelete->setEnabled(true);
            ui->actionEdit->setEnabled(true);
            ui->actionSave->setEnabled(true);
            ui->actionSave_As->setEnabled(true);
        }
     }

    }
 }

主要的

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
try{
    w.show();
} catch(QException &ex){

}
return a.exec();
}
4

1 回答 1

2

异常是从在事件循环中运行的代码抛出的,特别是它们将到达QCoreApplication::notify(). 这个是a.exec()通过介入的操作系统事件循环调用间接调用的。

因此,您不能仅仅包含a.exec()在 try/catch 中。您必须重新实现QCoreApplication::notify()如下:

class MyApplication : public QApplication
{
public:
   MyApplication(int & c, char ** a) : QApplication(c,a) {}
   virtual bool notify(QObject * obj, QEvent * ev) {
      bool rc = true;
      try {
         rc = QApplication::notify(obj, ev);
      }
      catch (QException &ex) {
         ...
      }
      return rc;
   }
};

int main(...) {
   MyApplication app(...);
   ...
}

您的代码的另一个问题是它尖叫使用State Machine Framework。您应该具有表示文件打开和关闭的状态,以及显示“未保存的更改”对话框时的中间状态。这样你就不会ui->actionXYZ->setEnabled(true)乱扔代码了。假设你有一个fileOpen状态,你会有

fileOpen->assignProperty(ui->actionBy_name, "setEnabled", true);
...

然后,当文件打开时,您会发出一个附加到状态机中的信号转换的信号。状态机将完成剩下的工作——它将为您启用/禁用操作等。

于 2013-10-03T00:38:07.897 回答