Just got this error message while compiling a tiny class that derives from QTreeWidgetItem
:
error C2039: 'staticMetaObject' : is not a member of 'QTreeWidgetItem'
What this is saying is that QTreeWidgetItem
does not inherit from QObject
, meaning that your own, singly-inherited class also does not inherit from QObject
. Inheriting from QObject
is one of the prerequisites to using the Q_OBJECT
macro, which, if you’re anything like me, you automatically insert into any Qt GUI related class.
If you’re not using any of the meta object stuff in your subclass, such as signals/slots or properties, just take out the Q_OBJECT
macro. If you need to use signals and slots, you’ll need to make your subclass multiply-inherit from QObject
as well. If you take this route, remember that «Multiple Inheritance Requires QObject to Be First», otherwise you’ll get either the same error as above, or something along the lines of «YourClass
inherits from two QObject subclasses» from the moc.
0
0
Есть простейший класс: .h файл: #include <QGraphicsItem> class Wall : public QGraphicsItem { Q_OBJECT public: Wall(QGraphicsItem *parent = 0); }; .cpp файл: #include "wall.h" Wall::Wall(QGraphicsItem *parent) : QGraphicsItem(parent){} При компиляции выдает что-то вообще непонятное: moc_wall.cpp:37: error: ‘staticMetaObject’ is not a member of ‘QGraphicsItem’ moc_wall.cpp: In member function ‘virtual void* Wall::qt_metacast(const char*)’: moc_wall.cpp:51: error: ‘qt_metacast’ is not a member of ‘QGraphicsItem’ moc_wall.cpp: In member function ‘virtual int Wall::qt_metacall(QMetaObject::Call, int, void**)’: moc_wall.cpp:56: error: ‘qt_metacall’ is not a member of ‘QGraphicsItem’ Что за беда? В коде никакого криминала не заметил. Откуда это? PS: Debian testing, Qt 4.3.2
I have some data types defined as enum
in a namespace.
I wanted to use Q_PROPERTY
, that would return the data types…
But I get error:
'staticMetaObject' is not a member of 'blah'
So it seems, if I want to create my own types, and use them in functions that are mentioned in Q_PROPERTY
, they must be inside a class inheriting QObject
and declaring the Q_OBJECT
macro ? Isn’t that a lot of overhead ?
is there an alternative ?
asked Feb 19, 2016 at 16:23
1
Maybe you are searching for Q_GADGET
? It generates metadata for non QObject
derived types. You can have Q_PROPERTY
and Q_INVOKABLE
within a gadget.
And yes, there is quite a lot of overhead, if you don’t need QObject
don’t use it. It is like 160 bytes to begin with.
answered Feb 19, 2016 at 16:28
dtechdtech
47.7k17 gold badges112 silver badges189 bronze badges
3
Я не могу получить доступ к staticmetaobject, и я не знаю почему. Мне нужна помощь.
Вот код
Две ошибки:
staticMetaObject is not a member of MainWIndow*
Я чувствую, что это как-то связано со списком, но я не уверен.
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "form.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
Form<MainWindow*>* form;
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"#include "ui_mainwindow.h"#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
/*qDebug() << MainWindow::staticMetaObject.className();
if (QString(MainWindow::staticMetaObject.className()) == QString("MainWindow")) {
qDebug() << "test";
}*/
form = new Form<MainWindow*>(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
form->myFunc();
}
form.h
#ifndef FORM_H
#define FORM_H
#include <QObject>
#include <QDebug>
class FormBase : public QObject
{
Q_OBJECT
public:
FormBase() {}
};
template <typename T>
class Form : public FormBase, public QList<T>
{
public:
Form(T a)
{
QList<T>::append(a);
}
void myFunc()
{
qDebug() << T::staticMetaObject.className();
}
};
#endif // FORM_H
0
Решение
Вы вводите вас в заблуждение.
Ты хочешь T
быть MainWindow
так что вы можете сделать
T::staticMetaObject.className()
Это означает, что вы хотите QList<T*>
, Вы выводите из этого, поэтому вы можете просто позвонить
append(a);
Следующий код компилируется нормально:
class FormBase : public QObject
{
Q_OBJECT
public:
FormBase() {}
};
template <typename T>
class Form : public FormBase, public QList<T*>
{
public:
Form( T* a )
{
append( a );
}
void myFunc()
{
qDebug() << T::staticMetaObject.className();
}
};
class MainWindow:
public QMainWindow
{
MainWindow()
{
form = new Form<MainWindow>( this );
}
FormBase* form;
};
2
Другие решения
Других решений пока нет …
Transfer from:https://www.xuebuyuan.com/329648.html
#ifndefQQUSERITEM_HThe following error occurred
#defineQQUSERITEM_H
#include<QTreeWidgetItem>
classQQUserItem:publicQTreeWidgetItem
{
Q_OBJECT
public:
explicitQQUserItem(QQUserItem*parent=0);
signals:publicslots:};
#endif
//QQUSERITEM_H
debugmoc_QQUserItem.cpp:41:8: error: 'staticMetaObject' is not a member of 'QTreeWidgetItem'
....Qt4.6.3include/QtCore/http://www.cnblogs.com/src/corelib/kernel/qobject.h: In member function 'virtual const QMetaObject* QQUserItem::metaObject() const':
....Qt4.6.3include/QtCore/http://www.cnblogs.com/src/corelib/kernel/qobject.h:296:33: error: 'QScopedPointer<QObjectData> QObject::d_ptr' is protected
debugmoc_QQUserItem.cpp:51:21: error: within this context
....Qt4.6.3include/QtCore/http://www.cnblogs.com/src/corelib/kernel/qobject.h:296:33: error: object missing in reference to 'QObject::d_ptr'
debugmoc_QQUserItem.cpp:51:21: error: from this location
....Qt4.6.3include/QtCore/http://www.cnblogs.com/src/corelib/kernel/qobject.h:296:33: error: 'QScopedPointer<QObjectData> QObject::d_ptr' is protected
debugmoc_QQUserItem.cpp:51:50: error: within this context
....Qt4.6.3include/QtCore/http://www.cnblogs.com/src/corelib/kernel/qobject.h:296:33: error: object missing in reference to 'QObject::d_ptr'
debugmoc_QQUserItem.cpp:51:50: error: from this location
debugmoc_QQUserItem.cpp: In member function 'virtual void* QQUserItem::qt_metacast(const char*)':
debugmoc_QQUserItem.cpp:59:12: error: 'qt_metacast' is not a member of 'QTreeWidgetItem'
debugmoc_QQUserItem.cpp: In member function 'virtual int QQUserItem::qt_metacall(QMetaObject::Call, int, void**)':
debugmoc_QQUserItem.cpp:64:11: error: 'qt_metacall' is not a member of 'QTreeWidgetItem'
debugmoc_QQUserItem.cpp: In member function 'virtual void* QQUserItem::qt_metacast(const char*)':
debugmoc_QQUserItem.cpp:60:1: warning: control reaches end of non-void function
debugmoc_QQUserItem.cpp: In member function 'virtual const QMetaObject* QQUserItem::metaObject() const':
debugmoc_QQUserItem.cpp:52:1: warning: control reaches end of non-void function
mingw32-make[1]: *** [debug/moc_QQUserItem.o] Error 1
mingw32-make: *** [debug] Error 2
The process "D:/MinGW/bin/mingw32-make.exe" exited with code %2.
Error while building project MyQQ (target: Desktop)
When executing build step 'Make'
Modified into such classQQUserItem: publicQObject, publicQTreeWidgetItem is no error, found the following information:
There is actually such a mistake: 'staticMetaObject' is not a member of 'Ui::MainWindow'
The earliest contact with this type of design started with the Borland C++ Builder. As a so-called rapid development tool, I didn’t have a clear understanding of the interface design. Later, I came into contact with Java for a while. At that time, I only knew that I designed the interface to inherit a class, such as the main window or applet, and then added many other components to the class as their protected members. However, it is rarely considered how to design more convenient. Therefore, it can be said that the GUI library that comes into contact with the first such design idea is in Qt. I have to say that Qt is very similar to Java. Although Qt is written in C++, it is noted that it is actually a single ancestor QObject. The RTTI implemented by QMetaObject is more or less consistent with Java’s single ancestor, but Qt does not exclude other uses. The C++ class just lost the signal/slot mechanism. In the man page of moc, I actually introduced the limitations of Qt implementation:
We can’t inherit QObject using template. In other words, the following code cannot be converted to a valid C++ compiler compilable code by moc:
template<class>
class TemplateClass : public QObject {
Q_OBJECT
// ...
public slots:
// ...
} ;
To use multiple inheritance you must put QObject or its subclasses in the first parent class (because Q_OBJECT needs to be overridden) and then inherit from other classes. After reversing, such as g++ will hold the wrong, such as
multiclass.hpp:17: Warning: Class MultiClass inherits from two QObject subclasses NoneQtClass and QObject. This is not supported!
moc_multiclass.cpp:39: error: ‘staticMetaObject’ is not a member of ‘NoneQtClass’
moc_multiclass.cpp: In member function ‘virtual void* MultiClass::qt_metacast(const char*)’:
moc_multiclass.cpp:55: error: ‘qt_metacast’ is not a member of ‘NoneQtClass’
moc_multiclass.cpp: In member function ‘virtual int MultiClass::qt_metacall(QMetaObject::Call, int, void**)’:
moc_multiclass.cpp:60: error: ‘qt_metacall’ is not a member of ‘NoneQtClass’
Make: *** [moc_multiclass.o] Error 1 MultiClass inherits QObject and NoneQtClass. After the inserted Q_OBJECT is expanded, since the structure of MultiClass is not in front of the second class after the NoneQtClass is placed, the staticMetaObject error is created, followed by the virtual function table. Also because of the latter, it is actually the vtable of the previous class.
Function pointers cannot be used as arguments to signal/slot, which can be overcome with typedef, such as
class SomeClass : public QObject
{
Q_OBJECT
//...
public slots:
// illegal
void apply( void (*apply)(List *, void *), void * );
};
/ / Will be considered illegal (mainly to judge the parameter type will fail, remember what information is saved by QMetaObject?), but
typedef void (*ApplyFunctionType)( List *, void * );
class SomeClass : public QObject
{
Q_OBJECT
//...
public slots:
void apply( ApplyFunctionType, char * );
};
//It works.
It is best not to put the friend declaration in the signal and slot declarations, which is obvious, because in most cases, according to macro substitution, signals: is replaced with protected:, slots are replaced with null, but the compiler may not be fully processed by friends. Such irrelevant processing, in theory, the standard compiler should be able to work, such as g++ 4.3.3.
signal and slot cannot be upgraded, because moc requires a complete function declaration, and the promotion is incomplete when it is raised, such as
class SlotClass : public QObject
{
Q_OBJECT
protected slots:
int getValue() ;
} ;
class UpgradeSlotClass : public SlotClass
{
Q_OBJECT
public slots:
Slot::getValue ;
} ;
Among them, the improvement of Slot::getValue is allowed in the normal situation, and it can be seen that the error is moc.
/usr/bin/moc-qt4 -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. upgradeslotclass.hpp -o moc_upgradeslotclass.cpp
upgradeslotclass.hpp:15: Error: Not a signal or slot
The parameters of declarationsignal and slot cannot use macros because moc does not expand macros.
Nested class declarations should not appear in signal or slot, but also because moc can’t handle it.
The constructor should not appear in signal and slot, although it is a function, but it is not necessary.
The Q_PROPERTY macro should declare the property before the public section containing its read/write function, not written in the same public. Note
#define Q_PROPERTY(text) In fact, this sentence has no effect when the class is declared, but the moc compiler will generate the corresponding code, and moc requires that this part must be written in a way similar to the following
class PropertyClass : public QObject
{
Q_OBJECT
Q_PROPERTY( int value READ getValue WRITE setValue )
int value ;
public:
PropertyClass() ;
void setValue( int = 0 ) ;
int getValue() const ;
} ;
This part corresponds to moc will produce the following code
int PropertyClass::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QObject::qt_metacall(_c, _id, _a);
if (_id < _c ="=" _v =" _a[0];" _c ="=" _v =" _a[0];" _c ="=" _c ="=" _c ="=" _c ="=" _c ="=" _c ="=">
Why do you provide support properties and Q_CLASSINFO in QMetaObject that don’t seem to be necessary at all? The latter such as
Q_CLASSINFO(“Version”, “3.0.0”)
These are actually support for GUI design programs in one aspect. The GUI design program provided by Qt is called Qt Designer (it seems that Qt Creator can also be designed). This is a graphical interface. Drag the required widgets to the window and organize them with the appropriate layout. When each widget is clicked, A property editor, where you can set the property that was previously declared with Q_PROPERTY and is DESIGNABLE true. This is called the widget editing mode. There is also signal and slot editing mode, where you can directly drag the signal-emitting widget to the widget of the slot, which will generate an arrow, then fill in the corresponding signal and slot. In buddy editing mode, we will somehow not accept keyboard response widgets to the widgets that accept keyboard responses, which will give them the ability to handle keyboards with equal effectiveness. In tab order mode we set the order in which we traverse in TAB. There is also a resource editor for us to manage resources, such as the image used, the action editor lets us edit the action on the menu (finally connect the menu item or toolbar to it). The newly added QUiLoader class allows Qt to handle the interface described by XML files like glade and generate it dynamically.
Qt provides far more than just widgets (compared to gtkmm), it also provides support for accessibility, database SQL, network modules, etc., which we will discuss later. Here we focus on some of the design features of Qt designer.
Qt Designer can preview the skin, add your own CSS-like stylesheet to change the style of the widget, which can be opened with the preview in settings -> preference -> form, or directly by adding a styleSheet of a widget. The commonly used containers in Qt are Frame, GroupBox, StackedWidget, TabWidget, ToolboxWidget, and DockWidget. We can put other widgets in it.
Qt design menus and toolbars are very simple, the interface and functions are designed separately. The interface can be added in the editing state according to the requirements. Click inside the menu to create a keyboard operation. For example, &File will make the menu open. Then press F to call the menu. Similarly, you can add some buttons to the toolbar after adding it. The function is edited with the Action Editor.
Let’s look at how to use the interface designed by Qt Designer to integrate with our program. The first thing to understand is how the .ui file output by Qt Designer will be processed. This is handled by the uic program. This will generate a .h file. For example, mywindow.ui will generate a ui_mywindow.h file with two parts. One is the Ui_MyWindow class. This class only contains all the widgets except the top widget. For example, our window uses QMainWindow or QWidget class, which has several layouts, buttons, etc., then the generated Ui_MyWindow class contains all but QMainWindow or QWidget. A pointer to components and the interface we designed is rendered on the specified top-level widget via the setupUi( QMainWindow *) method. In addition, a MyWindow class is declared in the Ui namespace, inheriting Ui_MyWindow, in order to avoid namespace pollution. So the easiest way to preview our form is to use the following code,
#include "ui_main.h"
int main( int argc, char *argv[] )
{
QApplication app( argc, argv ) ;
QMainWindow *widget = new QMainWindow ;
Ui::MainWindow ui ;
ui.setupUi( widget ) ;
widget -> show() ;
return app.exec() ;
}
We will analyze the relevant code in detail later. Note that we generate a QMainWindow via new, then pay attention to using Ui::MainWindow to generate a class entity that only generates code, and call the setupUi() method to generate the interface we need on the widget. Finally, call the widget’s show() method and start the message loop with app.exec() .
Here is a question about the release of the widget. Note that the controls generated by calling new in ui are destroyed together when the widget is destroyed. The ui is not destructed, because in fact it is dangling pointer, which is very dangerous. Never do this step more. Also, closing the window will trigger the QMainWindow::close() slot, which will destruct the form (if the QWidget::DeleteOnClose property is set).
However, we have added very simple signal/slot connections in Qt Designer, and there are many functions that we don’t implement in Qt Designer. Therefore, we need to use other methods to not automatically modify the code. Implement your own features. The easiest way is to inherit the form class and use the interface as a private member.
class MyWindow : public QMainWindow
{
// ...
private:
Ui::MyWindow ui ;
} ;
This way you can create your own interface with ui(this) when constructing MyWindow::MyWindow() , and then modify the signal/slot connection with functions such as QObject::connect(). But the connection must be made through the member ui.
It is more convenient to use multiple inheritance,
class MyWindow : public QMainWindow, private Ui::MyWindow
{
// ...
public:
MyWindow( QWidget *p ) : QMainWindow(p),
Ui::MyWindow() {
setupUi( this ) ;
// ...
}
} ;
At this point we can connect directly to MyWindow::component. However, it’s worth noting that connect can only be done between QObjects, not to non-QObject objects, and to connect to normal functions.
The other is similar to glade implementation,
QWidget* TextFinder::loadUiFile()
{
QUiLoader loader;
QFile file(":/forms/textfinder.ui");
file.open(QFile::ReadOnly);
QWidget *formWidget = loader.load(&file, this);
file.close();
return formWidget;
}
Note that dynamic loading cannot be called in the form of formWidget -> member. We should use QObject::objectName() to search for the corresponding address, such as
ui_findButton = qFindChild(this, "findButton");
We will compare the difference between gtkmm and similar functions.
The most common way to create a connection is to create it manually, because you said that you must connect to a QObject, so the most straightforward approach is as follows
ImageDialog::ImageDialog(QWidget *parent)
: QDialog(parent)
{
setupUi(this);
okButton->setAutoDefault(false);
cancelButton->setAutoDefault(false);
// ...
connect(okButton, SIGNAL(clicked()), this, SLOT(checkValues()));
}
Put the slot in the private slots of multiple inheritance QObjects, but Qt can use QMetaObject to implement automatic connections. This is the slot defined by the agreed on_objectName_signal, connected by QMetaObject::connectSlotsByName(QObject *), such as multiple inheritance. , take this, and the interface generated from the ui file uses the widget pointer returned by QUiLoader::load(). This function is called automatically by code generated by uic.
A link error, the program structure is very simple, is the designer design main interface, use multiple inheritance in the code, the strange error message is as follows:
moc_mainwin.cpp:39: error: ‘staticMetaObject’ is not a member of ‘Ui::MainWindow’
moc_mainwin.cpp: In member function ‘virtual void* MainWin::qt_metacast(const char*)’: moc_mainwin.cpp:56: error: ‘qt_metacast’ is not a member of ‘MainWin::qt_metacast(const char*)::QMocSuperClass’
moc_mainwin.cpp: In member function ‘virtual int MainWin::qt_metacall(QMetaObject::Call, int, void**)’: moc_mainwin.cpp:62: error: ‘qt_metacall’ is not a member of ‘MainWin::qt_metacall(QMetaObject::Call, int, void**)::QMocSuperClass’
make: *** [moc_mainwin.o] Error 1
Qt automatically generated moc file will also compile error? This is a bit ridiculous. The author took the project and looked at it from the beginning and did not see any errors that might cause this link error. After a long time, the warning reported in a compilation stage caused the author’s attention. The general idea is that multiple inheritance cannot be inherited from two QObject classes. This is strange. How does it treat my UI class as being derived from QObject? What? With this hint, I tried to modify the line of multiple inheritance:
class MainWin: public Ui::MainWindow, public QWidget
Changed to
class MainWin: public QWidget, public Ui::MainWindow
As a result, guess what? The miracle happened… Oh, the compilation was successful! It turned out to be a problem caused by the order of inheritance. Is this a Qt bug? The trolltech support bug report got the answer like this:
This is actually a known limitation which has been documented for some time, when using multiple inheritance you have to specify the QObject based class first and then the other class. Its mentioned in the documentation at:
http://doc.trolltech.com/4.5/moc.html
under the limitations section.
It turns out to be like him! It seems that the embarrassing road is not enough. Such an important document never knows its existence.
After reading it carefully, I found that there are still a lot of programming restrictions related to moc in Qt. We need to pay attention to it.
The number of functions of moc
1. Process the Q_OBJECT macro and the signals/slots keyword to generate the underlying code for the signal and slot.
2, handle Q_PROPERTY () and Q_ENUM () to generate property system code
3, processing Q_FLAGS () and Q_CLASSINFO () to generate additional class meta information
4. Code that does not require moc processing can be enclosed in predefined macros as follows:
#ifndef Q_MOC_RUN
…
#endif
The number of moc restrictions is too large (too much, dazzling)
1, the template class can not use the signal / slot mechanism
2, moc does not extend macros, so the definition of signals and slots cannot use macros. When connecting, you can’t use macros to make signal and slot names and parameters.
3, when derived from multiple classes, QObject derived class must be placed in the first one, because moc is so considered… (comparative rogue) This is also the case of our previous example
4, the function pointer can not be used as a signal or slot parameters, because its format is more complicated, moc can not handle. But you can use typedef to define it as a simple form to use. (This trick is really enough)
5. When using the enumerated type or typedef type to make signal and slot parameters, it must be fully qualified. The Chinese does not know how to translate. It is simple to say that if it is defined in a class, you must add the path of the class or the path of the namespace to prevent confusion. For example, Qt::Alignment, etc., the previous Qt is the qualifier of Alignment, which must be added, and there are several levels plus several levels.
6, signal and slot can not return reference type
7, signals and slots keyword area can only be placed in the definition of signals and slots, can not put other such as variable definitions, etc.
Oh, these restrictions feel quite like an unequal treaty. Is it an eye-opener for you? In fact, some of these restrictions should be treated as bugs, but the impact on Qt programming is not too big, can be ignored for a while, so it is classified as a low priority problem (meaning it may never change)