今天做一个QDialog,ui界面,是一个多界面项目中的某个子界面,需要通过主界面的click事件来初始化子界面,并且传如一个参数。传参数有很多办法,我想简单点直接通过重载构建函数来完成。但是如果真的写的太简单的话,恐怕不行,本文将此这个学习的过程写出来,欢迎大家探讨。
先看基本的代码: mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QString GetFileName(); //if file not exists ,return false;
private slots:
void on_btnTraceHead_clicked();
};
mainwindow.cpp 节选
//show traceinfo window
void MainWindow::ShowTraceinfo()
{
traceinfo *ti = new traceinfo(NULL,GetFileName());
ti->SetTotalTrNum(10);//just a demo ,will update later; gxx 20131220
ti->exec();
delete ti;
}
void MainWindow::on_btnTraceHead_clicked()
{
ShowTraceinfo();
}
子界面的头文件以及cpp
class traceinfo : public QDialog
{
Q_OBJECT
public:
explicit traceinfo(QWidget *parent = 0);
traceinfo(QWidget *parent,QString FileName);
~traceinfo();
void LoadFile();
void SetFileName(QString Name);
private:
Ui::traceinfo *ui;
};
#include "QMessageBox"
#include "traceinfo.h"
#include "ui_traceinfo.h"
#include "QFile"
#include "fstream"
using namespace std;
traceinfo::traceinfo(QWidget *parent) :
QDialog(parent),
ui(new Ui::traceinfo)
{
ui->setupUi(this);
}
traceinfo::traceinfo(QWidget *parent,QString FileName):
ui(new Ui::traceinfo)
{
traceinfo();
SetFileName(FileName);
}
traceinfo::~traceinfo()
{
delete ui;
}
//setup filename , used by mainwindow.cpp
void traceinfo::SetFileName(QString name)
{
if (name.trimmed().isEmpty())
throw "FileName error,view trace info failure!";
g_sFileName = name;
}
以上的代码大家都看到了,咳,运行起来,完全不是想象中的状况。具体的说,就是ui的控件完全没有体现在traceinfo的界面上。
(要说没有显示么,其实也不是完全没有。总之,再打一笔钱吧!)
要解决这个问题,似乎很简单,把setupui的代码挪到mainwindows.cpp来就可以。
//show traceinfo window
void MainWindow::ShowTraceinfo()
{
traceinfo *ti = new traceinfo(NULL,GetFileName());
Ui::traceinfo *ui;
ui->setupUi(ti);
//setup ui codes move to here
QStringList lsHeads;
lsHeads << "Short" << "Int" << "Float";
ui->tblTraceInfo->setColumnCount(3);
ui->tblTraceInfo->setHorizontalHeaderLabels(lsHeads);
ui->tblTraceInfo->columnAt(0);
ui->tblTraceInfo->setColumnWidth(0,ui->tblTraceInfo->width()/3-15);
ui->tblTraceInfo->setColumnWidth(1,ui->tblTraceInfo->width()/3-15);
ui->tblTraceInfo->setColumnWidth(2,ui->tblTraceInfo->width()/3-19);
ui->tblTraceInfo->setRowCount(120);
ti->SetTotalTrNum(10);//just a demo ,will update later; gxx 20131220
ti->exec();
delete ti;
}
但是,如果这么简单一搞,这篇文章完全没有写的必要了啊,小伙伴们都知道啊!
所以还是看看原先的代码错在哪里吧:
仔细看一下原先的实现。两个traceinfo构造函数(恩,是的,重载),其中一个调用了另一个,但是setupui没有正确执行。这是因为在某个构造函数里简单粗暴地调用另一个构造函数,结果被调用的构造函数并不会在原先这个构造函数的内存块里构建对象,而是会构建到一个另外的临时内存块内。如果想要让代码实现原先一样的结果,需要对new函数有更深入的了解。
new函数原本为具备分配空间并且构建对象的,但是在c++的stl里,new还可以在指定的内存地址内构建对象。
其STL中的原型如下:
new (place_address) type
或者 new (place_address) type (initializer-list) 其中place_address必须是一个指针,而intializer-list提供了(可能为空的)初始化立标,以便在构造新分配的对象时使用。
恩,stl里的东西非常值得大家好好花时间去学习,因为无脑调用stl经常导致莫名的崩溃!(走题了)
所以我把原先的代码调整了一下
traceinfo::traceinfo(QWidget *parent) :
QDialog(parent),
ui(new Ui::traceinfo)
{
ui->setupUi(this);
g_iCurrentTrNum = 0; //count trace num from 0!
QStringList lsHeads;
lsHeads << "Short" << "Int" << "Float";
ui->tblTraceInfo->setColumnCount(3);
ui->tblTraceInfo->setHorizontalHeaderLabels(lsHeads);
ui->tblTraceInfo->columnAt(0);
ui->tblTraceInfo->setColumnWidth(0,ui->tblTraceInfo->width()/3-15);
ui->tblTraceInfo->setColumnWidth(1,ui->tblTraceInfo->width()/3-15);
ui->tblTraceInfo->setColumnWidth(2,ui->tblTraceInfo->width()/3-19);
ui->tblTraceInfo->setRowCount(120);
}
traceinfo::traceinfo(QWidget *parent,QString FileName):
ui(new Ui::traceinfo)
{
new(this) traceinfo();
SetFileName(FileName);
LoadFile();
}
好了,现在这个程序可以正常运行了,当然很多人会说这段代码为啥这么别扭,是不是可以把共用部分单独拿出来,而不是让构造函数互相调用,这个么,臣妾做不到啊!
开个玩笑,:-)
文章基本写到这里,但是还是留下一个问题,调用构造函数是我们看到的代码是
traceinfo::traceinfo(QWidget *parent,QString FileName):
ui(new Ui::traceinfo)
{
traceinfo();
SetFileName(FileName);
}
能否改成如下代码?原因何在呢?
traceinfo::traceinfo(QWidget *parent,QString FileName):
ui(new Ui::traceinfo)
{
traceinfo(parent);
SetFileName(FileName);
}