Qt初学者:QLineEdit和QTextEdit的基类
除了QWidget
之外,还有另外一个类是否拥有两者的所有通用函数?像QEdit ...Qt初学者:QLineEdit和QTextEdit的基类
作为一个例子,我想引用剪切(),复制()和粘贴(),但它看起来像我必须动态铸造QWidget
。有没有其他方法?
回答:
除QWidget
之外没有别的办法。原因是QLineEdit
直接从QWidget
继承。您可以看到Qt类的完整层次结构here
回答:
您不必动态地施放任何东西:这通常是设计不好的标志。 Qt通常只有很少的接口类 - 它们通常在名称的某个地方有Abstract
这个词,而且它们不是纯粹的接口,因为它们有非抽象的基类,例如, QObject
。因此没有可遵循的模式,也不需要将编辑操作抽象为接口。
有克服这一几种方法:
杠杆的事实是有问题的方法是由元对象系统知道。请注意,
invokeMethod
需要一个方法名称,而不是签名。bool cut(QWidget * w) {
return QMetaObject::invokeMethod(w, "cut");
}
bool copy(QWidget * w) {
return QMetaObject::invokeMethod(w, "copy");
}
//...
您可以在任何支持编辑操作的窗口小部件上使用上述独立功能,如上所述。
如上所述,但缓存方法查找不会反复支付其成本。请注意,
indexOfMethod
采取方法签名,不仅仅是它的名字。static QMetaMethod lookup(QMetaObject * o, const char * signature) {
return o->method(o->indexOfMethod(signature));
}
struct Methods {
QMetaMethod cut, copy;
Methods() {}
explicit Methods(QMetaObject * o) :
cut(lookup(o, "cut()")),
copy(lookup(o, "copy()")) {}
Methods(const Methods &) = default;
};
// Meta class names have unique addresses - they are effectively memoized.
// Dynamic metaobjects are an exception we can safely ignore here.
static QMap<const char *, Methods> map;
static const Methods & lookup(QWidget * w) {
auto o = w->metaObject();
auto it = map.find(o->className());
if (it == map.end())
it = map.insert(o->className(), Methods(o));
return *it;
}
bool cut(QWidget * w) {
lookup(w).cut.invoke(w);
}
bool copy(QWidget * w) {
lookup(w).copy.invoke(w);
}
//...
定义一个接口并提供专用于窗口小部件类型的实现。这种方法的唯一好处是它比
QMetaMethod::invoke
快一点。将此代码用于剪贴板方法是没有意义的,但对于经常调用的小型方法而言,可能会降低开销。我建议不要过度设计它,除非基准测试显示它确实有帮助。以前的方法(上面#2)应该足够。// Interface
class IClipboard {
public:
virtual cut(QWidget *) = 0;
virtual copy(QWidget *) = 0;
virtual paste(QWidget *) = 0;
};
class Registry {
// all meta class names have unique addresses - they are effectively memoized
static QMap<const char *, IClipboard*> registry;
public:
static void register(const QMetaObject * o, IClipboard * clipboard) {
auto name = o->className();
auto it = registry.find(name);
if (it == registry.end())
registry.insert(name, clipboard);
else
Q_ASSERT(it->value() == clipboard);
}
static IClipboard * for(QWidget * w) {
auto it = registry.find(w->metaObject()->className());
Q_ASSERT(registry.end() != it);
return it->value();
}
static void unregister(const QMetaObject * o) {
registry.remove(o->className());
}
};
template <class W> class ClipboardWidget : public IClipboard {
Q_DISABLE_COPY(ClipboardWidget)
public:
cut(QWidget * w) override { static_cast<W*>(w)->cut(); }
copy(QWidget * w) override { static_cast<W*>(w)->copy(); }
paste(QWidget * w) override { static_cast<W*>(w)->paste(); }
ClipboardWidget() {
Registry::register(&W::staticMetaObject(), this);
}
~ClipboardWidget() {
Registry::unregister(&W::staticMetaObject());
}
};
// Implementation
QMap<const char *, IClipboard*> Registry::registry;
static ClipboardWidget<QTextEdit> w1;
static ClipboardWidget<QLineEdit> w2;
void yourCode() {
//...
Registry::for(widget)->cut(widget);
}
以上是 Qt初学者:QLineEdit和QTextEdit的基类 的全部内容, 来源链接: utcz.com/qa/260984.html