无法使qmlRegisterType工作

时间:2014-03-07 02:41:11

标签: c++ qt mingw qml qt5

我在互联网上找到了一些qmlRegisterType的例子,但却无法使其正常工作。我创建了一个新的Qt Quick 2项目,并添加了以下内容:

这是我的.pro文件:

#Add more folders to ship with the application, here
folder_01.source = qml/testlib
folder_01.target = qml
DEPLOYMENTFOLDERS = folder_01

#Libraries
QT += core gui widgets

#Additional import path used to resolve QML modules in Creator's code model
QML_IMPORT_PATH =

#Header files
HEADERS += main.hpp

#The .cpp file which was generated for your project. Feel free to hack it.
SOURCES += main.cpp

#Installation path
#target.path =

#Please do not modify the following two lines. Required for deployment.
include(qtquick2applicationviewer/qtquick2applicationviewer.pri)
qtcAddDeployment()

这是我的代码文件(main.cpp):

#include <QtQml>
#include <QtWidgets/QApplication>
#include "qtquick2applicationviewer.h"

//test class
class TestClass:public QObject {
  Q_OBJECT

  public:
    TestClass(QObject* parent=0):QObject(parent){}

  public slots:
    void test() {
      qDebug("test!");
    }
};

//entry point
int main(int argc, char *argv[]) {

  //create application
  QApplication app(argc, argv);

  //register custom qml component
  qmlRegisterType<TestClass>("testlib",1,0,"TestClass");

  //create and show qml viewer
  QtQuick2ApplicationViewer viewer;
  viewer.setMainQmlFile(QStringLiteral("qml/testlib/main.qml"));
  viewer.showExpanded();

  //back to OS
  return app.exec();
}

这是我的QML文件(main.qml):

import QtQuick 2.0
import testlib 1.0

Rectangle {

  TestClass {
    id:testobj
  }

  Component.onCompleted: {
    testobj.test();
  }
}

但我遇到了多个链接错误:

  • 未定义引用`vtable for TestClass'
  • 未定义对`TestClass :: staticMetaObject'
  • 的引用
  • 未定义对`TestClass :: metaObject()const'
  • 的引用
  • 未定义对`TestClass :: qt_metacast(char const *)'
  • 的引用
  • 未定义引用`TestClass :: qt_metacall(QMetaObject :: Call,int,void **)'

undefined reference to vtable

我使用的是MingW 4.8稳定版附带的Qt 5.2.1。这些错误意味着链接器无法找到包含方法实现的库文件(如上所述)。 发生什么事了?可能无法在Qt 5上编译,但在Qt 4上没问题?

3 个答案:

答案 0 :(得分:10)

关于使用Qt进行编译的注意事项:

(1) Use 'QT +=' in .pro file for Qt headers & Qt libraries

(2) Use 'HEADERS +=' and 'SOURCES +=' in .pro file for 
project level headers and source codes

关于创建自定义QML组件的注意事项(此处称为'CustomCom'):

(1) Inherit publically 'CustomCom' from QQuickItem: 

class CustomCom:public QQuickItem {}

(2) Put the Q_OBJECT macro right after first line of 
class 'CustomCom' declaration.

(3) Inherit the constructor:

public: CustomCom(QQuickItem* parent=0):QQuickItem(parent){}

(4) Put the methods to be called by JS after "public slots:"

(5) Call 'qmlRegisterType' after creation of 'QApplication' and
before creating any QML view or viewer.

(6) IMPORTANT: If you fail to compile with error 
'undefined reference to vtable...", just put the code of 'CustomCom.cpp'
nested inside the 'CustomCom.hpp' file, and put the whole code 
of the class 'CustomCom.hpp' in the main header file because of
something wrong in header referencing. 

示例标题代码:

[main.hpp]
class CustomCom:public QQuickItem {
  Q_OBJECT

  public:
    CustomCom(QQuickItem* parent=0):QQuickItem(parent){}

  public slots:
    void test() {
      qDebug("Test!");
    }
};

示例源代码:

[main.cpp]
int main(int argc,char** args) {
  QApplication* app = new QApplication(argc,args);

  //call before any qml may use the custom component
  qmlRegisterType<CustomCom>("CustomLib",1,0,"CustomCom");

  //class 'QtQuick2ApplicationViewer' is generated by Qt Creator
  //when creating new Quick 2 project. The path to 'main.qml'
  //may be different
  QtQuick2ApplicationViewer* viewer = new QtQuick2ApplicationViewer();
  viewer->setMainQmlFile("qml/project/main.qml");
  viewer->showExpanded();
}

示例QML:

[main.qml]
import QtQuick 2.0
import CustomLib 1.0

Rectangle {
  width:640; height:360;

  CustomCom {
    id:customcom;
  }

  Component.onCompleted: {
    customcom.test();
  }
}

问题的解决方案(面对'未定义的vtable引用'):

  • 结合'TestClass.hpp'&amp; 'TestClass.cpp'进入'TestClass.hpp'文件
  • 将'TestClass.hpp'的内容移至'main.hpp'

问题是由使用主头文件引起的。仅在需要时放置#include(s)才能解决问题。

答案 1 :(得分:4)

首先,您不要调用父构造函数

TestClass::TestClass():QObject(0) {
}

或更好

TestClass::TestClass(QObject* parent=0): 
  QObject (parent) {    
}

第二,你在哪里调用qmlRegister?如果我是对的你需要在使用之前注册类型,所以在QQmlEngine加载qml文件的源代码之前。

答案 2 :(得分:1)

我遇到了同样的问题,只需将头文件(在您的案例中为TestClass.hpp)添加到.pro文件中就可以解决问题:

HEADERS += TestClass.hpp

它将保证moc会找到它。顺便说一句,.h文件也没问题。

相关问题