Signals and slots or whatever
-
Hello everyone, I am a complete noob at Qt with 2 semesters of C++ under my belt. I am stuck with the task of editing someone else's QT code so that I can monitor a certain value.
There is an 'int' in a class and I have created a textBrowser so that I can have the value of this 'int' constantly displayed while the program is in use.
In the past week I have watched every signal and slot video on the web, I have tried every combination of code I could come up with. I have tried making a global variable. I have even tried accessing the Mainwindow from this other class which many forums say is "bad programming". I just want to have this program display the value of the integer so that I can move on with my work assignment.
If anyone can help me please, I have been going in circles.
I would try to show my code but there are thousands of lines of code and I don't know what you would need to see.Also, just to let you all know, I have no problem with data types. I understand that the int must be changed to QString. My Problem is really just trying to get a value from one class to fill the textBroswer in the Mainwindow.cpp
Thank You
-
There is an 'int' in a class and I have created
Something like the below?
class ValueClass : public QObject { Q_OBJECT Q_DISABLE_COPY(ValueClass) public: explicit ValueClass(QObject* parent = Q_NULLPTR) :QObject(parent) ,m_value(0) {} int value() const { return m_value; } void setValue(int val) { if (val != m_value){ m_value = val; valueChanged(m_value); } } signals: void valueChanged(int); private: int m_value; };
-
Here is a snippet from the class file:
cccmodule.cpp
void CccModule::paramChange() { int i; QVariant val; char id[128]; uint32_t sigLen; uint8_t *sigData; QByteArray ba; bool setPalette; //Maybe something to do with signatures // check to see if any signatures have changed for (i=0, setPalette=false; i<CL_NUM_SIGNATURES; i++) { sprintf(id, "signature%d", i+1); if (pixyParameterChanged(id, &val)) { ba = val.toByteArray(); Chirp::deserialize((uint8_t *)ba.data(), val.toByteArray().size(), &sigLen, &sigData, END); if (sigLen==sizeof(ColorSignature)) { memcpy(m_signatures+i, sigData, sizeof(ColorSignature)); m_palette[i] = m_signatures[i].m_rgb; //I want to send m_palette[i] //to the textBrowser in the Mainwindow QString print = "HINT("; setPalette = true; } } } if (setPalette) m_renderer->setPalette(m_palette); // create label dictionary Parameters ¶ms = m_interpreter->m_pixyParameters.parameters(); QStringList words; uint32_t signum; m_labels.clear(); // go through all parameters and find labels for (i=0; i<params.length(); i++) { if (params[i].id().startsWith("Signature label")) { words = params[i].id().split(QRegExp("\\s+")); if (words.length()<3) // bogus! continue; signum = words[2].toUInt(); m_labels.push_back(QPair<uint16_t, QString>(convert10to8(signum), params[i].value().toString().remove(QRegExp("^\\s+")))); // remove leading whitespace } } }
-
- inside the declaration of
CccModule
, in the public section, addQ_SIGNAL void paletteChanged(int index, uint32_t palette);
- replace
m_palette[i] = m_signatures[i].m_rgb;
with
if(m_palette[i] != m_signatures[i].m_rgb){ m_palette[i] = m_signatures[i].m_rgb; paletteChanged(i,m_palette[i]); }
- connect the
CccModule::paletteChanged
signal with a slot inMainwindow
that updates thetextBrowser
- inside the declaration of
-
@jrod2much said in Signals and slots or whatever:
how would the connect look like
-
I'm pretty sure that I declared it correctly but I am getting back:
119:13: error: use of undeclared identifier 'cModule'
and now I'm getting back:
mainwindow.cpp:123: error: no matching function for call to 'MainWindow::connect(CccModule*&, void (CccModule::*)(int, uint32_t), MainWindow* const, MainWindow::MainWindow(int, char**, QWidget*)::__lambda0)' }); ^ mainwindow.cpp:123: error: template argument for 'template<class Func1, class Func2> static QMetaObject::Connection QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const typename QtPrivate::FunctionPointer<Func2>::Object*, Func2, Qt::ConnectionType)' uses local type 'MainWindow::MainWindow(int, char**, QWidget*)::__lambda0' }); ^ mainwindow.cpp:123: error: template argument for 'template<class Func1, class Func2> static typename QtPrivate::QEnableIf<(((int)(QtPrivate::FunctionPointer<Func2>::ArgumentCount) >= 0) && (! QtPrivate::FunctionPointer<Func2>::IsPointerToMemberFunction)), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const QObject*, Func2, Qt::ConnectionType)' uses local type 'MainWindow::MainWindow(int, char**, QWidget*)::__lambda0' }); ^ mainwindow.cpp:123: error: template argument for 'template<class Func1, class Func2> static typename QtPrivate::QEnableIf<(QtPrivate::FunctionPointer<Func2>::ArgumentCount == (-1)), QMetaObject::Connection>::Type QObject::connect(const typename QtPrivate::FunctionPointer<Func>::Object*, Func1, const QObject*, Func2, Qt::ConnectionType)' uses local type 'MainWindow::MainWindow(int, char**, QWidget*)::__lambda0' }); ^
-
@jrod2much said in Signals and slots or whatever:
use of undeclared identifier 'cModule'
yes, that's just a name I used, you have to change it to the one of your instance of
CccModule
@jrod2much said in Signals and slots or whatever:
and now I'm getting back:
mainwindow.cpp:123: error: no matching function for call to 'MainWindow::connect(CccModule*&, void (CccModule::)(int, uint32_t), MainWindow const[edit, it was just bad formatting by the forum]MainWindow const
? how are you passing the 3rd argument?You are calling the connect from a
const
method. That's a problem as a connection alters the objects -
I really apologize for having to ask these kinds of questions, but, how do I check what "my instance of CccModule" are. I added this in above the connect and in the header of CccModule.cpp in public:
CccModule* cModule;
Also, I don't know how to fix the const issue.
-
No, I do not use CccModule anywhere else in the Mainwindow.
I put the connect in the Mainwindow.cpp
MainWindow::MainWindow(int argc, char *argv[], QWidget *parent) : QMainWindow(parent), m_ui(new Ui::MainWindow) { QCoreApplication::setOrganizationName(PIXYMON_COMPANY); QCoreApplication::setApplicationName(PIXYMON_TITLE); qRegisterMetaType<Device>("Device"); m_ui->setupUi(this); setWindowTitle(PIXYMON_TITLE); m_interpreter = NULL; m_flash = NULL; m_pixyConnected = false; m_pixyDFUConnected = false; m_configDialog = NULL; m_fwInstructions = NULL; m_fwMessage = NULL; m_versionIncompatibility = false; m_testCycle = false; m_waiting = WAIT_NONE; parseCommandline(argc, argv); m_settings = new QSettings(QSettings::NativeFormat, QSettings::UserScope, PIXYMON_COMPANY, PIXYMON_TITLE); m_console = new ConsoleWidget(this); m_video = new VideoWidget(this); m_ui->imageLayout->addWidget(m_video); m_ui->imageLayout->addWidget(m_console); // hide console m_showConsole = m_testCycle; m_console->setVisible(m_testCycle); m_ui->actionConsole->setChecked(m_testCycle); m_ui->toolBar->addAction(m_ui->actionPlay_Pause); m_ui->actionDefault_program->setIcon(QIcon(":/icons/icons/home.png")); m_ui->toolBar->addAction(m_ui->actionDefault_program); m_ui->actionRaw_video->setIcon(QIcon(":/icons/icons/raw.png")); m_ui->toolBar->addAction(m_ui->actionRaw_video); m_ui->actionConfigure->setIcon(QIcon(":/icons/icons/config.png")); m_ui->toolBar->addAction(m_ui->actionConfigure); m_ui->menuProgram->setToolTipsVisible(true); m_status = new QLabel; // give the status a little of a left margin m_ui->statusBar->setContentsMargins(6, 0, 0, 0); m_ui->statusBar->addPermanentWidget(m_status, 1); updateButtons(); m_parameters.add("Pixy start command", PT_STRING, "", "The command that is sent to Pixy upon initialization"); // start looking for devices m_connect = new ConnectEvent(this); if (m_connect->getConnected()==NONE) error("No Pixy devices have been detected.\n"); connect(cModule, &CccModule::paletteChanged, this, [=](int index, uint32_t palette)->void{ m_ui->textBrowser->append(QStringLiteral("Palette changed. Index %1, Palette: %2").arg(index).arg(palette)); }); } MainWindow::~MainWindow() { if (m_connect) delete m_connect; DBG("deleting mainWindow"); // we don't delete any of the widgets because the parent deletes it's children upon deletion delete m_settings; }
-
@jrod2much said in Signals and slots or whatever:
I put the connect in the Mainwindow.cpp
Ok, this is correct
I do not use CccModule anywhere else in the Mainwindow.
So where are you using that class?
-
So here is the entire CccModule.cpp source file:
#include <QPainter> #include <QString> #include <stdio.h> #include "cccmodule.h" #include "interpreter.h" #include "renderer.h" #include "qqueue.h" #include "colorlut.h" #include "calc.h" // declare module MON_MODULE(CccModule); CccModule::CccModule(Interpreter *interpreter) : MonModule(interpreter) { int i; m_crc = 0; m_qvals = new uint32_t[0x8000]; m_numQvals = 0; for (i=0; i<CL_NUM_SIGNATURES; i++) m_palette[i] = Qt::black; } CccModule::~CccModule() { delete [] m_qvals; } bool CccModule::render(uint32_t fourcc, const void *args[]) { if (fourcc==FOURCC('C', 'C', 'B', '1')) { renderCCB1(*(uint8_t *)args[0], *(uint16_t *)args[1], *(uint32_t *)args[2], *(uint32_t *)args[3], (uint8_t *)args[4]); return true; } else if (fourcc==FOURCC('C', 'C', 'B', '2')) { renderCCB2(*(uint8_t *)args[0], *(uint16_t *)args[1], *(uint32_t *)args[2], *(uint32_t *)args[3], (uint16_t *)args[4], *(uint32_t *)args[5], (uint16_t *)args[6]); return true; } else if (fourcc==FOURCC('C','C','Q','F')) { renderCCQF(*(uint8_t *)args[0], *(uint16_t *)args[1], *(uint16_t *)args[2]); return true; } else if (fourcc==FOURCC('C','C','Q','S')) { renderCCQS(*(uint32_t *)args[0], (uint32_t *)args[1]); return true; } return false; } bool CccModule::command(const QStringList &argv) { return false; } uint16_t convert10to8(uint32_t signum) { uint16_t res=0; uint32_t q; q = signum/10000; if (q) { res += q*8*8*8*8; signum -= q*10000; } q = signum/1000; if (q) { res += q*8*8*8; signum -= q*1000; } q = signum/100; if (q) { res += q*8*8; signum -= q*100; } q = signum/10; if (q) { res += q*8; signum -= q*10; } if (signum) res += signum; return res; } void CccModule::paramChange() { CccModule* cModule QString m_paletteOne; int i; QVariant val; char id[128]; uint32_t sigLen; uint8_t *sigData; QByteArray ba; bool setPalette; //Maybe something to do with signatures // check to see if any signatures have changed for (i=0, setPalette=false; i<CL_NUM_SIGNATURES; i++) { sprintf(id, "signature%d", i+1); if (pixyParameterChanged(id, &val)) { ba = val.toByteArray(); Chirp::deserialize((uint8_t *)ba.data(), val.toByteArray().size(), &sigLen, &sigData, END); if (sigLen==sizeof(ColorSignature)) { memcpy(m_signatures+i, sigData, sizeof(ColorSignature)); //m_palette[i] = m_signatures[i].m_rgb; //THIS IS THE CODE YOU HAD ME INSERT if(m_palette[i] != m_signatures[i].m_rgb) { m_palette[i] = m_signatures[i].m_rgb; m_paletteOne = QString::number(m_signatures[i].m_rgb); paletteChanged(i,m_palette[i]); } //I want to send m_palette[i] //to the textBrowser in the Mainwindow QString print = "HINT("; setPalette = true; } } } if (setPalette) m_renderer->setPalette(m_palette); // create label dictionary Parameters ¶ms = m_interpreter->m_pixyParameters.parameters(); QStringList words; uint32_t signum; m_labels.clear(); // go through all parameters and find labels for (i=0; i<params.length(); i++) { if (params[i].id().startsWith("Signature label")) { words = params[i].id().split(QRegExp("\\s+")); if (words.length()<3) // bogus! continue; signum = words[2].toUInt(); m_labels.push_back(QPair<uint16_t, QString>(convert10to8(signum), params[i].value().toString().remove(QRegExp("^\\s+")))); // remove leading whitespace } } } QString CccModule::lookup(uint16_t signum) { int i; for (i=0; i<m_labels.length(); i++) { if (m_labels[i].first==signum) return m_labels[i].second; } return ""; } void CccModule::renderCCQF(uint8_t renderFlags, uint16_t width, uint16_t height) { if (renderFlags&RENDER_FLAG_START) m_numQvals = 0; else m_renderer->renderCCQ1(renderFlags, width, height, m_numQvals, m_qvals); } void CccModule::renderCCQS(uint32_t numVals, uint32_t *vals) { uint32_t i; for (i=0; i<numVals && m_numQvals<0x8000; i++) m_qvals[m_numQvals++] = vals[i]; } int CccModule::renderCCB1(uint8_t renderFlags, uint16_t width, uint16_t height, uint32_t numBlobs, uint8_t *blobs) { float scale = (float)m_renderer->m_video->activeWidth()/width; QImage img(width*scale, height*scale, QImage::Format_ARGB32); if (renderFlags&RENDER_FLAG_BLEND) // if we're blending, we should be transparent img.fill(0x00000000); else img.fill(0xff000000); // otherwise, we're just black numBlobs /= sizeof(BlobC); renderBlobsC(renderFlags&RENDER_FLAG_BLEND, &img, scale, (BlobC *)blobs, numBlobs); m_renderer->emitImage(img, renderFlags, "CCC Blobs"); return 0; } int CccModule::renderCCB2(uint8_t renderFlags, uint16_t width, uint16_t height, uint32_t numBlobs, uint16_t *blobs, uint32_t numCCBlobs, uint16_t *ccBlobs) { float scale = (float)m_renderer->m_video->activeWidth()/width; QImage img(width*scale, height*scale, QImage::Format_ARGB32); if (renderFlags&RENDER_FLAG_BLEND) // if we're blending, we should be transparent img.fill(0x00000000); else img.fill(0xff000000); // otherwise, we're just black numBlobs /= sizeof(BlobA2)/sizeof(uint16_t); numCCBlobs /= sizeof(BlobA2)/sizeof(uint16_t); renderBlobsA(renderFlags&RENDER_FLAG_BLEND, &img, scale, (BlobA2 *)blobs, numBlobs); renderBlobsA(renderFlags&RENDER_FLAG_BLEND, &img, scale, (BlobA2 *)ccBlobs, numCCBlobs); m_renderer->emitImage(img, renderFlags, "CCC Blobs"); return 0; } void CccModule::renderBlobsA(bool blend, QImage *image, float scale, BlobA2 *blobs, uint32_t numBlobs) { QPainter p; QString str, modelStr; uint x, y, w, h, i; p.begin(image); for (i=0; i<numBlobs; i++) { if (blobs[i].m_model==0) continue; x = scale*blobs[i].m_left; y = scale*blobs[i].m_top; w = scale*blobs[i].m_right - x; h = scale*blobs[i].m_bottom - y; //DBG("%d %d %d %d", left, right, top, bottom); if (blend || blobs[i].m_model>CL_NUM_SIGNATURES+1) Renderer::drawRect(&p, QRect(x, y, w, h), QColor(Qt::white), 0x40); else Renderer::drawRect(&p, QRect(x, y, w, h), m_palette[blobs[i].m_model-1], 0xff); // color code if (blobs[i].m_model>CL_NUM_SIGNATURES+1) { if ((str=lookup(blobs[i].m_model))=="") { modelStr = QString::number(blobs[i].m_model, 8); str = "s=" + modelStr + ", " + QChar(0xa6, 0x03) + "=" + "0";//QString::number(blobs[i].m_angle); } else str += QString(", ") + QChar(0xa6, 0x03) + "=" + "0"; //QString::number(blobs[i].m_angle); } else if ((str=lookup(blobs[i].m_model))=="") str = str.sprintf("s=%d", blobs[i].m_model); Renderer::drawText(&p, x+w/2, y+h/2, str); } p.end(); } void CccModule::renderBlobsC(bool blend, QImage *image, float scale, BlobC *blobs, uint32_t numBlobs) { QPainter p; QString str, modelStr; uint x, y, w, h, i; p.begin(image); for (i=0; i<numBlobs; i++) { if (blobs[i].m_model==0) continue; w = scale*blobs[i].m_width; h = scale*blobs[i].m_height; x = scale*blobs[i].m_x-w/2; y = scale*blobs[i].m_y-h/2; //DBG("%d %d %d %d", left, right, top, bottom); if (blend || blobs[i].m_model>CL_NUM_SIGNATURES+1) Renderer::drawRect(&p, QRect(x, y, w, h), QColor(Qt::white), 0x40); else Renderer::drawRect(&p, QRect(x, y, w, h), m_palette[blobs[i].m_model-1], 0xff); // color code if (blobs[i].m_model>CL_NUM_SIGNATURES+1) { if ((str=lookup(blobs[i].m_model))=="") { modelStr = QString::number(blobs[i].m_model, 8); str = "s=" + modelStr + ", " + QChar(0xa6, 0x03) + "=" + QString::number(blobs[i].m_angle); } else str += QString(", ") + QChar(0xa6, 0x03) + "=" + QString::number(blobs[i].m_angle); } else if ((str=lookup(blobs[i].m_model))=="") str = str.sprintf("s=%d", blobs[i].m_model); Renderer::drawText(&p, x+w/2, y+h/2, str); } p.end(); }
If I search the entire project, 'CccModule' only comes up in this file and its header.
-
Welcome to my world haha. I don't know how it changes, but it does because I set a printf statement to print it every time the program runs through that section of code and it changes.
Can't we just make it emit the value? I'm not sure I understand anything about the emit function but it sounds like it might work.
-
@jrod2much
ok, you'll need to know whereCccModule
is instantiated, for you be able to listen/connect to signals that are emitted.Do you know where that happens? If not and, you 're using QtCreator, you can simply right-click on the constructor and click on
find uses
that will list all places where the an instance of that class is created, even when it's done in aui
file.Than you can use QObject:connect to connect that instance with your textbrowser