In my custom designer widget plugin I have a custom widget that derives QProgressBar. I have a field to chose either a determinate or indeterminate state. For this I have simply made an enum with the two states. I would like to use these values in the QtDesigner widget property area via implementing a Q_PROPERTY macro as follows:
class QDESIGNER_WIDGET_EXPORT QtMaterialProgress : public QProgressBar
{
Q_OBJECT
Q_PROPERTY(QColor progressColor WRITE setProgressColor READ progressColor)
Q_PROPERTY(QColor backgroundColor WRITE setProgressColor READ backgroundColor)
Q_PROPERTY(Material::ProgressType progressType WRITE setProgressType READ progressType)
.....
And also here is the enum declaration:
enum ProgressType
{
DeterminateProgress,
IndeterminateProgress
};
I would expect this piece of code to produce a QComboBox in the property editor of QtDesigner with the two states, however I get non of the such. I have also tried adding Q_ENUMS(PropertyType) to the header with no luck.
You have to use Q_ENUM (Not Q_ENUMS since it is deprecated from Qt 5.5: https://doc.qt.io/qt-5/whatsnew55.html) as the following example shows:
#ifndef TESTWIDGET_H
#define TESTWIDGET_H
#include <QWidget>
class TestWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY(EnumTest test READ test WRITE setTest)
public:
TestWidget(QWidget *parent = 0);
enum EnumTest { ENUM0, ENUM1, ENUM2, ENUM3 };
Q_ENUM(EnumTest)
EnumTest test() const;
void setTest(const EnumTest &test);
private:
EnumTest mTest;
};
#endif
In the following link you can find a complete example
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 a progress bar object (ui->QprogressBar) available in my mainwindow.cpp. But, I want to use this object in another class (readerfile.cpp).
Headers
mainwindow.h
demo.h
Sources
mainwindow.cpp
demo.cpp
I use this method to call object most of the time:- Using a function call, for example -mainwindow.cpp I will call this function
mainwindow->isFunction(ui->QprogressBar);
isFunction is available inside my demo.cpp file
void demo :: isfunction (QProgressBar *progress)
But, Now I want to use QprogressBar object directly inside my demo.cpp file.
I tried all possible combinations, connections and just can't get it work.
So could someone please explain me, how to access UI elements object from class demo.
Any idea for the solution will be a great help.
Thanks.
To get a pointer to an object from another class you need to implement a public function that returns this pointer. I will give you a little example:
Your class MainWindow in the header file will include a function progressbar().
mainwindow.h:
//...
class MainWindow : public QMainWindow
{
Q_ObBJECT
public:
QProgressBar *progressbar(); //returns a pointer to the QProgressBar
//..
private:
//..
};
This function is implemented in mainwindow.cpp like this:
QProgressBar *MainWindow::progressbar()
{
return ui->progbar; //I just called it like this to avoid confusion, it's the just the name you defined using QtDesigner
}
Then, in demo.hpp if you have an instance of MainWindow in your class:
//..
class Demo : public QObject
{
Q_OBJECT
public:
//..
private:
MainWindow *window;
//..
}
you can just access QProgressBar using by calling the function in demo.cpp:
QProgressBar *bar;
bar = window->progressbar();
I have to say though that it's unusual to have an instance of MainWindow in another class. Usually your QMainWindow or QApplication is the main entry point to the program and you have instances of the other classes in them, not the other way around.
I am beginner in Qt, now I want to make my label clickable, I have searched so much online, but no one gives my a real example of how they made it. So can someone teach me step by step? Now my basic thinking is creating a new .c file and new .h file respectively and then include them into my mainwindow.c and then connect it with the existing label in ui form. These are what I was trying to do, but can not make it. Hope someone can teach and better put the step picture in the command, thanks.
Here is the clicklabel.h code:
#ifndef CLICKEDLABEL_H
#define CLICKEDLABEL_H
#include <QWidget>
#include <QLabel>
class ClickedLabel : public QLabel
{
Q_OBJECT
public:
ClickedLabel(QWidget *parent=0): QLabel(parent){}
~ClickedLabel() {}
signals:
void clicked(ClickedLabel* click);
protected:
void mouseReleaseEvent(QMouseEvent*);
};
#endif // CLICKEDLABEL_H
This the clicklabel.c code:
#include "clicklabel.h"
void ClickedLabel::mouseReleaseEvent(QMouseEvent *)
{
emit clicked(this);
}
These are what I added into my mainwindow.c( the name of the label is click_test):
void data_labeling::on_label_clicked()
{
QString path="/home/j/Pictures/images.jpeg";
QPixmap cat(path);
connect(ui->click_test, SIGNAL(clicked()), this,
SLOT(on_label_clicked()));
ui->click_test->setPixmap(cat);
ui->click_test->resize(cat.width(),cat.height());
}
Of course I have promoted it to clicklabel.h and also I have added void on_label_click() to my mainwindow.h under private slots, but nothing happened.
Create a new class derived from QLabel, reimplement mousePressEvent to emit custom pressed() signal (or any other functionality you need)
If you need to use your clickable label in ui files, follow these steps:
Add QLabel to the form
Right-click on added label and select Promote to...
Enter your clickable label class name and its header file name
Press add, than select your label in the tree and select promote
Now you can use your subclassed label (this tutorial actually works for any subclassed widget) as any QWidget using ui->
You can use QPushButton instead, but if you desperately need QLabel, you can do this:
clickable.h
class Clickable :public QLabel
{
Q_OBJECT
signals:
void clicked();
public:
void mousePressEvent(QMouseEvent* event);
using QLabel::QLabel;
};
clickable.cpp
void Clickable::mousePressEvent(QMouseEvent* event)
{
emit clicked();
}
UPDATE:
This implementation I used in my source code. I can't paste complete code, but here is the part where I used it.
source.h
...
private:
QLabel* label1;
QLabel* label2;
...
source.cpp
...
label1 = new Clickable("label1 text", this);
label2 = new Clickable("label2 text", this);
...
connect(label1 , SIGNAL(clicked()), this, SLOT(label1clicked()));
connect(label2 , SIGNAL(clicked()), this, SLOT(label1clicked()));
...
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 want to add a signal to a class that inherits from QGraphicsScene.
signals:
void update(std::vector< std::vector<int> > board);
When I do this, Qt Creator warns me that I forgot the Q_OBJECT macro. But somewhere I read that since QGraphicsScene doesn't inherit from QObject, I shouldn't put it in my class definition. But signals need this macro.
How do I add a signal to a class that doesn't inherit from QObject?
boardgui.h
#ifndef BOARDGUI_H
#define BOARDGUI_H
#include <QGraphicsView>
#include <QGraphicsScene>
class BoardGUI : public QGraphicsScene
{
Q_OBJECT
public:
BoardGUI(QGraphicsView*& view, int dimension);
~BoardGUI();
void buildBoard();
signals:
void update(std::vector< std::vector<int> > board);
private:
int dimension;
QGraphicsView* view;
};
#endif // BOARDGUI_H
Reposting as answer, as requested:
Is update() your signal? did you try to implement the signal yourself? If yes, don't do that, signals are defined by moc.
QGraphicsScene does inherit from QObject. You can consult the documentation.
http://doc.qt.io/qt-5/qgraphicsscene.html
Vtables have something to do with virtual functions. When you have an error like Undefined reference to vtable then it cannot find an implementation for a virtual function (I think). Have you implemented all of your functions? Maybe you used the virtual keyword when you weren't supposed to? Or vice versa?
Also, you say that you want to add a signal, but your code chunk shows a slot? Could you show a little more of your class?
If you have not implemented any class with Q_Object before to the project and you add the Q_OBJECT line yourself, you get the vtable error. If you add another c++ class to the project that inherits from QObject, then you get rid of this problem. You can remove this class you created if you dont need it. I am not sure why this happens, but this is easy way to get rid of the problem. Maybe the creator adds some line to the . pro file when you add a class that inherits from qobject.
Have you implemented your destructor? If not, try changing ~BoardGUI(); to ~BoardGUI(){};
Have you added boardgui.h to the MOC preprocessor's file list? Any class that uses QObject and Signals/Slots needs to be passed through the Meta-Object Compiler so it can generate the actual code behind the signals.
I am unsure if Qt Creator handles this automatically.
You simply have to inherit from QObject yourself.
boardgui.h
#ifndef BOARDGUI_H
#define BOARDGUI_H
#include <QGraphicsView>
#include <QGraphicsScene>
class BoardGUI : public QObject, public QGraphicsScene
{
Q_OBJECT
public:
BoardGUI(QGraphicsView*& view, int dimension);
~BoardGUI();
void buildBoard();
signals:
void update(std::vector< std::vector<int> > board);
private:
int dimension;
QGraphicsView* view;
};
#endif // BOARDGUI_H
If you are using Qt Creator, you shouldn't have to worry about moc, everything should be handled by Qt Creator.