and*_*ref 28
我对Qt的大多数抱怨来自于API并不完全接受QObject提供的动态.如果你敢于创建一个元对象编译器来为C++添加动态行为,为什么还要害羞呢?
我在下面列出的所有内容都是我的团队在某些时候需要的东西,我们必须自己编写代码.这很有趣,我们学到了很多关于Qt内部的知识,但我不介意它是否已经完成并准备好使用.
没有分布式QObject
你知道,就像在Cocoa.他们用QtDBus走了一半 - 唯一剩下的就是网络.我们必须为此实现我们自己的解决方案,因为我们生活在Qt代码之外,我们无法改变内部实现所有不错的功能.
没有用于数据存储的API
当然,每个人都编写自己不完整的QObject-to-SQLite库.不过,QDataStream是一个非常好的开端.
没有数据绑定
好吧,Qt Quick有数据绑定,但数据绑定应该存在于QtCore中.通过良好的数据绑定,编写代表QObject集合的QAbstractItemModel应该是过去的事情:QObjectListModel应该是您所需要的.
(是的,QDataWidgetMapper是个笑话.)
没有QObjects的自动撤消管理
我们的模型类通常是QObjects,Q_PROPERTY有一个可选的NOTIFY信号,它正是实现自动撤销所需要的.这很容易做到应该已经成为Qt的一部分.(但是,它需要一些kludges.)
没有收藏属性
并非所有属性都是平等的.其中一些是收藏品.能够以抽象的方式处理这些将是一件好事.
半生不熟的QMetaStuff API
我只讨厌这个API因为我喜欢它.例如,一个人不能:
几乎所有这些都可以轻松解决.#2的解决方案:
QVariant call(QObject* object, QMetaMethod metaMethod, QVariantList args)
{
QList<QGenericArgument> arguments;
for (int i = 0; i < args.size(); i++) {
// Notice that we have to take a reference to the argument. A
// const_cast is needed because calling data() would detach
// the QVariant.
QVariant& argument = args[i];
QGenericArgument genericArgument(
QMetaType::typeName(argument.userType()),
const_cast<void*>(argument.constData())
);
arguments << genericArgument;
}
QVariant returnValue(QMetaType::type(metaMethod.typeName()),
static_cast<void*>(NULL));
QGenericReturnArgument returnArgument(
metaMethod.typeName(),
const_cast<void*>(returnValue.constData())
);
// Perform the call
bool ok = metaMethod.invoke(
object,
Qt::AutoConnection, // In case the object is in another thread.
returnArgument,
arguments.value(0),
arguments.value(1),
arguments.value(2),
arguments.value(3),
arguments.value(4),
arguments.value(5),
arguments.value(6),
arguments.value(7),
arguments.value(8),
arguments.value(9)
);
if (!ok) {
// Handle the error...
} else {
return returnValue;
}
}
Run Code Online (Sandbox Code Playgroud)
有用的功能可能会被删除
有兴趣在qt-interest中讨论将在Qt的未来版本中删除DOM,样式表和自定义文件引擎.
Phonon没有跨平台的后端
除了没有真正起作用外,Phonon没有稳定的后端可以在三个最常见的平台上运行:Windows,Linux和Mac OS X.有一个VLC后端,但它肯定不稳定,其许可不清楚而且,VLC对Mac的支持是" 搁置在不稳定的基础上 ".当然,责任完全在Linux上.多媒体支持从未成为 其优势之一.它缺少类似Quicktime或DirectStuff的东西.
没有加密类
有QCryptographicHash和QSSLSocket(及其有趣的错误模式),就是这样.幸运的是,有两个很好的库来填补这个空白:Botan和QCA.QCA基于Qt,但是从Java加密类复制其API,所以不是很好.Botan有一个漂亮的界面,(但?)是"纯粹的"C++.Qt风格的加密库仍然缺乏.
Hos*_*ork 11
对于SO来说,这是一个奇怪的问题,但是这里有:
qmake牙齿很长(而且我不是唯一一个这么说的人).我使用cmake,尽管它有自己的尴尬.
信号/插槽/等的元对象预处理构建步骤.是一个巨大的买入.许多愿意接受增加的抽象层次的人是那些被其他环境所吸引的人(Java,C#,无论如何).在围栏的另一边是硬核C++程序员,他们宁愿使用std::thread而不是QThread.
(如果C++程序更加面向服务器并且没有GUI,那么人们似乎避开了Qt,我明白了他们的观点.)
模型/视图既不在这里也不在那里,但它有点微不足道.我批评了线程亲和力的问题:
http://blog.hostilefork.com/qt-model-view-different-threads/
此外,我已经将应用程序交叉编译到Mac,Windows和Linux,并且发现Qt并没有像我希望的那样保护我免受平台问题的影响.如果你看一下内部结构以及如何拖放是极其多样的代码实现(例如qnd_x11.cpp,qdnd_win.cpp和qdnd_mac.mm)然后就看到了"漏抽象"的原则发挥作用.Qt并没有强加强烈的形式主义; 你会得到不同顺序或重复的消息 - 或者在某些平台上根本没有.
但除了所有批评之外,我确实喜欢Qt的设计,文档,社区支持和一般审美.你可以做得更糟! (我在看着你,wxWidgets和GTK.)
我试图解决的问题是Qt,wxWidgets以及可能的其他UI框架的一般问题:
void MainDialog::OnCppException()
{
throw std::runtime_error("test unhandled exception");
}
Qt框架捕获了这种未处理的C++异常,阻止了立即异常调试或生成信息性崩溃转储.在Qt允许处理这种情况的地方,原始异常信息和堆栈跟踪将丢失.我试图在两个框架中解决这个问题,并没有找到可接受的解决方案.Qt专业人士的建议"就是不要这样做"就是我所拥有的,这实际上意味着:不要犯错误,一切都会好的.这是我对Qt和wxWidjets的最大失望.