Connections qml dial and slider in qml - c++

I have a dial and a slider, in mainwindow.cpp I have:
ui->quickWidget_3->setSource(QUrl("qrc:///slider.qml"));
ui->quickWidget_4->setSource(QUrl("qrc:///dial.qml"));
I want that when I move slider dial moves..
I wrote:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtQml>
#include <QtQuick>
#include <QSlider>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setStyleSheet("background-color:white");
ui->quickWidget->engine()->rootContext()->setContextProperty("yourObject",ui->horizontalSlider);
ui->quickWidget_2->engine()->rootContext()->setContextProperty("yourObject1",ui->horizontalSlider_3);
QObject* item = ui->quickWidget_3->rootObject();
QObject::connect(item, SIGNAL(moved()), SLOT(sliderMoved()));
ui->quickWidget_2->setSource(QUrl("qrc:///sl.qml"));
ui->quickWidget->setSource(QUrl("qrc:///qml.qml"));
ui->quickWidget_3->setSource(QUrl("qrc:///slider.qml"));
ui->quickWidget_4->setSource(QUrl("qrc:///dial.qml"));
ui->horizontalSlider->setStyleSheet("QSlider::groove:vertical {background-color:red; position:absolute; left:4px; right: 4px}");
//connect circularGauge e text
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_horizontalSlider_2_sliderMoved(int position)
{
ui->dial->setValue(position);
}
void MainWindow::sliderMoved()
{
QObject* slider = ui->quickWidget_3->rootObject();
QObject* dial = ui->quickWidget_4->rootObject();
qreal value = QQmlProperty::read(slider, "value").toReal();
QQmlProperty::write(dial, "value", value);
}
but it doesn't work

It is well documented here: Interacting with QML Objects from C++
Please try to provide full relevant working code in your questions next time, like I'm going to do in this answer. Doing so, you will increase the chance of an answer.
test.pro
QT += core gui widgets quickwidgets quickcontrols2
[...]
dial.qml
import QtQuick.Controls 2.12
Dial {
id: control
from: 0
to: 100
stepSize: 1
value: 0
}
slider.qml
import QtQuick.Controls 2.12
Slider {
id: control
from: 0
to: 100
stepSize: 1
value: 0
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
public slots:
void sliderMoved();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include <QQmlProperty>
#include <QQuickItem>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->quickWidget_1->setSource(QUrl("qrc:/slider.qml"));
ui->quickWidget_2->setSource(QUrl("qrc:/dial.qml"));
QObject* item = ui->quickWidget_1->rootObject();
QObject::connect(item, SIGNAL(moved()), SLOT(sliderMoved()));
}
void MainWindow::sliderMoved()
{
QObject* slider = ui->quickWidget_1->rootObject();
QObject* dial = ui->quickWidget_2->rootObject();
qreal value = QQmlProperty::read(slider, "value").toReal();
QQmlProperty::write(dial, "value", value);
}
MainWindow::~MainWindow()
{
delete ui;
}

Related

How me get acces ui from another class?

I have a database in a separate widget class datbase.ui that I insert as tab in mainwindow.ui. I want that when initializing the connection in the class datbase.ui statusbar in mainwindow.ui to change depending.
datbase.cpp
void DatBase::on_pushButton_clicked()
{
QSqlDatabase ddbb = QSqlDatabase::addDatabase("QSQLITE");
ddbb.setDatabaseName(".../db/ddberdbsqlite");
if (ddbb.open()){
// It is necessary that this status is displayed in mainwindow.ui
// How to get access to gui mainwindow?
ui->statusBar->showMessage("Successful connection!");
}
else{
ui->statusBar->showMessage("Not Successful connection!");
}
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "datbase.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle("Measurement DDEBR");
connect(ui->tabWidget, QTabWidget::currentChanged, this, MainWindow::showTabPageIndex);
DatBase *tabDatBase = new DatBase();
ui->tabWidget->insertTab(0, tabDatBase, "Data Base");
}
MainWindow::~MainWindow()
{
delete ui;
}

Opening child window after n seconds from formation of parent window in Qt C++

