error: static assertion failed: Signal and slot arguments are not compatible - qt

I am getting this error with connect function
QTimer timer;
QObject::connect(&timer, &QTimer::timeout,this, &MainWindow::draw);
timer.start(1000);
both timeout and draw are predefined functions.
How can I solve this?
Even If I use a different function like
Sprite *sprite = new Sprite(this);
QTimer timer;
QObject::connect(&timer, &QTimer::timeout,sprite, &Sprite::drawNextBall);
timer.start(1000);
void Sprite::drawNextBall(QPainter &painter)
{
qDebug() <<"Sprite::drawNextBall() called";
painter.drawEllipse(x, y, 15, 15);
}

As stated by the error message, signal and slot arguments should match. This is definitely not the case in your example as QTimer::timeout has not a QPainter& as its first argument:
The signature of a signal must match the signature of the receiving slot. (In fact a slot may have a shorter signature than the signal it receives because it can ignore extra arguments.) [1]
Secondly, QPainter should only be used to draw on a QWidget inside a QWidget::paintEvent:
Warning: When the paintdevice is a widget, QPainter can only be used inside a paintEvent() function or in a function called by paintEvent(). [2]
What you probably want is connecting the QTimer::timeout signal to the QWidget::update (MainWindow::update or Sprite::update).
Relevant reading material
Signals & Slots
QPainter - Detailed description

Related

How to fix "In Qt two timer to one function, use qmutex will qeventloop for sleep"

