i am trying to take a feedback data which is published from arduino and subscribed to my GUI created in QT.
Now i have main.cpp and mainwindow.cpp.
main.cpp
#include <QtGui>
#include <ros/ros.h>
#include <QApplication>
#include "../include/abc/main_window.hpp"
#include "std_msgs/String.h"
#include <std_msgs/UInt16.h>
#include <QMainWindow>
#include <std_msgs/Float32.h>
void chatterCallback(const std_msgs::UInt16 &fb_msg){
ROS_INFO("Feedback: [%f]", fb_msg.data);
ui.label_6->setText(QString("%1").arg(fb_msg.data));
}
int main(int argc, char **argv) {
ros::init(argc, argv, "talker");
ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("feedback",1000, chatterCallback);
ros::spinOnce();
QApplication app(argc, argv);
abc::MainWindow w(argc,argv);
w.show();
w.setWindowTitle("GUI for Controlling Servo Motor");
app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
int result = app.exec();
return result;}
mainwindow.cpp
namespace abc {
using namespace Qt;
QSerialPort *serial;
MainWindow::MainWindow(int argc, char** argv, QWidget *parent)
: QMainWindow(parent)
, qnode(argc,argv)
{
ui.setupUi(this);
}
MainWindow::~MainWindow() {}
void MainWindow::on_horizontalSlider_valueChanged(int value)
{
ui.label_5->setText(QString("%1").arg(value));
msg.data = ui.label_5->text().toUInt();
ROS_INFO("%d", msg.data);
chatter_pub.publish(msg);
ros::spinOnce();
}
main_window.hpp
#ifndef abc_MAIN_WINDOW_H
#define abc_MAIN_WINDOW_H
#include <QtGui/QMainWindow>
#include "ui_main_window.h"
#include "qnode.hpp"
#include <QtSerialPort/QSerialPort>
#include <ros/ros.h>
#include "std_msgs/UInt16.h"
namespace abc {
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(int argc, char** argv, QWidget *parent = 0);
~MainWindow();
public Q_SLOTS:
private:
Ui::MainWindowDesign ui;
ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise <std_msgs::UInt16> ("chatter", 1000);
QSerialPort *arduino;
QNode qnode;
};
} // namespace abc
#endif // abc_MAIN_WINDOW_H
Now when i run this code, it shows me that UI is not declared in main.cpp.
I wanted to display the data from feedback to label_6 (TextBox). The data is only available in main.cpp, any suggestions are highly appreciable.
Thanks in advance.
You will have to pass the fb_msg.data as an argument to the MainWindow constructor. Then you can set the UI element in the MainWindow thread.
Alternatively once you create the MainWindow instance in your main, you can emit a signal which you catch and process in the MainWindow thread.
You cannot modify the UI elements from a different thread.
Related
I am trying to use OpenGLES in a desktop platform. I have a class whose name is GraphicsViewer which is derived from QOpenGLWidget. When I set the QSurfaceFormat::renderableType to QSurfaceFormat::OpenGLES, I get the following errors and nothing is drawn on the widget. Can you help me to create an OpenGLES context in a desktop platform? My OS is Windows 10 and my Qt version is 5.12.3.
Errors:
QOpenGLWidget: Failed to create context
QOpenGLWidget: Failed to create context
qt.qpa.backingstore: composeAndFlush: QOpenGLContext creation failed
QOpenGLWidget: Failed to create context
qt.qpa.backingstore: composeAndFlush: makeCurrent() failed
qt.qpa.backingstore: composeAndFlush: makeCurrent() failed
Here is my codes...
main.cpp
#include "QtOpenGLES.h"
#include <QApplication>
#include <QSurfaceFormat>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSurfaceFormat f;
f.setVersion(2, 0);
f.setRenderableType(QSurfaceFormat::OpenGLES);
QSurfaceFormat::setDefaultFormat(f);
QtOpenGLES w;
w.show();
return a.exec();
}
QtOpenGLES.h
#ifndef QTOPENGLES_H
#define QTOPENGLES_H
#include <QMainWindow>
namespace Ui {
class QtOpenGLES;
}
class QtOpenGLES : public QMainWindow
{
Q_OBJECT
public:
explicit QtOpenGLES(QWidget *parent = nullptr);
~QtOpenGLES();
private:
Ui::QtOpenGLES *ui;
};
#endif // QTOPENGLES_H
QtOpenGLES.cpp
#include "QtOpenGLES.h"
#include "ui_QtOpenGLES.h"
QtOpenGLES::QtOpenGLES(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::QtOpenGLES)
{
ui->setupUi(this);
}
QtOpenGLES::~QtOpenGLES()
{
delete ui;
}
GraphicsViewer.h
#ifndef GRAPHICSVIEWER_H
#define GRAPHICSVIEWER_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
class GraphicsViewer : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
GraphicsViewer(QWidget* parent = nullptr);
// QOpenGLWidget interface
protected:
void initializeGL();
void paintGL();
};
GraphicsViewer.cpp
#include "GraphicsViewer.h"
#include <QtOpenGL>
GraphicsViewer::GraphicsViewer(QWidget *parent) :
QOpenGLWidget (parent)
{
}
void GraphicsViewer::initializeGL()
{
initializeOpenGLFunctions();
}
void GraphicsViewer::paintGL()
{
glClearColor(1, 0, 0, 1);
}
.h
#include <QObject>
#include <QDebug>
class MyClass : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE void cppMethod (const QString &msg)
{
qDebug() << "Called the C++ method with" << msg;
}
public slots:
void cppSlot (int number)
{
qDebug() << "Called the C++ slot with" << number;
}
};
.cpp
#include <QtCore/QCoreApplication>
#include <QDeclarativeEngine>
#include <QDeclarativeComponent>
#include <QDeclarativeContext>
#include <QDeclarativeView>
#include <QVariant>
#include <QMetaObject>
#include "cppFromQml.h"
int main (int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QDeclarativeView view;
return a.exec();
}
This results in segmentation fault. What's the way out?
Qt: 4.8.1
note that you're not using MyClass, and - just my guess - a declarative view will need a QApplication to properly run.
To better understand, I created a project, dumped almost all away (just kept the .pro, where I added qt += declarative), and changed a bit your code as follow:
#include <QApplication>
#include <QDeclarativeEngine>
#include <QDeclarativeComponent>
#include <QDeclarativeContext>
#include <QDeclarativeView>
#include <QVariant>
#include <QMetaObject>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDeclarativeView view;
view.show();
return a.exec();
}
now it runs and display an empty view, as expected...
i was experimenting with QThread the other day and i wanted to create an infinite loop by using signals only and not for, foreach or while but then my code would crash after emitting the signal and executing the slot for a number of times here's my code:
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "worker.h"
#include <QThread>
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void startthreads();
private:
Ui::MainWindow *ui;
QThread thread;
worker *work;
};
#endif // MAINWINDOW_H
//worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QDebug>
#include <QMutex>
#include "insiderobject.h"
class worker : public QObject
{
Q_OBJECT
public:
explicit worker(QObject *parent = 0);
signals:
void doagain();
void okidid();
void finished();
public slots:
void printing();
};
#endif // WORKER_H
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
startthreads();
}
MainWindow::~MainWindow()
{
thread.wait();
delete ui;
delete work;
}
void MainWindow::startthreads()
{
work = new worker;
work->moveToThread(&thread);
connect(&thread, SIGNAL(started()), work, SLOT(printing()));
connect(work, SIGNAL(finished()), &thread, SLOT(quit()));
thread.start();
}
//worker.cpp
#include "worker.h"
worker::worker(QObject *parent) :
QObject(parent)
{
connect(this, SIGNAL(okidid()), this, SLOT(printing()));
}
void worker::printing()
{
qDebug() << "printing";
emit okidid();
}
//main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
i have read the entire documentation for signal/slots and threads and queued connections or whatever i could get my hands on but i could not understand the reason for this crash... also i tried chatting with people and developers at Qt irc chat room but no one could tell me the reason.
What you are doing is an infinite recursion. emit okidid(); is actually a direct call to worker::printing(). That will cause a stack overflow.
You can fix this by using a queued signal connection:
connect(this, SIGNAL(okidid()), this, SLOT(printing()), Qt::QueuedConnection);
Now the emit okidid(); is not a direct function call anymore. The worker::printing() function will be called in the Qt's event loop.
I'm trying to write application's menu for my text editor, but I don't understand why signal triggered does not working. It should open a QFileDialog::getOpenFileName, but it does not happen. Why?
main.cpp
#include "mainwindow.h"
#include "centralwidget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow *mainWindow = new MainWindow;
CentralWidget *centralWidget = new CentralWidget;
mainWindow->setCentralWidget(centralWidget);
mainWindow->show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMenu>
#include <QMenuBar>
#include <QStatusBar>
#include <QAction>
#include <QFileDialog>
#include <QString>
class MainWindow : public QMainWindow
{
public:
MainWindow();
public slots:
void slotFileDialog();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow()
{
QMenu *fileMenu = new QMenu("File");
QAction *openAction = new QAction(tr("&Open..."), this);
connect(openAction, SIGNAL(triggered()),
this, SLOT(slotFileDialog()));
fileMenu->addAction(openAction);
QMenuBar *mainMenu = new QMenuBar;
mainMenu->addMenu(fileMenu);
mainMenu->show();
QStatusBar *mainStatusBar = new QStatusBar;
setMenuBar(mainMenu);
setStatusBar(mainStatusBar);
}
void MainWindow::slotFileDialog()
{
QString fileName = QFileDialog::getOpenFileName(
this, tr("Open File"),"/home",tr("Text (*.txt)"));
}
You haven't included the Q_OBJECT macro in the class definition, so the moc will not generate the associated files for it.
I need small help, I'm using class Qslider from qt, how can I get the number of the current position of the cursor (with which function I can do that) thanks in advance
edited
I want to implement one thing: when I reach the max of the interval I want to quit, how can I do this with slot and signal?
I am assuming you want the value of the slider?
int QSlider::value ()
I looked at the code in your other post and this is what I came up with after cleaning it up:
main.cpp
#include <QApplication>
#include "mywidget.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MyWidget widget;
widget.show();
return app.exec();
}
mywidget.h
#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include <QObject>
include <QPushButton>
#include <QSlider>
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget(QWidget *parent = 0);
~MyWidget(){};
public slots:
void getSliderValueAndQuit();
private:
QPushButton *quit;
QSlider *slider;
};
#endif // MYWIDGET_H
myWidget.cpp
#include "mywidget.h"
#include <QWidget>
#include <QObject>
#include <QApplication>
#include <QFont>
#include <QLCDNumber>
#include <QPushButton>
#include <QSlider>
#include <QVBoxLayout>
MyWidget::MyWidget(QWidget *parent) :
QWidget(parent)
{
quit = new QPushButton(tr("Quit"));
quit->setFont(QFont("Times", 18, QFont::Bold));
QLCDNumber *lcd = new QLCDNumber(3);
lcd->setSegmentStyle(QLCDNumber::Flat);
slider = new QSlider(Qt::Horizontal);
slider->setRange(0, 999);
slider->setValue(0);
connect(quit, SIGNAL(clicked()), qApp, SLOT(quit()));
connect(slider, SIGNAL(valueChanged(int)),lcd, SLOT(display(int)));
connect(slider,SIGNAL(sliderReleased()), SLOT(getSliderValueAndQuit()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(quit);
layout->addWidget(lcd);
layout->addWidget(slider);
setLayout(layout);
}
void MyWidget::getSliderValueAndQuit(){
if(slider->value() == slider->maximum())
close();
}