I am trying to connect a button with a slot defined in an external class called simu. The slot is a function called startSimu(). The object simulation is instantiated in the same class where I hope to connect the button. Below is the code:
QPushButton *btn1 = new QPushButton("start simulation");
simu simulation;
QObject::connect(btn1, SIGNAL(clicked()), &simulation, SLOT(startSimu()));
The code compiles and runs, but when I click on the button nothing happens. The function startSimu() is the following:
void simu::startSimu() {
std::cout << "aaaa" << std::endl;
}
The header of the simu class:
#ifndef SIMU_H
#define SIMU_H
#include <QObject>
class simu : public QObject
{
Q_OBJECT
public:
simu();
double timer() {return time;}
public slots:
void startSimu();
private:
double time;
};
#endif // SIMU_H
I hope someone has a clue or a hint!
Thanks
It looks like your simulation object destroyed before the slot is called, because you allocated it in the stack:
simu simulation; // Will be destroyed as the execution leave the scope.
QObject::connect(btn1, SIGNAL(clicked()), &simulation, SLOT(startSimu()));
To fix this you will need probably do the following:
simu *simulation = new simu; // Will be destroyed soon
QObject::connect(btn1, SIGNAL(clicked()), simulation, SLOT(startSimu()));
Please do not forget to delete the simulation object when needed.
Related
I'd like a signal to be connected to a slot inside of a struct. My struct looks like:
//Header file
struct someStruct {
public:
int index;
public slots:
void someSlot();
};
QList<someStruct*> mListOfStructs;
and then I create a button that should forward its clicked() signal to the someSlot function.
//Source file
QPushButton *cmd = new QPushButton();
grd->addWidget(cmd, 3, 2, Qt::AlignCenter);
//grd is a QGridLayout somewhere inside the gui. I can see it and also the button.
now connection the clicked() event with the slot inside a specific struct does not work.
connect(cmd, SIGNAL(clicked()), mListOfStructs[3], SLOT(someSlot()));
some sources tell me that I have to add a metaObject or sth. I tried but it didn't work out. Maybe you know better.
I might use How to connect in Qt signal and slot in dynamically added buttons to get in slot index of added button? as workaround though.
your structure need the Q_Object meta attributes in order to emit signals and recieve slot events...
struct testStruct : public QObject
{
Q_OBJECT
public:
int index;
testStruct():index(0){}
public slots:
void someSlot()
{
qDebug() << "slot called!";
}
};
after that you can conected as usual:
testStruct *ts= new testStruct;
connect(this, SIGNAL(someSignal()), ts, SLOT(someSlot()));
I am trying to put the data passed to a mainwindow.cpp function on the screen with the typical ui->control->setText(message) without success. The same line works if it is in a timer loop or a button function but not from display_that_data function
"MainWindow::display_that_data()" is called from myudp.cpp with the following lines
MainWindow show_tlm;
show_tlm.display_that_data(data_source, buf_copy);
mainwindow.cpp (updated to include emitting a signal for a SIGNAL/SLOT connection)
The SIGNAL/SLOT connection is set up in the constructor with the following line
connect (this, SIGNAL (showdata_signal()), this, SLOT(showdata_slot()));
void MainWindow::display_that_data(QByteArray data_source, QByteArray tlmBuf){
QString msg ;
msg = " in display_that_data";
qDebug() << msg ;
ui->tlm_vals->setText(msg);
//generate a signal which will trigger showdata_slot
emit showdata_signal();
msg = " in display_that_data after emit showdata_signal()";
qDebug() << msg ;
}
void MainWindow::showdata_slot() {
QString msg = "showdata_slot called";
qDebug() << msg ;
ui->tlm_vals->setText(msg);
}
Runtime debug messages show that code is making it to the showdata_slot but it is still not writing to the ui->tlm_vals
" in display_that_data"
"showdata_slot called"
" in display_that_data after emit showdata_signal()"
but.... neither one of the ui->tlm_vals->setText(msg) lines are putting text on the ui
"MainWindow::realtimeDataSlot()" is called by at timer timout signal as follows:
void MainWindow::setupRealtimeDataDemo(QCustomPlot *customPlot) {
// setup a timer that repeatedly calls MainWindow::realtimeDataSlot
connect(&dataTimer, SIGNAL(timeout()), this, SLOT(realtimeDataSlot()));
dataTimer.start(1000);
}
void MainWindow::realtimeDataSlot(){
QString temp = QString("%1").arg(epochTime, 10, 10, QChar('0'));
ui->tlm_vals->setText(temp);
}
And this works perfectly (of course I have to disable it to see if showdata_slot is writing to the ui)
I thought the problem was a needed SIGNAL and SLOT connection to trigger the write to the ui but generating a SIGNAL/SLOT connection (which debug shows as working) still does not write to the ui from the slot function.
For completeness mainwindow.h contains the following
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void setupRealtimeDataDemo(QCustomPlot *customPlot);
void display_that_data (QByteArray data_source, QByteArray tlmBuf);
private slots:
void realtimeDataSlot();
void showdata_slot();
private:
Ui::MainWindow *ui;
QTimer dataTimer;
What am I missing/doing wrong?
Somewhere deeply embedded in Qt there is a difference between gui mouse click generated event and code generated event and this somehow caues Qt behavior to vary with the same lines of code. I will repost a more more "root level" question on this topic.
I want to make a program in Qt to add points one by one, not all at once. To do that, I need to use QThread, or I can just use QTimer?
it can be done using QTimer and if it is time dependent (like every 1 second) then its the way to go. just create the timer, connect its timeout signal to your slot and it should work like a charm
You need create some class, inherited from QObject:
class QTimer;
class QList;
class Test_Timer : public QObject
{
Q_OBJECT
public:
explicit Test_Timer(QObject *parent = 0);
~Test_Timer();
private:
QList<QPoint> *lst;
QTimer *timer;
public slots:
void addPoint();
};
Ok, now we have timer variable for QTimer events, lst for store QPoint and addPoint() slot for handling your timer event.
At constructor we initialize members of class, connect timer's slot with current class slot and start timer with period 500ms:
Test_Timer::Test_Timer(QObject *parent) : QObject(parent)
{
lst = new QList<QPoint>;
timer = new QTimer;
connect(timer, SIGNAL(timeout()), this, SLOT(addPoint()));
timer->start(500);
}
Slot for adding points may look something like this:
void Test_Timer::addPoint()
{
static int number = 0;
if (lst->size() < 10) {
lst->append(QPoint(0, number++));
qDebug() << lst->size();
} else {
timer->stop();
deleteLater();
}
}
After all don't remember free resources:
Test_Timer::~Test_Timer()
{
lst->clear();
delete lst;
if (timer->isActive())
timer->stop();
delete timer;
}
I think this example will be helpful for you.
I'm writing a Qt Application in C++. I have a QRunnable running in a QThreadPool, and it sends a signal to the main thread. The problem is, the connection doesn't work: the signal is never received by the main thread, even though I've verified that the code doing the emit is indeed called. Here is my code:
My QRunnable class:
class OfflineAnalysisThread : public QObject, public QRunnable
{
Q_OBJECT
public:
void run();
void sendMessage(QString &qmsg)
{
emit threadMessageCallback(qmsg);
}
signals:
void threadMessageCallback(QString &string);
};
And the calling class (main thread):
class OfflineAnalysisMain : public QObject
{
Q_OBJECT
public:
(...)
public slots:
void threadMsg(QString &string);
};
The code that instantiates the new QRunnables and starts them:
void OfflineAnalysisMain::myFunction()
{
OfflineAnalysisThread *newTask = new OfflineAnalysisThread();
QObject::connect(newTask, SIGNAL(threadMessageCallback(QString &)), this, SLOT(threadMsg(QString &)));
QThreadPool::globalInstance()->start(newTask);
}
So, from my QRunnable's run function, I call sendMessage and then I do QApplication::exec(). I have a breakpoint on the threadMsg slot implementation in OfflineAnalysisMain.cpp, and that function is never called.
What am I doing wrong?
UPDATE:
Definition of my OfflineAnalysisThread::run() function:
void OfflineAnalysisThread::run()
{
std::string myMsg("This is my message");
sendMessage(myMsg);
QApplication::exec();
}
I have also tried without the QApplication::exec();, without success.
Remove the call to QApplication::exec() from within run(). This is ideally called from within your main function.
In order to get your code to work, I had to write the following main function:
#include <QApplication>
#include <QMetaType>
#include <offlineanalysismain.h>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
qRegisterMetaType<QString>("QString&");
OfflineAnalysisMain* main = new OfflineAnalysisMain;
main->myFunction();
return app.exec();
}
Note the call to qRegisterMetaType, which allows Qt to pass a QString through a signal-slot connection that cross thread boundaries.
Sorry for the bulky title.
I have a class containing a QListWidget.
I connected it's itemSelectionChanged() signal to a custom slot.
When I call QListWidget::clear(), the slot gets called (as expected) but a call to QListWidget::count() in this slot returns the number of items the QListWidget had before.
A call to count() right after the call to clear() (when the signal was processed as described) returns the correct number 0.
I prepared a complete demo project. Most important is this source file:
#include "ListWidgetTest.hpp"
#include "ui_ListWidgetTest.h"
#include <QDebug>
ListWidgetTest::ListWidgetTest(QWidget* parent)
: QWidget(parent), ui(new Ui::ListWidgetTest)
{
ui->setupUi(this);
for (int i = 0; i < 5; ++i) {
QListWidgetItem* item = new QListWidgetItem(QString("Item %1").arg(i));
ui->listWidget->addItem(item);
}
QObject::connect(ui->pushButton, SIGNAL(clicked()),
this, SLOT(clearList()));
QObject::connect(ui->listWidget, SIGNAL(itemSelectionChanged()),
this, SLOT(selectionChanged()));
}
ListWidgetTest::~ListWidgetTest()
{
delete ui;
}
void ListWidgetTest::clearList()
{
qDebug() << "void ListWidgetTest::clearList()";
ui->listWidget->clear();
qDebug() << "clearList: ui->listWidget->count() is " << ui->listWidget->count();
}
void ListWidgetTest::selectionChanged()
{
qDebug() << "void ListWidgetTest::selectionChanged()";
qDebug() << "selectionChanged: ui->listWidget->count() is " << ui->listWidget->count();
}
Output
void ListWidgetTest::clearList()
void ListWidgetTest::selectionChanged()
selectionChanged: ui->listWidget->count() is 5
clearList: ui->listWidget->count() is 0
What happens
The list gets populated.
Every click on an item calls selectionChanged()
A click on the button calls clearList()
The call to QListWidget::clear() also emits the signal and the slot gets called
The number of items has not changed yet
You can add "Qt::QueuedConnection" to both of QObject::connection. Like:
connect(ui->pushButton, SIGNAL(clicked()),
this, SLOT(clearList()), Qt::QueuedConnection);
connect(ui->listWidget, SIGNAL(itemSelectionChanged()),
this, SLOT(selectionChanged()), Qt::QueuedConnection);
It is works. But sorry I don't know why. Maybe queued connection method can solve multi-signal order problem.
First of all QListWidget::clear() is a SLOT and not a SIGNAL. So obviously it is not emitting/triggering the signal itemSelectionChanged().
You might be accidentally triggering this itemSelectionChanged() just before calling clear(). Check whether you are triggering itemchanged() or selectionchanged() or any other events that trigger itemSelectionChanged() before calling clear().
One possible solution is to declare a custom signal and emit this signal just
after calling clear(). And connect it to the custom slot you have defined.You
will get the expected value in your SLOT