I have three windows Mainwindow,firstwindow and secondwindow.I have a pushbutton in mainwindow,When i clicked the push button it opens the firstwindow.Up to this part everything is ok.
What i need is , I need to open secondwindow automaticaly after 2sec of the formation of firstwindow
What is happening now is when i clicking the push button in mainwindow, secondwindow will appear first,and the first window will form only after execution of second window.
I am using qt5 with qtcreator
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_clickMeButton_clicked()
{
FirstWindow * dlg = new FirstWindow;
dlg->show();
}
FirstWindow.cpp
#include "firstwindow.h"
#include "ui_firstwindow.h"
FirstWindow::FirstWindow(QWidget *parent) :
QDialog(parent),
ui(new Ui::FirstWindow)
{
ui->setupUi(this);
connect(this,SIGNAL(winMessage()),this,SLOT(openNewWindow()));
emit winMessage();
}
FirstWindow::~FirstWindow()
{
delete ui;
}
void FirstWindow::openNewWindow()
{
dlg = new SecondWindow;
dlg->show();
}
SecondWindow.cpp
**
#include "secondwindow.h"
#include "ui_secondwindow.h"
SecondWindow::SecondWindow(QWidget *parent) :
QDialog(parent),
ui(new Ui::SecondWindow)
{
ui->setupUi(this);
}
SecondWindow::~SecondWindow()
{
delete ui;
}
**
My understading is you want something like this:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QPushButton>
class FirstWindow : public QWidget
{
Q_OBJECT
public:
FirstWindow() : QWidget() { resize(100, 100); }
};
class SecondWindow : public QWidget
{
Q_OBJECT
public:
SecondWindow() : QWidget() { resize(100, 100); }
};
class MainWindow : public QPushButton
{
Q_OBJECT
public:
MainWindow(QWidget* parent = nullptr);
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include <QTimer>
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QPushButton(parent)
{
setText("Click me");
connect(this, &MainWindow::clicked, this, [this] {
FirstWindow* first = new FirstWindow;
first->show();
QTimer::singleShot(2000, this, [] {
(new SecondWindow)->show();
});
});
}
If you prefer to separate the implementations, you can start the timer in the first window; the timer will give time to return to the event loop and actually show the first window.
#include <QTimer>
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QPushButton(parent)
{
setText("Click me");
connect(this, &MainWindow::clicked, this, [] {
FirstWindow* first = new FirstWindow;
first->show();
});
}
FirstWindow::FirstWindow()
{
resize(100, 100);
QTimer::singleShot(2000, this, [] {
(new SecondWindow)->show();
});
}
or more precisely, you may wait for the actual show event:
#include <QTimer>
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QPushButton(parent)
{
setText("Click me");
connect(this, &MainWindow::clicked, this, [] {
FirstWindow* first = new FirstWindow;
first->show();
});
}
void FirstWindow::showEvent(QShowEvent *)
{
QTimer::singleShot(2000, this, [] {
(new SecondWindow)->show();
});
}

Changing QML Object value from C++

I created a QML class like
import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4
Rectangle {
width: 80
height: 200
property double myVal: 15
Timer {
running: true
repeat: true
interval: 1
onTriggered: gauge.value = myVal
}
Gauge {
objectName: "gauge"
id: gauge
anchors.fill: parent
anchors.margins: 10
value: myVal
Behavior on value {
NumberAnimation {
duration: 1000
}
}
style: GaugeStyle {
valueBar: Rectangle {
implicitWidth: 16
color: Qt.rgba(gauge.value / gauge.maximumValue, 0, 1 - gauge.value / gauge.maximumValue, 1)
}
}
}
}
and I want to change value from my c++ file. To do this, I created a method which is setDataToGauge() and this method is like
void MainWindow::setDataToGauge(double newVal){
QQmlApplicationEngine engine;
QQmlComponent component(&engine, QUrl::fromLocalFile("gauge.qml"));
QObject object = component.create();
QObject *myGauge = object->findChild<QObject*>("gauge");
if(myGauge){
myGauge->setProperty("value",newVal);
qDebug() << myGauge->property("value");
}
}
this. However, it doesn't change the value of gauge. I tried different methods but it couldn't find the solution. When I drop
Behavior on value {
NumberAnimation {
duration: 1000
}
}
this part from QML file value is changing but view of gauge is not changing.
Also, I am adding to full code of my c++ file
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QDateTime>
#include <QtQuickWidgets/QQuickWidget>
#include <QtQml>
#include <QObject>
QObject *object;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
m_serial(new QSerialPort(this))
{
ui->setupUi(this);
ui->gaugeWidget->setSource(QUrl::fromLocalFile("gauge.qml"));
ui->gaugeWidget->setUpdatesEnabled(true);
QQmlApplicationEngine engine;
QQmlComponent component(&engine, QUrl::fromLocalFile("gauge.qml"));
object = component.create();
setDataToGauge(60.0);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setDataToGauge(double newVal){
QObject *myGauge = object->findChild<QObject*>("gauge");
if(myGauge){
QQmlProperty::write(myGauge, "value", newVal);
qDebug() << myGauge->property("value");
}
}
What is the problem in there?
In your attempt of solution you are creating another gauge, and that gauge is not shown because the QQmlApplicationEngine is a local variable that will be deleted when it finishes executing, in addition QQmlApplicationEngine expects a Window or ApplicationWindow, not an Item like Rectangle.
On the other hand it is advisable to use a qresource to store the .qml because otherwise you will have to copy them every time you compile the side of your executable.
It is also not recommended to access QML objects from C ++, it is better to export a C ++ object to QML using setContextProperty().
A simple solution is to create a signal, the signal is connected through Connections::
*.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
void setDataToGauge(double newVal);
signals:
void dataGaugeChanged(double dataToGauge); // signal
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
*.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QQmlEngine>
#include <QQmlContext>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->gaugeWidget->engine()->rootContext()->setContextProperty("MainWindow", this);
ui->gaugeWidget->setSource(QUrl("qrc:/gauge.qml"));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setDataToGauge(double newVal){
emit dataGaugeChanged(newVal);
}
gauge.qml
import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4
Rectangle {
width: 80
height: 200
Gauge {
id: gauge
anchors.fill: parent
anchors.margins: 10
Behavior on value {
NumberAnimation {
duration: 1000
}
}
style: GaugeStyle {
valueBar: Rectangle {
implicitWidth: 16
color: Qt.rgba(gauge.value / gauge.maximumValue, 0, 1 - gauge.value / gauge.maximumValue, 1)
}
}
}
Connections{
target: MainWindow
onDataGaugeChanged: gauge.value = dataToGauge
}
}
Another option is to create a Q_PROPERTY and make a binding:
*.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
Q_PROPERTY(double dataGauge READ dataGauge WRITE setDataGauge NOTIFY dataGaugeChanged)
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
double dataGauge() const;
void setDataGauge(double dataGauge);
signals:
void dataGaugeChanged();
private:
Ui::MainWindow *ui;
double mDataGauge;
};
#endif // MAINWINDOW_H
*.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QQmlEngine>
#include <QQmlContext>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->gaugeWidget->engine()->rootContext()->setContextProperty("MainWindow", this);
ui->gaugeWidget->setSource(QUrl("qrc:/gauge.qml"));
}
MainWindow::~MainWindow()
{
delete ui;
}
double MainWindow::dataGauge() const
{
return mDataGauge;
}
void MainWindow::setDataGauge(double dataGauge)
{
if(mDataGauge == dataGauge)
return;
mDataGauge = dataGauge;
emit dataGaugeChanged();
}
*.qml
import QtQuick 2.2
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Extras 1.4
Rectangle {
width: 80
height: 200
Gauge {
id: gauge
anchors.fill: parent
anchors.margins: 10
value: MainWindow.dataGauge // binding
Behavior on value {
NumberAnimation {
duration: 1000
}
}
style: GaugeStyle {
valueBar: Rectangle {
implicitWidth: 16
color: Qt.rgba(gauge.value / gauge.maximumValue, 0, 1 - gauge.value / gauge.maximumValue, 1)
}
}
}
}
Both solutions can be found in the following link.

