А проблема следующая: У меня есть два идентичных куска кода на C# (Qyoto) и на C++ (Qt 4.7), создающие QMainWindow с QTreeView, лежащем на нем. Этому TreeView скармливается QStandardItemModel содержащая в себе некоторые QStandardItem'ы. В случае Qt все работает хорошо, а вот в Qyoto item'ы на мгновение появляются, а потом почему-то исчезают.
В результате выяснилось, что item'ы на которые нет ссылок из managed кода просто собираются GC, не смотря на то, что они были добавлены в модель и по идее ссылки на них должны храниться в этой самой QStandardItemModel!!! Такова уж специфика работы Smoke, будем иметь это ввиду.
Выяснить это удалось при помощи слабых ссылок. Ниже приведен код на примере которого можно убедиться в верности предположения:
using System;
using Qyoto;
using System.Collections.Generic;
namespace QyotoDrv
{
public class MainWindow : QMainWindow
{
Ui.MainWindow _ui;
QStandardItem it1; //menu item referred from MainWindow
WeakReference _wr1; //weak reference to it1
WeakReference _wr2; //weak reference to it2
const string SlotShowWR = "slot_ShowWR()";
public MainWindow ()
{
_ui = new Ui.MainWindow();
_ui.SetupUi(this);
SetModel();
}
void SetModel()
{
var model = new QStandardItemModel(_ui.treeView);
it1 = new QStandardItem("Hello, World!");
model.AppendRow(it1);
//the following menu item is not referred from MainWindow and will be collected by GC,
//in spite of being added to the model!!!
QStandardItem it2 = new QStandardItem("Good bye, World!");
model.AppendRow(it2);
_ui.treeView.SetModel(model);
//set weak references pointing to the corresponding menu items
_wr1 = new WeakReference(it1);
_wr2 = new WeakReference(it2);
QMenu file = MenuBar().AddMenu("Click me!");
QAction showWR = new QAction("Show Weak References", this);
file.AddAction(showWR);
Connect(showWR, SIGNAL("triggered()"), this, SLOT(SlotShowWR));
}
[Q_SLOT(SlotShowWR)]
void ShowWeakReference()
{
//after the main window will be shown wait a fiew seconds until the second item has disappeared
Console.WriteLine("wr1.IsAlive={0}", _wr1.IsAlive); //is alive
Console.WriteLine("wr2.IsAlive={0}", _wr2.IsAlive); //is not alive!
}
}
}
* This source code was highlighted with Source Code Highlighter.
Запустите приложение. После появления главного окна дождитесь пока второй item не исчезнет, после чего щелкните на пункт меню "Click me! > Show Weak References" и посмотрите на консоль.
Комменты на английском сделаны для возможных англоязычных посетителей, чтоб хоть чем-то помочь им, слишком уж мало материала в сети на тему Qyoto.