我想从XML文件中读取对象,我需要处理2个异常:当无法打开文件时以及无法加载文件内容时。 (格式不正确)我编写了以下函数来读取文件中的内容和2个异常的clases。问题是,当我运行我的应用程序并且我尝试加载具有不同格式的文件然后XML,而不是通知存在异常的frindly消息时,我有一个调试错误:调用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();
}
答案 0 :(得分: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);
...
然后,当文件打开时,您会发出一个信号,该信号附加到状态机中的信号转换。状态机将完成剩下的工作 - 它将为您启用/禁用操作等。