4

我有一个在 QTreeView 中使用拖放的 Windows/Linux Qt 4.3 应用程序。我有两个非常相似的应用程序,它们使用相同的 Qt 库集。拖放在 Linux 上都适用,但在 Windows 上只适用于其中之一。

在不工作的应用程序中,一旦鼠标移动,QDrag 对象就会被删除。它被事件队列中的 DeferredDelete 事件删除,该事件队列在拖动期间仍在 Qt 中处理。我不知道如何查看导致 QDrag 对象过早删除的原因。

我想不出调试这个问题的好方法。我已经比较了来源,找不到任何明显的东西。我曾尝试在另一个应用程序中使用其中一个应用程序的代码。

有什么建议么?

更新:

QDrag 操作失败的原因是 COM 没有成功初始化,所以 QDrag::exec 中对 DoDragDrop 的调用立即返回。QApplication 尝试通过在 qt_init 中调用 OleInitialize 来初始化 COM,但失败并出现错误“设置后无法更改线程模式”。

有趣的是,即使 OleInitialize 是在 main 中完成的第一件事,也会发生这种情况,因此线程模式最初是由某些外部依赖项设置的。在 Windows 上运行的应用程序之间的区别之一是失败的应用程序还包含 .NET 代码,所以这可能就是问题所在。

解决了:

此问题是 COM/CLR 互操作问题。CLR 在初始化时将单元状态设置为 MTA,然后当 Qt 尝试初始化 COM 时失败。Adam NathanGotcha 中使用 STAThreadAttribute 和 Managed C++讨论了这个问题和一个旧的解决方案。在 Visual Studio 2005 中,您可以在Configuration Properties > Linker > Advanced中设置/CLRTHREADATTRIBUTE:STA 编译器选项,将线程属性设置为 STA,而无需创建新的入口点。

4

1 回答 1

1

I have no idea what can cause this, but I would try to find out by subclassing QDrag, overwrite deleteLater() (well, reimplement it, but as it's a slot, it will get called anyway), use this instead of a QDrag and put a breakpoint in deleteLater().

于 2008-09-20T12:24:37.723 回答