I want to add C++ class like this notchedrectangle.hpp to QML:
#ifndef NOTCHEDRECTANGLE_HPP
#define NOTCHEDRECTANGLE_HPP
#include <QtQml/qqmlregistration.h>
#include <QQuickPaintedItem>
class NotchedRectangle : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
QML_ELEMENT
public:
NotchedRectangle();
void paint(QPainter* painter) override;
QColor color() const;
void setColor(QColor color);
signals:
void colorChanged();
private:
QColor m_color;
};
#endif // NOTCHEDRECTANGLE_HPP
I have qmake build system, but don't know - what should I add in qmake file.
My filesystem looks like that:
I tried to add to qmake file this strings:
CONFIG += qmltypes
QML_IMPORT_NAME = UI.NR
QML_IMPORT_MAJOR_VERSION = 1
INCLUDEPATH += UI/NotchedRectangle
But they will cause error:
[Makefile.Debug:1175: qlauncher_metatypes.json] Error 1
Can you help me, please?
you should import in qml file after exposing the class:
import UI.NR 1.0
I suggest you to change UI.NR to smth else which has no dot in it.
Then take an instance:
WhatEverYouNamed {
}
QML_IMPORT_NAME is not a name of class!
It's the name of package and must be different.
I use "Custom".
Next you must include class in main.cpp
And finally - you should make Recompile
Related
After integration C++ and QML using the way described here:
QML C++ integration
I have noticed only .h methods are visible outside class (from QML level), I have no access for public variables.
After research I found that:
void QQmlContext::setContextProperty(const QString &name, const QVariant &value)
Is this way proper?
If not, how can I get access to my class public variables from QML level ?
Supposedly I can create functions for this purpose, but I don't like this way.
It looks for me like way around...
In the following example, I wanted to expose the C++ qVersion() from QtGlobal to QML as System.qtVersion.
//System.h
#ifndef System_H
#define System_H
#include <QObject>
class System : public QObject
{
Q_OBJECT
Q_PROPERTY(QString qtVersion READ qtVersion CONSTANT)
public:
System(QObject* parent = nullptr);
QString qtVersion() const;
};
#endif
//System.cpp
#include "System.h"
System::System(QObject * parent) :
QObject(parent)
{
}
QString System::qtVersion() const
{
return qVersion();
}
#endif
```c++
//main.cpp
//...
qmlRegisterSingletonType<System>("qmlonline", 1, 0, "System", [](QQmlEngine*,QJSEngine*) -> QObject* { return new System(); } );
I can access the above in QML with the following snippet:
import QtQuick
import QtQuick.Controls
import qmlonline
Page {
Text {
text: System.qtVersion
}
}
You can try the QML portion online
For other examples of C++ wrappings to QML checkout my GitHub projects:
https://github.com/stephenquan/qt-toolkit
https://github.com/stephenquan/qmlonline6
I have created a custom widget called OpenGLWidget which I have registered with the qmlRegisterType function.
Nested inside the Qml file, I have this:
OpenGLWidget {
id: glwidget
width: parent.width
}
My app dies saying that width is a readonly property.
I have also tried adding this line to the OpenGLWidget header file:
Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged)
(However, even if these methods are not there, the code still compiles -- why?)
Anyway, it seems to me like Q_PROPERTY is used if you want to add your own custom properties, but properties like x, y, width, height, etc (which are all readonly) ought to be built-in, no?
EDIT: OpenGLWidget header file upon request.
#ifndef OPENGLWIDGET_H
#define OPENGLWIDGET_H
#include <QObject>
#include <QGLWidget>
class OpenGLWidget : public QGLWidget
{
Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged)
public:
OpenGLWidget();
void setWidth(int width) { resizeGL(width, this->geometry().height()); }
void widthChanged(int width) { }
protected:
void initializeGL();
void paintGL();
void resizeGL(int width, int height);
};
#endif // OPENGLWIDGET_H
Your class is missing the Q_OBJECT macro. This causes the Qt meta object system to think of it as the closest superclass where the macro was defined, missing your method overrides.
Add Q_OBJECT line before the Q_PROPERTY line (it is needed so that the build system knows to run moc for this class). Then run qmake manually (eg. from Qt Creator build menu), because this change isn't picked up automatically so Makefiles aren't updated automatically.
It is a good idea to use Qt Creator new class wizard to add classes to a project, to avoid easy mistakes like this.
I am attempting to make a custom TCP widget for QML for my project (WebSocket sends a HTTP request, it doesn't allow me to send raw TCP packets). I created the "TCPSocketConnection" (named in cpp as TCPSocketConn) class and gave it some properties with placeholder methods and tried to insert it into QML. When I tried to use the class, I get the following error
qrc:/qml/qmlwebsocketclient/main.qml:43:9: Cannot assign to non-existent property "onTextMessageReceived"
I have a QML file like this
****************************************************************************/
import QtQuick 2.0
import QtWebSockets 1.0
import Qt.Comm 2.0
Rectangle {
width: 360
height: 360
TCPSocketConnection{
id: socket
url: "ff"
onTextMessageReceived: {
console.log("On Recieve: " + messsage)
}
}
}
The TCPSocketConnection is defined as follows
qmlRegisterType<TCPSocketConn>("Qt.Comm", 2, 0, "TCPSocketConnection");
in tcpsocketconn.h
#ifndef TCPSOCKETCONN_H
#define TCPSOCKETCONN_H
#include <QQuickItem>
class TCPSocketConn : public QQuickItem
{
Q_PROPERTY(QString url READ url WRITE a_1 NOTIFY a_2)
Q_PROPERTY(QString message READ message WRITE a_3 NOTIFY textMessageRecieved)
Q_PROPERTY(int status READ status WRITE a_4 NOTIFY statusChanged)
public:
explicit TCPSocketConn(QQuickItem *parent = 0);
QString url();
QString message();
int status();
signals:
void a_2();
void textMessageReceived();
void statusChanged();
public slots:
void a_1(QString);
void a_3(QString);
void a_4(int);
};
#endif // TCPSOCKETCONN_H
with a placeholder cpp file
#include "tcpsocketconn.h"
TCPSocketConn::TCPSocketConn(QQuickItem *parent) : QQuickItem(parent)
{
}
QString TCPSocketConn::url(){
return "";
}
QString TCPSocketConn::message(){
return "";
}
int TCPSocketConn::status(){
return 0;
}
void TCPSocketConn::a_1(QString d){
}
void TCPSocketConn::a_3(QString d){
}
void TCPSocketConn::a_4(int s){
}
void TCPSocketConn::textMessageReceived(){
}
void TCPSocketConn::statusChanged(){
}
void TCPSocketConn::a_2(){
}
You're missing the Q_OBJECT macro; it's not enough to just derive from a QObject subclass:
The Q_OBJECT macro must appear in the private section of a class definition that declares its own signals and slots or that uses other services provided by Qt's meta-object system.
There's also this paragraph:
Notice that the Q_OBJECT macro is mandatory for any object that implements signals, slots or properties. You also need to run the Meta Object Compiler on the source file. We strongly recommend the use of this macro in all subclasses of QObject regardless of whether or not they actually use signals, slots and properties, since failure to do so may lead certain functions to exhibit strange behavior.
This is explained in more detail here.
I am trying to add property title into the main window of my application. But when I try to compile it, the compiler gives me this error:
mainwindow.cpp:19: undefined reference to `MainWindow::titleChanged(QString const&)'
I tried it on mingw and msvc2013 both fails on the same line with this error. The header/source files:
mainwindow.h:
#ifndef MAINWINDOW
#define MAINWINDOW
#include <QObject>
#include <QString>
class MainWindow : public QObject {
QOBJECT_H
Q_PROPERTY(QString title READ getTitle WRITE setTitle NOTIFY titleChanged)
public:
MainWindow();
QString getTitle();
public slots:
void setTitle(const QString& title);
signals:
void titleChanged(const QString& title);
private:
QString title_;
};
#endif // MAINWINDOW
mainwindow.cpp:
#include "mainwindow.h"
#include <QString>
MainWindow::MainWindow()
{
}
QString MainWindow::getTitle()
{
return title_;
}
void MainWindow::setTitle(const QString& title)
{
if (title_ != title) {
title_ = title;
emit titleChanged(title);
}
}
If I add the method below to the end of mainwindow.cpp file, then the application compiles and runs, but the signal isn't emitted:
void MainWindow::titleChanged(const QString&)
{
}
I tried to cleaning out the project's build folders, it doesn't help :(. I am using QT 5.4 and working on QT Creator.
This question was already answered in comments by someone else. I just wanted to highlight the answer. The error in my case was in the header file
mainwindow.h:
class MainWindow : public QObject {
QOBJECT_H // This should be Q_OBJECT
...
I confused the QOBJECT_H macro used in QObject.h header file as an include guard with the Q_OBJECT macro used by QT's moc tool. Since the intellisense will offer you both options, they are easy to confuse.
I also got pointed to a good reading about common problems with signals/slots worth for reading: My signal / slot connection does not work
I'm a newbie in Qt and not that much experienced in C++ either.
I created simple Qt GUI app, but then I had to add the mousepressevent function on a QLabel type object, so I created the class which has the header file with following code:
#ifndef IMAGEACTION_H
#define IMAGEACTION_H
#include <QLabel>
#include <QMouseEvent>
#include <QDebug>
#include <QEvent>
class imageaction : public QLabel
{
Q_OBJECT
public:
explicit imageaction(QWidget *parent = 0);
void mousePressEvent(QMouseEvent *ev);
signals:
void Mouse_Pressed();
public slots:
};
#endif // IMAGEACTION_H
The .cpp file has the following code:
#include "imageaction.h"
imageaction::imageaction(QWidget *parent) :
QLabel(parent)
{
}
void imageaction::mousePressEvent(QMouseEvent *ev)
{
emit Mouse_Pressed();
}
In the mainwindow.cpp file added the line #include "imageaction.h" to include the header file and in the .pro file it's the following lines are also added:
SOURCES += main.cpp\
mainwindow.cpp \
imageaction.cpp
HEADERS += mainwindow.h \
imageaction.h
But the program always gives the following error:
C1083: Cannot open include file:'imageaction.h': No such file or directory.
Could you say where I'm making the mistake? To make this class I followed this video
I think, "C1083: Cannot open include file:'imageaction.h': No such file or directory" error from your ui_*.h file. If that is the case, your issue regading promoting imageaction widget.
This may work
1. while promoting imageaction widget, uncheck "globalinclude".
or
2. Update pro file with "INCLUDEPATH += path where mywidget.h"
Please check for more info Promoting Widget