I have some code use qtcpsocket to write and read,
write-->sleep-->read;
and ui had 2 and more timer to use this function; by i want i run synchronous;so i add mutex to lock it; by it deadlock;
qt4; qt5;
void MainWindow::Start()
{
pTimer = new QTimer(this);
pTimer->setInterval(100);
connect(pTimer,SIGNAL(timeout()), this, SLOT(OnTimer()) );
pTimer->start();
pTimer2 = new QTimer(this);
pTimer2->setInterval(100);
connect(pTimer2,SIGNAL(timeout()), this, SLOT(OnTimer()) );
pTimer2->start();
}
void MainWindow::OnTimer()
{
FunCal(); // in my real code it will MyObj.DoSometing();
}
void MainWindow::FunCal()
{
qDebug()<<"log in fun...";
QMutexLocker loc(&this->_mtx);
qDebug()<<"getted lock in fun...";
QEventLoop loop;
QTimer::singleShot(100, &loop, SLOT(quit()));
loop.exec();
qDebug()<<"log out fun...";
}
I Want i run and out put as:
log in fun...
getted lock in fun ...
log out fun...
log in fun...
getted lock in fun...
log out fun...
but It Run like this:
log in fun...
getted lock in fun ...
log in fun....
---------------------------------no more ---------------------
IMHO the issue of OP results from a basic misunderstanding:
QTimer doesn't introduce multithreading.
It's just a facility to queue events which will sent after a certain time.
That's why, the QEventLoop is necessary to make it running at all.
However, it's still a deterministic execution and this is what probably happens inside the code of OP:
pTimer->start(); → starts first timer
pTimer2->start(); → starts second timer
control flow returns to event loop of QApplication (not exposed in code)
first timer becomes due and calls MainWindow::FunCal()
qDebug()<<"log in fun..."; → output of log in fun...
QMutexLocker loc(&this->_mtx); → this->_mtx becomes locked
qDebug()<<"getted lock in fun..."; → output of getted lock in fun...
loop.exec(); → enter a nested event loop (Nested event loops are allowed in Qt.)
second timer becomes due and calls MainWindow::FunCal() (Please, remember that it was immediately started after first with same interval time.)
qDebug()<<"log in fun..."; → output of log in fun...
QMutexLocker loc(&this->_mtx); → PROBLEM!
To illustrate it further, imagine the following call stack at this point (above called below):
QApplication::exec()
QEventLoop::exec()
QEventLoop::processEvents()
QTimer::timerEvent()
QTimer::timeOut()
MainWindow::onTimer()
MainWindow::FunCal()
QEventLoop::exec()
QTimer::timerEvent()
QTimer::timeOut()
MainWindow::onTimer()
MainWindow::FunCal()
QMutexLocker::QMutexLocker()
QMutex::lock()
(Note: In reality, you will see much more entries in the call-stack which I considered as irrelevant details in this case.)
The problem is: This second call of MainWindow::FunCal() cannot lock the mutex because it is already locked. Hence, the execution is suspended until the mutex is unlocked but this will never happen. The locking of mutex happened in the same thread (in the first/outer call of MainWindow::FunCal()). Unlocking would require to return from this point but it cannot because it's suspended due to the locked mutex.
If you think this sounds like a cat byting into its own tail – yes, this impression is right. However, the official term is Deadlock.
The usage of a QMutex doesn't make much sense as long as there are no competing threads. In a single thread, a simple bool variable would do as well because there are no concurrent accesses possible in a single thread.
Whatever OP tried to achieve in this code: Concerning the event-based programming forced/required by Qt, the problem is simply modeled wrong.
In single threading, a function cannot be entered twice accept by
a (direct or indirect) recursive call
a call out of a triggered interrupt handler.
Leaving the 2. aside (irrelevant for OPs Qt issue), the recursive call happens explicitly due to establishing a second (nested) event loop. Without this, the whole (mutex) locking is unnecessary and should be removed as well.
To understand event-based programming in general – it's described in the Qt doc. The Event System.
Additionally, I found Another Look at Events by Jasmin Blanchette which IMHO gives a nice little introduction into how the Qt event-based execution works.
Note:
Event-based programming can become confusing as soon as the amount of involved objects and signals becomes large enough. While debugging my Qt applications, I noticed from time to time recursions which I didn't expect.
A simple example: A value is changed and emits a signal. One of the slots updates a Qt widget which emits a signal about modification. One of the slots updates the value. Hence, the value is changed and emits a signal...
To break such infinite recursions, a std::lock_guard might be used with a simple DIY class Lock:
#include <iostream>
#include <mutex>
#include <functional>
#include <cassert>
// a lock class
class Lock {
private:
bool _lock;
public:
Lock(): _lock(false) { }
~Lock() = default;
Lock(const Lock&) = delete;
Lock& operator=(const Lock&) = delete;
operator bool() const { return _lock; }
void lock() { assert(!_lock); _lock = true; }
void unlock() { assert(_lock); _lock = false; }
};
A sample object with
a property-like member: bool _value
a simplified signal emitter: std::function<void()> sigValueSet
and a lock used to prevent recursive calls to setValue(): Lock _lockValue
// a sample data class with a property
class Object {
private:
bool _value; // a value
Lock _lockValue; // a lock to prevent recursion
public:
std::function<void()> sigValueSet;
public:
Object(): _value(false) { }
bool value() const { return _value; }
void setValue(bool value)
{
if (_lockValue) return;
std::lock_guard<Lock> lock(_lockValue);
// assign value
_value = value;
// emit signal
if (sigValueSet) sigValueSet();
}
};
Finally, some code to force the lock into action:
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__
int main()
{
DEBUG(Object obj);
std::cout << "obj.value(): " << obj.value() << '\n';
DEBUG(obj.sigValueSet = [&](){ obj.setValue(obj.value()); });
DEBUG(obj.setValue(true));
std::cout << "obj.value(): " << obj.value() << '\n';
}
To keep things short, I connected a slot to the signal which directly sets value again while the signal is emitted.
Output:
Object obj;
obj.value(): 0
obj.sigValueSet = [&](){ obj.setValue(obj.value()); };
obj.setValue(true);
obj.value(): 1
Live Demo on coliru
For a counter-example, I excluded the test if (_lockValue) return; and got the following output:
a.out: main.cpp:18: void Lock::lock(): Assertion `!_lock' failed.
Object obj;
obj.value(): 0
obj.sigValueSet = [&](){ obj.setValue(obj.value()); };
obj.setValue(true);
bash: line 7: 12214 Aborted (core dumped) ./a.out
Live Demo on coliru
This is similar to what happened in OPs case with the only difference that in my case double-locking just violated the assert().
To make this complete, I exluded the lock guard std::lock_guard<Lock> lock(_lockValue); as well and got the following output:
execution expired
Live Demo on coliru
The execution was trapped into an infinite recursion, and the online compiler aborted this after a certain time. (Sorry, coliru. I won't do it again.)

Processing signal of QTreeWidget that has QTreeWidgetItem derivitives as items

I didn't find a proper solution to this problem, so I hope somebody can give me an answer to my problem:
I am using a normal QTreeWidget, but as items I use an own subclass of QTreeWidgetItem (because I needed to store some other information in the item). Now I want to use the itemClicked() signal by the QTreeWidget, but I think my slot doesn't get any signal and I think it has to do with the signature of itemClicked(), since it sends a QTreeWidgetItem and of course not my own subclass.
Is it possible that QTreeWidget doesn't detect a click on my own subclass items?
Here is my connection:
connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *)), this, SLOT(displayTransformData(QTreeWidgetItem*)));
And here is my slot:
void GUI::displayTransformData(QTreeWidgetItem* item) {
cout << "test" endl;
Q_actorTreeWidgetItem* actor_item = dynamic_cast<Q_actorTreeWidgetItem*>(item);
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor = actor_item->getActorReference();
double* position = new double[3];
position = actor->GetOrigin();
x_loc->setText(QString(std::to_string( position[0]).c_str() ));
}
I'm already trying to cast the item that I could get from the signal into my own subclass, but the slot function is never called, because the test from my cout line doesn't appear in the console.
I'm very grateful for every help!
The problem is your incorrect SIGNAL specification,
SIGNAL(itemClicked(QTreeWidgetItem *))
You should probably see a warning message at the console along the lines of:
QObject::connect: No such signal
tree_widget::itemClicked(QTreeWidgetItem *) in ...
From the documentation the actual signal spec is
void QTreeWidget::itemClicked(QTreeWidgetItem *item, int column)
So, using the old Qt4 syntax you need
connect(treeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
this, SLOT(displayTransformData(QTreeWidgetItem*)));
If possible, however, you should make use of the newer Qt5 signal/slot syntax
connect(treeWidget, &QTreeWidget::itemClicked, this, &GUI::displayTransformData);

QEventLoop usage(signals and slots)

I have an application which contains such lines.
emit WindowAdded(settings->WindowType);//!!!!!!!!!!!!!!
MyWindow *widget = new MyWindow(0,settings,currentWindowIndex);
The signal changes value of currentWindowIndex, but it didn't work because of slot, it doesn't change its value in time. Some one advices me to use QEventLoop, but i don't understand how to do this. Give me an example, please.
Another part of the code:
connect(area,SIGNAL(WindowAdded(QString)),this,SLOT(addWindowOnTab(QString)));
void WorkSpace::addWindowOnTab(QString title)
{
qint32 i = TabsList->addTab(title);/////!!!!!!!!!!!!!!!!!!!!!!!!!
emit addedWindowIndex(i);
TabsList->setVisible(true);
}
connect(this,SIGNAL(addedWindowIndex(qint32)),area,SLOT(WindowIndexChanged(qint32)));
void MyMdiArea::WindowIndexChanged(qint32 index)
{
currentWindowIndex=index;
}
I think it can help.
MyMdArea is сlass inherited from QMdiArea, WorkSpace is a QWidget, TabsList is a QTabBar.
And there is another fact: I tried to understand execution sequence of slots and added some lines to code:
QLabel *n= new QLabel("1");
n->show();
after emiting WindowAdded signal
QLabel *n= new QLabel("2");
n->show();
after emiting addedWindowIndex signal
and
QLabel *n= new QLabel("3");
n->show();
after changing currentWindowIndex's value
and that is what i saw "1 2 3" and its exploded my brain. Maybe i don't understand something?

Why does my program halt when calling front() on a std::queue?

I want to use the Irrnet network library in an Irrlicht game.
The source code uses Linux sockets and I'm trying to port it for Windows replacing it with code that uses Windows' Winsock2.
The library compiles successfully but when I try to run the Quake example it crashes. I located the line at which the program stops but i can't figure out how to solve the problem.
The program stops at the second call of the function getNextItem
class NetworkType {
public :
NetworkType();
~NetworkType();
template<class T>
void getNextItem(irr::core::vector3d<T>& data);
private:
typedef std::queue<std::string> Container;
Container items;
};
template<class T>
void NetworkType::getNextItem(irr::core::vector3d<T>& data) {
T X, Y, Z;
std::istringstream item(items.front());
// the program does not get here the second time it calls this function
items.pop();
item >> X;
item >> Y;
item >> Z;
data = irr::core::vector3d<T>(X, Y, Z);
}
and exactly at this line
std::istringstream item(items.front());
Can anyone tell me why does the program stop the second time it gets to this line ?
here is the link for the complete source code
I assume by "stops" you mean "crashes" in some fashion? Likely causes for a crash on the line in question are:
The NetworkType instance that is invoking the getNextItem() method is garbage (the this pointer is garbage or null). This could happen due to bad pointer math elsewhere, a premature delete or destruction of the instance, et cetera. This would manifest as a fault when the program attempted to access the items member.
The items container is empty. In these cases the return value of front() is undefined (since it is a reference) and the constructor for istringstream may be crashing. front() itself may be raising a debug/runtime check error as well depending on your compiler and its configuration.
Actually you might have a runtime error on this one if the dequeue is empty: MSDN deque
So just check the deque isn't empty before you try to pop a value from it.
if(items.size()>0)
{
//do things
}
else
{
//error deque empty
}
[edit] confounded std and (I guess) MSDN ( OP doesn't say) lib.

How to use QCOMPARE Macro to compare events

I have MyWindow class which pops up a blank window, which accepts a mouse click, I need to unit test the mouse click event
Code snippet:
void TestGui::testGUI_data()
{
QTest::addColumn<QTestEventList>("events");
QTest::addColumn<QTestEventList>("expected");
Mywindow mywindow;
QSize editWidgetSize = mywindow.size();
QPoint clickPoint(editWidgetSize.rwidth()-2, editWidgetSize.rheight()-2);
QTestEventList events, expected;
events.addMouseClick( Qt::LeftButton, 0, clickPoint);
expected.addMouseClick( Qt::LeftButton, 0, clickPoint);
QTest::newRow("mouseclick") << events << expected ;
}
void TestGui::testGUI()
{
QFETCH(QTestEventList, events);
QFETCH(QTestEventList, expected);
Mywindow mywindow;
mywindow.show();
events.simulate(&mywindow);
QCOMPARE(events, expected); } // prints FAIL! : TestGui::testGUI(mouseclick) Compared values are not the same
...
}
How to test the mouse click on mywindow. is there any better approach to unit test mouse events?
Thanks,
vels
Take a look on QTest namespace documentation. There is QTest::mouseClick function which allows you to emulate mouse click on the given position of your widget (there is even no necessity to show the widget).
As far as I remember QCOMPARE uses "operator==" for the arguments given and if it returns false then it tries to print it using "QTest::toString<T>(const T& t)" function. If there is no implementation for a type of QCOMPARE arguments then it will just print that values are different. Again take a look on the QTest namespace documentation for details how to reimplement "QTest::toString<T> (const T& t)" for the type you need.

Resources