Why doesn't setCentralWidget work?

Here is my class MainWindow :
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
menu* v = new menu(this);
setCentralWidget(v);
}
And my menu class :
menu::menu(MainWindow* parent){
QLabel l = new QLabel("123");
QVBoxLayout* lay = new QVBoxLayout;
lay->addWidget(l);
this->setLayout(lay);
QWidget* a = new QWidget;
QVBoxLayout* lay2 = new QVBoxLayout;
QLabel* ll = new QLabel("456");
lay2->addWidget(ll);
a->setLayout(lay2);
parent->setCentralWidget(a);
}
When I run the program, the window shows 123 but I would like it to show 456.
Is the method setCentralWidget not working?
setCentralWidget works ok.
You are mixing up your widget menu construction with its position in an external widget (MainWindow). You should keep these thing well separated, or you won't be able, for example, to use menu inside other widgets.
So, you should set the appearance of menu in the constructor, and call setCentralWidget only in MainWindow.
It should look like:
file.h
menu::menu(QWidget* parent = 0);
file.cpp
menu::menu(QWidget* parent) : QWidget(parent)
{
// Create items
QLabel* l = new QLabel("123", this);
QLabel* ll = new QLabel("456", this);
// Put items in layout
QVBoxLayout* lay = new QVBoxLayout();
lay->addWidget(l);
lay->addWidget(ll);
// Set "lay" as the layout of this widget
setLayout(lay);
}
UPDATE
Since the wanted behavior is to have an interface that switch view according to button clicks:
the best option is to use a QStackedWidget.
Here a sample code the will produce this interface using QStackedWidget.
widget1.h
#ifndef WIDGET1
#define WIDGET1
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
class Widget1 : public QWidget
{
Q_OBJECT
public:
Widget1(QWidget* parent = 0) : QWidget(parent) {
QPushButton* btn = new QPushButton("Button Widget 1", this);
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(btn);
setLayout(layout);
connect(btn, SIGNAL(clicked()), SIGNAL(buttonClicked()));
}
signals:
void buttonClicked();
};
#endif // WIDGET1
widget2.h
#ifndef WIDGET2
#define WIDGET2
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
class Widget2 : public QWidget
{
Q_OBJECT
public:
Widget2(QWidget* parent = 0) : QWidget(parent) {
QPushButton* btn1 = new QPushButton("Button 1 Widget 2", this);
QPushButton* btn2 = new QPushButton("Button 2 Widget 2", this);
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(btn1);
layout->addWidget(btn2);
setLayout(layout);
connect(btn2, SIGNAL(clicked()), SIGNAL(button2Clicked()));
}
signals:
void button1Clicked();
void button2Clicked();
};
#endif // WIDGET2
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QStackedWidget>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void buttonWidget1Clicked();
void button2Widget2Clicked();
private:
QStackedWidget* m_sw;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include <QVBoxLayout>
#include <QLabel>
#include "widget1.h"
#include "widget2.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// Create Widgets
Widget1* w1 = new Widget1(this);
Widget2* w2 = new Widget2(this);
QLabel* w3 = new QLabel("Result", this);
m_sw = new QStackedWidget(this);
m_sw->addWidget(w1);
m_sw->addWidget(w2);
m_sw->addWidget(w3);
setCentralWidget(m_sw);
connect(w1, SIGNAL(buttonClicked()), this, SLOT(buttonWidget1Clicked()));
connect(w2, SIGNAL(button2Clicked()), this, SLOT(button2Widget2Clicked()));
}
void MainWindow::buttonWidget1Clicked()
{
m_sw->setCurrentIndex(1); // Will show Widget2
}
void MainWindow::button2Widget2Clicked()
{
m_sw->setCurrentIndex(2); // Will show Widgee3
}
MainWindow::~MainWindow() {}

