我有一个应用程序为某个流打开一个QDialog,当它关闭时,QMainWindow被打开。
在QDialog中,我创建了一些我想作为指针(或其他方式)传递给QMainWindow的对象。例如,我创建了一个需要从QMainWindow更改其状态的SysTray对象。什么是最好的方法?单身?
更新。
实施闷热后,另一个问题是上升,QDialog是否从内存中清除,意味着,调用了它的析构函数?我认为不是这样的。我必须做一些对象清理,并且从不调用析构函数
答案 0 :(得分:3)
一种方法是在堆上分配QMainWindow
作为父级。 QObject-hierarchy将负责释放内存,您将在QMainWindow
的生命周期内访问该对象。
如果您在任何时候确定不再需要QDialog
或共享对象,则可以致电deleteLater。
示例:
class MyDialog : public QDialog
{
Q_OBJECT
QObject* _objToShare;
public:
QObject* objToShare() const { return _objToShare; }
MyDialog(QObject* parent = 0) : QDialog(parent)
{
_objToShare = new QObject(this); // either use this as the parent
// or free by hand in the destructor
}
// ...
};
class MyWindow : public QMainWindow
{
Q_OBJECT
// ...
QObject* ptrToSharedObj; // alternatively you can hold a pointer
// to your MyDialog instance
};
您使用QDialog的地方:
MyDialog* d = new MyDialog(this);
d->exec();
ptrToSharedObj = d->objToShare();
// don't delete d explicitly, the QObject hierarchy will take care of that
更好(并且可能更加内存友好)的方法是使用共享指针实现。 Qt有各种smart pointer classes,其中一个是QSharedPointer
。它基本上是一个线程安全的引用计数指针,这意味着如果你抓住一个指向QDialog
的共享对象的指针,只要有任何其他QSharedPointer
它就不会被释放s指向它。请记住,如果您不小心,这可能会导致循环引用。
示例:
class MyDialog : public QDialog
{
Q_OBJECT
QSharedPointer<QObject> _objToShare;
// ^ don't delete in the destructor
public:
QSharedPointer<QObject> objToShare() const { return _objToShare; }
MyDialog(QObject* parent = 0) : QDialog(parent)
{
_objToShare = QSharedPointer<QObject>(new QObject);
// no parent to avoid destruction when the dialog is destructed
}
// ...
};
class MyWindow : public QMainWindow
{
Q_OBJECT
// ...
QSharedPointer<QObject> ptrToSharedObj;
};
您使用QDialog的地方:
MyDialog d;
d.exec();
ptrToSharedObj = d.objToShare();
从这一点开始,即使d超出范围(即销毁),你仍然会有一个指向共享数据的有效指针(当然,除非你明确地做了一些事情来使它无效)。
答案 1 :(得分:2)
你有很多不同的选择。其中一些可能不适用于您的情况:
定义一个可以控制排序的控制器。然后,该控件可以充当中介并在对话框关闭后获取数据:
void FlowController::displayFlow()
{
MyDialog *dialog = new MyDialog();
YourSharedData *data = NULL;
int result = dialog->exec();
if (result == QDialog::Accepted) {
data = dialog->sharedDataAccessor();
}
MyMainWindow *window = new MyMainWindow();
window->setSharedData(data);
window->exec();
}
预先创建对话框和主窗口。连接相应的信号和插槽,让它们彼此无知。这通常更容易测试并保持解耦:
void AppLauncher::launch()
{
MyDialog *dialog = new MyDialog();
MyMainWindow *window = new MyMainWindow();
window->connect(
dialog,
SIGNAL(dialogResult(int, const SharedData&)),
SLOT(setDialogResult(int,const SharedData&))
);
}
void MyMainWindow::setDialogResult(int result, const SharedData& sharedData)
{
if (result == Dialog::Accepted) // something domain-specific would be better
{
this->processSharedData(sharedData); // do whatever with it.
}
}
预先定义您的共享数据,并使其成为每个表单的依赖项。然后,每个表单定义状态,基于该状态的行为,或两者的某种组合:
void AppLauncher::launch()
{
SharedData *data = this->createSharedData();
MyDialog *dialog = new MyDialog(data);
MyMainWindow *window = new MyMainWindow();
dialog->exec(); // does what it needs with shared data
window->exec(); // checks shared data and acts accordingly
}
您可以将共享状态定义为他们都采取行动的模型。这可能与上面的案例三没有太大的不同。
它会起作用,但please don't do it:)。
答案 2 :(得分:0)
在QDialog中你拥有所有者,可能是QMainWindow。 (如果没有,你可以在那里添加它,在获得QMainWindow类之前获取父对象)。您可以在创建新对象时引用它...
答案 3 :(得分:0)
您可以将QApplication子类化,使其保留指向systray对象的指针,或者应该在“应用程序范围内”可用的其他对象。
在Qt应用程序中,只有一个QApplication实例,可以在任何地方使用qApp宏。
请参阅this mailing list discussion which also contains an example。