This code creates a thread and connect it to MainWindow in QT.
void UI_handling::create_thread_for_looping_terminal(){
loop_terminal_thread = new Loop_terminal_thread(mainWindow, &j1939);
loop_terminal_thread->start();
mainWindow->connect(loop_terminal_thread, &Loop_terminal_thread::send_ID_and_data_to_looping_terminal, mainWindow, &MainWindow::update_looping_teriminal);
}
This code gives error on ->connect part due to mainWindow argument.
If I would run this code inside the MainWindow class, it would look like this. It will work fine, but as you can see, mainWindow is the issue here.
connect(loop_terminal_thread, &Loop_terminal_thread::send_ID_and_data_to_looping_terminal, this, &MainWindow::update_looping_teriminal);
So why is mainWindow the issue if I have a constructor that look like this
UI_handling::UI_handling(QMainWindow* mainWindow, Ui::MainWindow* ui) : mainWindow(mainWindow), ui(ui){
}
And I call the UI_handling constructor inside the MainWindow class
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow){
ui->setupUi(this);
/* Important handler */
ui_handling = new UI_handling(this, ui);
So why does the argument this, causing so I don't get right argument?
The error is:
ui_handling.cpp:119:17: error: no matching member function for call to 'connect'
qobject.h:242:43: note: candidate function [with Func1 = void (Loop_terminal_thread::*)(unsigned int, unsigned char *), Func2 = void (MainWindow::*)(unsigned int, unsigned char *)] not viable: cannot convert from base class pointer 'QMainWindow *' to derived class pointer 'const typename QtPrivate::FunctionPointer<void (MainWindow::*)(unsigned int, unsigned char *)>::Object *' (aka 'const MainWindow *') for 3rd argument
qobject.h:222:36: note: candidate function not viable: no known conversion from 'void (Loop_terminal_thread::*)(uint32_t, uint8_t *)' to 'const char *' for 2nd argument
qobject.h:225:36: note: candidate function not viable: no known conversion from 'void (Loop_terminal_thread::*)(uint32_t, uint8_t *)' to 'const QMetaMethod' for 2nd argument
qobject.h:481:41: note: candidate function not viable: no known conversion from 'void (Loop_terminal_thread::*)(uint32_t, uint8_t *)' to 'const char *' for 2nd argument
qobject.h:283:13: note: candidate template ignored: requirement '!QtPrivate::FunctionPointer<void (MainWindow::*)(unsigned int, unsigned char *)>::IsPointerToMemberFunction' was not satisfied [with Func1 = void (Loop_terminal_thread::*)(unsigned int, unsigned char *), Func2 = void (MainWindow::*)(unsigned int, unsigned char *)]
qobject.h:322:13: note: candidate template ignored: requirement 'QtPrivate::FunctionPointer<void (MainWindow::*)(unsigned int, unsigned char *)>::ArgumentCount == -1' was not satisfied [with Func1 = void (Loop_terminal_thread::*)(unsigned int, unsigned char *), Func2 = void (MainWindow::*)(unsigned int, unsigned char *)]
qobject.h:274:13: note: candidate function template not viable: requires 3 arguments, but 4 were provided
qobject.h:314:13: note: candidate function template not viable: requires 3 arguments, but 4 were provided
Minimal example:
First you create the thread header
#ifndef LOOP_TERMINAL_THREAD_H
#define LOOP_TERMINAL_THREAD_H
#include <QThread>
#include <QObject>
class Loop_terminal_thread : public QThread {
Q_OBJECT
public:
Loop_terminal_thread(QObject *parent = nullptr);
signals:
void send_ID_and_data_to_looping_terminal(uint32_t ID, uint8_t data[]);
private:
bool* start_loop_terminal_thread;
void run();
};
#endif // LOOP_TERMINAL_THREAD_H
Then you create the thread source
#include "loop_terminal_thread.h"
Loop_terminal_thread::Loop_terminal_thread(QObject *parent) : QThread(parent) {
}
void Loop_terminal_thread::run(){
uint8_t data[8] = {0};
data[1] = 23;
while(1){
emit send_ID_and_data_to_looping_terminal(300, data);
msleep(1000);
}
}
Then you create the UI_handler class
/* QT includes */
#include "ui_mainwindow.h"
#include <QStandardItemModel>
#include <QIntValidator>
#include <QMainWindow>
/* Project includes */
#include "UI_threads/Loop_terminal_thread/loop_terminal_thread.h"
class UI_handling{
public:
UI_handling(QMainWindow* mainWindow, Ui::MainWindow* ui);
void create_thread_for_looping_terminal();
private:
QMainWindow* mainWindow;
Ui::MainWindow* ui;
/* Thread for the looping terminal */
Loop_terminal_thread* loop_terminal_thread;
};
#endif // UI_HANDLING_H
And you implement the counstructor and the function inside the source file.
UI_handling::UI_handling(QMainWindow* mainWindow, Ui::MainWindow* ui) : mainWindow(mainWindow), ui(ui){
}
void UI_handling::create_thread_for_looping_terminal(){
loop_terminal_thread = new Loop_terminal_thread(mainWindow, &j1939);
loop_terminal_thread->start();
mainWindow->connect(loop_terminal_thread, &Loop_terminal_thread::send_ID_and_data_to_looping_terminal, mainWindow, &MainWindow::update_looping_teriminal);
}
Then lastly you implement this inside your MainWindow constructor
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow){
ui->setupUi(this);
/* Important handler */
ui_handling = new UI_handling(this, ui);
ui_handling->create_thread_for_looping_terminal();
}
void MainWindow::update_looping_teriminal(uint32_t ID, uint8_t data[]){
}
The header file of MainWindow class look like this
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 update_looping_teriminal(uint32_t ID, uint8_t data[]);
The clue is in this part of the error message:
You are connecting to a slot in
MainWindowclass, therefore you need to provide a pointer toMainWindow. A pointer toQMainWindowis not enough.When you run your connect inside
MainWindowand passthis, then the type of this argument isMainWindowand it works.In order for your code to work you need to change
UI_handlingclass, so that it stores a pointer toMainWindowinstead ofQMainWindow.