QString exchange in qml through c++

this example is supposed to read the string from TextInput and display it in another Rectangle on click of the mouse. However, it does not. Why?
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QDeclarativeView>
#include <QDeclarativeContext>
#include <QObject>
#include <QString>
class MainWindow : public QDeclarativeView
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
};
class Data : public QObject
{
Q_OBJECT
Q_PROPERTY(QString teamName READ getTeamName WRITE setTeamName NOTIFY nameChanged)
public:
Data(QObject *parent = 0);
~Data();
public:
QString getTeamName();
void setTeamName(QString &);
signals:
void nameChanged();
private:
QString n_teamName;
};
#endif // MAINWINDOW_H
//mainwindow.cpp
#include "mainwindow.h"
#include <QDeclarativeView>
#include <QDeclarativeContext>
#include <QString>
#include <QObject>
MainWindow::MainWindow(QWidget *parent)
: QDeclarativeView(parent)
{
}
MainWindow::~MainWindow()
{
}
Data::Data(QObject *parent) : QObject(parent)
{
//n_teamName = "Ahoj";
}
Data::~Data(){
}
QString Data::getTeamName(){
return n_teamName;
}
void Data::setTeamName(QString &newName){
if(newName != n_teamName){
n_teamName = newName;
emit nameChanged();
}
}
//main.cpp
#include "mainwindow.h"
#include <qdeclarative.h>
#include <QApplication>
#include <QDeclarativeView>
#include <QDeclarativeContext>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
Data d;
qmlRegisterType<Data>("NData", 1, 0, "Data");
w.rootContext()->setContextProperty("data", &d);
w.setSource(QUrl::fromLocalFile("../klik/Main.qml"));
w.show();
return a.exec();
}
//main.qml
// import QtQuick 1.0 // to target S60 5th Edition or Maemo 5
import QtQuick 1.1
import NData 1.0
Rectangle {
id: root
width: 600
height: 400
Rectangle{
id: text
...
TextInput{
anchors.fill: text
anchors.margins: 3
focus: true
}
}
Rectangle{
...
Text{
id: copyText
anchors.centerIn: copy
text: data.setTeamName()
}
}
Rectangle{
id: klik
...
MouseArea{
...
onClicked: {
copyText.text = data.teamName
}
}
}
}
It lets out the error: TypeError: Result of expression 'data.setTeamName' [undefined] is not a function.
Main.qml:51: Error: Cannot assign [undefined] to QString
teamName is a property of data, so simply use assign operator like data.teamName = 'some text';
Probably you should add id field to your TextInput like
TextInput{
id: textInput
anchors.fill: text
anchors.margins: 3
focus: true
}
And change onClicked, so
MouseArea{
...
onClicked: {
data.teamName = textInput.text
copyText.text = data.teamName // copyText.text = textInput.text is fine too
}
}
I believe your actual exception is due to the following line
text: data.setTeamName()
setTeamName is a private function on your data object, that is not exposed as a slot, and is thus undefined when called and assigned to text. Nevermind the fact that it makes no sense to call the set when you are performing an assignment. I'm assuming this was supposed to be data.getTeamName().