How to combine 2 applications in one application with one window
-
Hello everyone, so my problem is that i have a Qt application that allows me to take images using a thermal camera on a raspberry Pi, and then i have another application that allows me to take and save images using a nightvision camera, now the purpose of my project is to combine both projects and have one window showing both the thermal camera flow as well as the night camera flow with a capture button that'll take and save images for both cameras, meaning if i click on the capture button, both cameras need to take an image and save it. I don't know how to combine 2 .cpp into one especially that my thermal camera application runs on main.cpp and the other one runs on widget.cpp. Thank you !
- widget.h
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QCamera> #include <QScopedPointer> #include <QCameraInfo> #include <QAction> #include <QCameraImageCapture> #include <QCameraViewfinder> #include <QPushButton> #include <QTimer> QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); void set_camera_action(QAction *camera_action); void set_camera(const QCameraInfo &camera_info); private: Ui::Widget *ui; void _setup_ui(); void _setup_camera_devices(); int idx{0}; QScopedPointer<QCamera> _camera; QScopedPointer<QCameraImageCapture> _image_capture; QCameraViewfinder *_camera_view; QWidget *_central_widget; QPushButton *_take_image_button; QPushButton *_take_image_button_timer; QPushButton *_turn_camera_on; QPushButton *_turn_camera_off; QTimer *timer; }; #endif // WIDGET_H- widget.cpp
#include "widget.h" #include "ui_widget.h" #include "LeptonThread.h" #include "MyLabel.h" #include <QDir> #include <QFile> #include <QMenuBar> #include <QMenu> #include <QActionGroup> #include <QVBoxLayout> #include <QImage> #include <QStandardPaths> #include <QDebug> #include <QVideoFrame> #include <QRandomGenerator> #include <QThread> Q_DECLARE_METATYPE(QCameraInfo) Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); _camera_view = new QCameraViewfinder(); _take_image_button_timer = new QPushButton("Take Timed Images"); _take_image_button = new QPushButton("Take Image"); _turn_camera_off = new QPushButton("Turn Off"); _turn_camera_on= new QPushButton("Turn On"); timer = new QTimer(this); _central_widget = new QWidget(); _central_widget->show(); _setup_ui(); set_camera(QCameraInfo::defaultCamera()); _image_capture->setCaptureDestination(QCameraImageCapture::CaptureToBuffer); connect(_take_image_button, &QPushButton::clicked, [this] { _image_capture.data()->capture(); }); connect(_turn_camera_off, &QPushButton::clicked, [this]{_camera.data()->stop(); timer->stop();}); connect(_turn_camera_on, &QPushButton::clicked, [this]{_camera.data()->start();}); connect(_take_image_button_timer, &QPushButton::clicked, [this] { for(int hh=0;hh<5;hh++) { QThread::sleep(2); _image_capture.data()->capture(); } //timer->start(1000); }); QObject::connect(_image_capture.data(), &QCameraImageCapture::imageCaptured, [=] (int id=0, QImage img) { idx=0; QString fileName = QString::number(idx) + ".png"; QString path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/" + fileName; while(QFile::exists(path)) { idx++; fileName = QString::number(idx) + ".png"; path = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation) + "/" + fileName; } qDebug() << "khrjt mn lboucle"; img.save(path, "PNG"); }); } void Widget::_setup_ui() { QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(_camera_view); layout->addWidget(_turn_camera_on); layout->addWidget(_turn_camera_off); layout->addWidget(_take_image_button); layout->addWidget(_take_image_button_timer); _central_widget->setLayout(layout); } void Widget::set_camera_action(QAction *camera_action) { set_camera(qvariant_cast<QCameraInfo>(camera_action->data())); } void Widget::set_camera(const QCameraInfo &camera_info) { _camera.reset(new QCamera(camera_info)); _image_capture.reset(new QCameraImageCapture(_camera.data())); _camera.data()->setCaptureMode(QCamera::CaptureStillImage); _camera.data()->setViewfinder(_camera_view); _camera.data()->start(); } Widget::~Widget() { delete ui; }- main.cpp
#include <QApplication> #include <QThread> #include <QMutex> #include <QMessageBox> #include <QColor> #include <QLabel> #include <QtDebug> #include <QString> #include <QPushButton> #include <QVBoxLayout> #include "widget.h" #include "ui_widget.h" #include "LeptonThread.h" #include "MyLabel.h" void printUsage(char *cmd) { char *cmdname = basename(cmd); printf("Usage: %s [OPTION]...\n" " -h display this help and exit\n" " -cm x select colormap\n" " 1 : rainbow\n" " 2 : grayscale\n" " 3 : ironblack [default]\n" " -tl x select type of Lepton\n" " 2 : Lepton 2.x [default]\n" " 3 : Lepton 3.x\n" " [for your reference] Please use nice command\n" " e.g. sudo nice -n 0 ./%s -tl 3\n" " -ss x SPI bus speed [MHz] (10 - 30)\n" " 20 : 20MHz [default]\n" " -min x override minimum value for scaling (0 - 65535)\n" " [default] automatic scaling range adjustment\n" " e.g. -min 30000\n" " -max x override maximum value for scaling (0 - 65535)\n" " [default] automatic scaling range adjustment\n" " e.g. -max 32000\n" " -d x log level (0-255)\n" "", cmdname, cmdname); return; } int LeptonThread::snapshotCount =0; int main( int argc, char **argv ) { int typeColormap = 3; // colormap_ironblack int typeLepton = 2; // Lepton 2.x int spiSpeed = 20; // SPI bus speed 20MHz int rangeMin = -1; // int rangeMax = -1; // int loglevel = 0; for(int i=1; i < argc; i++) { if (strcmp(argv[i], "-h") == 0) { printUsage(argv[0]); exit(0); } else if (strcmp(argv[i], "-d") == 0) { int val = 3; if ((i + 1 != argc) && (strncmp(argv[i + 1], "-", 1) != 0)) { val = std::atoi(argv[i + 1]); i++; } if (0 <= val) { loglevel = val & 0xFF; } } else if ((strcmp(argv[i], "-cm") == 0) && (i + 1 != argc)) { int val = std::atoi(argv[i + 1]); if ((val == 1) || (val == 2)) { typeColormap = val; i++; } } else if ((strcmp(argv[i], "-tl") == 0) && (i + 1 != argc)) { int val = std::atoi(argv[i + 1]); if (val == 3) { typeLepton = val; i++; } } else if ((strcmp(argv[i], "-ss") == 0) && (i + 1 != argc)) { int val = std::atoi(argv[i + 1]); if ((10 <= val) && (val <= 30)) { spiSpeed = val; i++; } } else if ((strcmp(argv[i], "-min") == 0) && (i + 1 != argc)) { int val = std::atoi(argv[i + 1]); if ((0 <= val) && (val <= 65535)) { rangeMin = val; i++; } } else if ((strcmp(argv[i], "-max") == 0) && (i + 1 != argc)) { int val = std::atoi(argv[i + 1]); if ((0 <= val) && (val <= 65535)) { rangeMax = val; i++; } } } //create the app QApplication a( argc, argv ); QWidget *myWidget = new QWidget; myWidget->setGeometry(400, 300, 340, 290); //create an image placeholder for myLabel //fill the top left corner with red, just bcuz QImage myImage; myImage = QImage(320, 240, QImage::Format_RGB888); QRgb red = qRgb(255,0,0); for(int i=0;i<80;i++) { for(int j=0;j<60;j++) { myImage.setPixel(i, j, red); } } //create a label, and set it's image to the placeholder MyLabel myLabel(myWidget); myLabel.setGeometry(10, 10, 320, 240); myLabel.setPixmap(QPixmap::fromImage(myImage)); //create a FFC button QPushButton *button1 = new QPushButton("Perform FFC", myWidget); button1->setGeometry(580/2-50, 290-35, 100, 30); //create a capture button QPushButton *button2 = new QPushButton("Capture", myWidget); button2->setGeometry(100/2-50, 290-35, 100, 30); //create a thread to gather SPI data //when the thread emits updateImage, the label should update its image accordingly LeptonThread *thread = new LeptonThread(); thread->setLogLevel(loglevel); thread->useColormap(typeColormap); thread->useLepton(typeLepton); thread->useSpiSpeedMhz(spiSpeed); thread->setAutomaticScalingRange(); if (0 <= rangeMin) thread->useRangeMinValue(rangeMin); if (0 <= rangeMax) thread->useRangeMaxValue(rangeMax); QObject::connect(thread, SIGNAL(updateImage(QImage)), &myLabel, SLOT(setImage(QImage))); //connect ffc button to the thread's ffc action QObject::connect(button1, SIGNAL(clicked()), thread, SLOT(performFFC())); thread->start(); //connect capture button to the thread's capture action QObject::connect(button2, SIGNAL(clicked()), thread, SLOT(Capture())); myWidget->show(); Widget w; w.show(); return a.exec(); } -
Hi!
Maybe you can turn one program into a class that you use in the other
And let the program handle the output from the class using SIGNALS and SLOTS. -
Hi!
Maybe you can turn one program into a class that you use in the other
And let the program handle the output from the class using SIGNALS and SLOTS.@posktomten Thank you for your answer, actually i'm pretty new to Qt programming so can you please tell me how to do that exactly ? or can you give me an example so i can see how it works exactly.
-
In Qt Creator: "File", "New File ...", select "C / C ++" and "C ++ class"
You get an h-file and a cpp file.The program and the class can communicate through SIGNALS and SLOTS
Example:
In the Program// in h file public slots: void getValue (const QString & string); // in cpp file // Declares an object of class MyClass MyClass *mMyClass; // Create contact connect (mMyClass, & MyClass::a_signal, this, & mMyProgram::setValue); // Receives what the class sends void MyProgram::getValue(QString *content) { // Do something }In the class
//In h file signals: // Declares a signal void a_signal (QString); // In cpp file // Sends a signal emit a_signal (QString ("Hello!"));Hope you get some inspiration!
-
In Qt Creator: "File", "New File ...", select "C / C ++" and "C ++ class"
You get an h-file and a cpp file.The program and the class can communicate through SIGNALS and SLOTS
Example:
In the Program// in h file public slots: void getValue (const QString & string); // in cpp file // Declares an object of class MyClass MyClass *mMyClass; // Create contact connect (mMyClass, & MyClass::a_signal, this, & mMyProgram::setValue); // Receives what the class sends void MyProgram::getValue(QString *content) { // Do something }In the class
//In h file signals: // Declares a signal void a_signal (QString); // In cpp file // Sends a signal emit a_signal (QString ("Hello!"));Hope you get some inspiration!
@posktomten Thank you sir for your help i'll try to get this working !
-
I have clarified my example a bit.
-
Hi,
You don't need combine two classes in a single one.
In fact it depends on how you implemented both widgets originally. If they work the same way, you can simply create two objects, one for each camera and configure them properly rather than duplicate code.
-
Just! or perhaps have two classes that inherit common characteristics from a parent class.