using QList<T> in a connect( ) call - qt

I am writing my first application in Qt4, basically using the books of Blanchette/Summerfield andSams 24 hours, and a lot of Qt search on internet.
my actual call is:
connect( thumbNailView,
SIGNAL(leftClicked(QListWidgetItem *)),
leftKeypointList,
SLOT(openItem(QListWidgetItem *)));
which gives the following error:
"no matching function for call to DAPPMainWindowWidget::connect(DAPPListWidget*&, const char [32], DAPPKeypointList*&, const char [29])"
I also connected this signal to another object which works flawless:
connect( thumbNailView,
SIGNAL(leftClicked(QListWidgetItem *)),
leftImage,
SLOT(openItem(QListWidgetItem *)));
Both leftImage and leftKeypointList are pointers to objects to a standard QWidget and and a custom object DAPPKeypointList : public QList with DAPPKeypoint holding index and position
of the keypoint.
My idea is that I cannot simply pass a pointer to QList sort of object the same way as I do a pointer to a standard Qwidget.
below follow:
in my DAPP.h
private:
DAPPKeypointList * leftKeypointList;
DAPPKeypointList * rightKeypointList;
and classes:
class DAPPKeypoint {
public:
DAPPKeypoint();
~DAPPKeypoint();
QPoint getKeypointPos();
void setKeypointPos(QPoint);
int getKeypointIndex();
void setKeypointIndex(int);
private:
QPoint keypointPos;
int keypointIndex;
};
class DAPPKeypointList : public QList<DAPPKeypoint> {
Q_OBJECT
public: DAPPKeypointList();
~DAPPKeypointList();
private slots:
void openItem(QListWidgetItem *);
};
in my cpp files:
DAPPKeypoint.cpp
#include "DAPP.h"
DAPPKeypoint::DAPPKeypoint(){}
DAPPKeypoint::~DAPPKeypoint(){}
QPoint DAPPKeypoint::getKeypointPos(){ return keypointPos; }
void DAPPKeypoint::setKeypointPos(QPoint kpPos){ keypointPos = kpPos; }
int DAPPKeypoint::getKeypointIndex(){ return keypointIndex; }
void DAPPKeypoint::setKeypointIndex(int kpIndex){ keypointIndex = kpIndex; }
DAPPKeypointList.cpp: (for the moment just a template ...)
#include "DAPP.h"
DAPPKeypointList::DAPPKeypointList(){}
DAPPKeypointList::~DAPPKeypointList(){}
void DAPPKeypointList:: openItem(QListWidgetItem *) {}
And DAPPMainWindowWidget.cpp :
Parts that are relevant (if you need more, let me know, but I think this is sufficient to have an idea of the problem):
leftKeypointList = new DAPPKeypointList;
rightKeypointList = new DAPPKeypointList;
leftImage = new DAPPImageWidget(leftImageLabel);
connect(thumbNailView,SIGNAL(leftClicked(QListWidgetItem *)) ,leftKeypointList ,SLOT(openItem(QListWidgetItem *)));
connect(thumbNailView,SIGNAL(leftClicked(QListWidgetItem *)) ,leftImage ,SLOT(openItem(QListWidgetItem *)));

Related

How can I connect a signal to QWidget::update slot?

I am using Qt5 with new signal/slot syntax.
I don't know why the following code doesn't work:
QWidget *widget = new QWidget();
connect(pipeline, &Pipeline::NewFrame, widget, &QWidget::update);
I get the error:
no matching member function for call to 'connect' why?
Pipeline class inherits from QObject and NewFrame signal has the same signature as QWidget::update
class Pipeline
: public QObject
{
Q_OBJECT
Q_DISABLE_COPY(Pipeline)
public:
Pipeline(QObject *parent);
signals:
void NewFrame();
};
I am using QtCreator on Arch Linux with g++.
TL;DR: The pipeline should be signaling an image, and the widget should have a SetImage method:
class Pipeline : public QObject {
Q_OBJECT // important
public:
Q_SIGNAL void NewFrame(const QImage &);
...
};
class Viewer : public QWidget {
Q_OBJECT // important
QImage m_image;
public:
Q_SLOT void SetImage(const QImage &image) {
m_image = image;
update();
}
...
};
This is how you'd be using it - note that Viewer knows nothing about Pipeline, because it shouldn't: it just shows new frames, wherever they come from.
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
Pipeline pipeline;
Viewer viewer;
QObject::connect(&pipeline, &Pipeline::NewFrame, &viewer, &Viewer::SetImage);
return app.exec();
}
Connecting anything to QWidget::update directly, especially from external sources, is usually a sign of bad design.
To satisfy your curiosity, you can use a lambda or qOverload to specify what you're connecting to, to fix the very error you're seeing - caused by ambiguity of the the type of the method pointer. Any of the following will work:
connect(…, widget, qOverload<>(&QWidget::update));
or
auto constexpr update = qOverload<>(&QWidget::update));
connect(…, widget, update);
or
connect(…, widget, [widget]{ widget->update(); });

Can i use SIGNAL/SLOT on QPolygon?

disclaimer, i only just downloaded Qt today and have NO experience with it. so i'm sorry if this is a bit stupid. gotta start somewhere :).
i'll use [thing1] and [thing2], 1 being a qpolygon in a GraphicsWidget , 2 being a Widget.
[thing1] = scene->addPolygon([pathname],Pen,Brush)
ui->[thing2]->hide();
connect([thing1],SIGNAL(hovered()),ui->[thing2],SLOT(show()));
i'm trying to hide/show on a mouseover event, but i get the error
D:\Documents\Test\GUI\mainwindow.cpp:61: error: no matching function for call to 'MainWindow::connect(QGraphicsPolygonItem*&, const char*, MainWindow*, QTextEdit*&, const char*)'
connect([thing1],SIGNAL(hovered()),this,ui->[thing2],SLOT(show()));
^
NO!!
FYI:Signals and slots can be used by any qt objects, which a QPolygon is!
bool QObject::connect(const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoConnection)
the connect we use is actually QObject::connect(const QObject* sender_object, const char* signal, const QObject receiver_object, const char ), so it works on every QObject whether it is sending and receiving.
And in your case, as mentioned in the comments by hayt, QPolygon doesnt have hovered() signal, that's why it won't work.
You should go to QPolygon documentation in qt official site and read it.
As far as i know there's no signal for QPolygon so it cannot be used in signals and slots :)
Not always. In Qt 5 you can certainly connect a signal to "anything", e.g. a method on a non-qobject, or to a functor. But you can't connect a non-signal to anything, and there's no hovered signal on a QGraphicsPolygonItem because it's not a QObject, so it can't have any signals.
Instead, you need to create a filter object that will convert QGraphicsSceneEvent to a signal. E.g.:
// https://github.com/KubaO/stackoverflown/tree/master/questions/polygon-sigslot-39528030
#include <QtWidgets>
class HoverFilter : public QGraphicsObject {
Q_OBJECT
bool sceneEventFilter(QGraphicsItem * watched, QEvent *event) override {
if (event->type() == QEvent::GraphicsSceneHoverEnter)
emit hoverEnter(watched);
else if (event->type() == QEvent::GraphicsSceneHoverLeave)
emit hoverLeave(watched);
return false;
}
QRectF boundingRect() const override { return QRectF{}; }
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override {}
public:
Q_SIGNAL void hoverEnter(QGraphicsItem *);
Q_SIGNAL void hoverLeave(QGraphicsItem *);
};
QPolygonF equilateralTriangle(qreal size) {
return QPolygonF{{{0.,0.}, {size/2., -size*sqrt(3.)/2.}, {size,0.}, {0.,0.}}};
}
int main(int argc, char ** argv) {
QApplication app{argc, argv};
QWidget ui;
QVBoxLayout layout{&ui};
QGraphicsView view;
QLabel label{"Hovering"};
layout.addWidget(&view);
layout.addWidget(&label);
label.hide();
ui.show();
QGraphicsScene scene;
view.setScene(&scene);
HoverFilter filter;
QGraphicsPolygonItem triangle{equilateralTriangle(100.)};
scene.addItem(&filter);
scene.addItem(&triangle);
triangle.setAcceptHoverEvents(true);
triangle.installSceneEventFilter(&filter);
QObject::connect(&filter, &HoverFilter::hoverEnter, [&](QGraphicsItem * item) {
if (item == &triangle) label.show();
});
QObject::connect(&filter, &HoverFilter::hoverLeave, [&](QGraphicsItem * item) {
if (item == &triangle) label.hide();
});
return app.exec();
}
#include "main.moc"

How to store global data in QList

Can you explain a methods for storing program data with global access ?
I found these keywords:
- using static class to store data
- pass QList by value
- pass Qlist by reference
- use 'friend' keyword
but I cannot find any real example of storing global QList, as they say, it is a bad design to use global variables. Also there is a mention that using pointers on a QList is a bad idea because of implicit sharing (?).
So where should I store my Qlist for accessing it from a different class in an other .cpp ? So I have:
mainwindow.h
QList <SceneCard> sceneList;
QString mTitle;
public slots:
QString setValue()
{
return mTitle;
}
mainwindow.cpp
MainWindow::AddScene()
{
sceneCard = new SceneCard(sNumber);
sceneList.append(sceneCard);
mTitle = "Nejat is right!"
}
void MainWindow::showSceneCard()
{
SceneDialog D;
connect(D,SIGNAL(getValue()),this,SLOT(setValue()));
D.exec();
}
scenedialog.h
#ifndef SCENEDIALOG_H
#define SCENEDIALOG_H
#include <QDialog>
#include <QList>
namespace Ui {
class SceneDialog;
}
class SceneDialog : public QDialog
{
Q_OBJECT
public:
SceneDialog(QWidget *parent = 0);
~SceneDialog();
signals:
QString getValue();
private:
Ui::SceneDialog *ui;
QString myText;
};
scenedialog.cpp
#include "scenedialog.h"
#include "ui_scenedialog.h"
#include <QDebug>
SceneDialog::SceneDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::SceneDialog)
{
ui->setupUi(this);
myText = getValue();
qDebug() << myText; // myText is empty!!
}
You can put your list as a class member and use Qt's Signal/slot mechanism to access the list from other classes. Just make a signal in the target class, connect it to a slot in the class containing the list and make a connection between two objects of the classes. This way you can access any data member of other classes by connecting a signal to a slot returning that value and just emitting the signal and getting the return value.
For example if you have two classes like :
class A: public QObject
{
Q_OBJECT
public:
A(QObject *parent = 0);
~A();
signals:
int getValue();
private:
void someFunction()
{
int val = getValue();
}
};
class B
{
Q_OBJECT
public:
B(QObject *parent = 0);
~B();
public slots:
int getValue()
{
return someValue;
}
};
And connect the signal from an object of A to the slot in an object of B :
connect(a, SIGNAL(getValue()), b, SLOT(getValue()));
In class A you can access the value returned from getValue slot in B by just calling the signal and using the returned value.
Note that the two objects should be in the same thread for this to work. If they are in different threads then the connection type should be of type Qt::BlockingQueuedConnection :
connect(a, SIGNAL(getValue()), b, SLOT(getValue()), Qt::BlockingQueuedConnection);
Another way is two use static class members but it is not recommended unless you have a good reason to do it. If you have two classes like :
class A {
public:
static QList<int> list;
};
class B {
public:
void do_something();
};
You can access A's static data member from B like this:
void B::do_something()
{
int val = A::list[0];
...
};

QT signal with struct in parameter

I have the class :
class SupervisionManager : public QThread {
Q_OBJECT public:
explicit SupervisionManager(ComAds* com, ComRegEtat* comEt,
ComRegOrdonnanceur* comOrdo,
QObject *parent = 0);
~SupervisionManager();
protected:
virtual void run();
private:
void actionFromPlc();
ComRegEtat::Antichoc antichoc;
signals:
void majAntichoc(ComRegEtat::Antichoc&);
};
and the implementation:
void SupervisionManager::run() {
manage=true;
while(manage)
{
actionFromPlc();
usleep(5000);
}
}
void SupervisionManager::actionFromPlc() {
antichoc.SAS = false;
emit majAntichoc(antichoc);
}
And I connect this signal with :
connect(manager, SIGNAL(majAntichoc(ComRegEtat::Antichoc&)),
preparation, SLOT(affichageAntichoc(ComRegEtat::Antichoc&)));
How do to emit a signal with a struct in its parameter list?
I think I have to use a QSignalMapper but I don't understand how.
In absolutely same way as you emit other things..
ComRegEtat::Antichoc myStruct;
.. some initialisation code
emit majAntichoc(myStruct);
I dont know for sure about latest Qt (after they changed signals/slot be templates based), but before 'emit' was just empty define, so you should look on emit like on function call...
With my code, the slot isn't called whereas the signal is emitted.
I found the solution :
signals:
void majAntichoc(ComRegEtat::Antichoc *);
and
slot :
void affichageAntichoc(ComRegEtat::Antichoc *);
And I don't have to use a QSignalMapper.
Thanks

Is it possible to emit a Qt signal from a const method?

In particular, I am implementing a QWizardPage ("MyWizardPage") for a QWizard, and I want to emit a signal ("sigLog") from my override of the QWizardPage::nextId virtual method.
Like so:
class MyWizardPage
: public QWizardPage
{
Q_OBJECT
public:
MyWizardPage();
virtual int nextId() const;
Q_SIGNALS:
void sigLog(QString text);
};
int MyWizardPage::nextId() const
{
Q_EMIT sigLog("Something interesting happened");
}
But when I try this, I get the following compile error on the Q_EMIT line:
Error 1 error C2662: 'MyWizardPage::sigLog' : cannot convert 'this' pointer from 'const MyWizardPage' to 'MyWizardPage &'
It is possible to emit a signal from a const method by adding "const" to the signal declaration, like so:
void sigLog(QString text) const;
I tested this and it does compile and run, even though you don't actually implement the signal as a normal method yourself (i.e. Qt is okay with it).
You may try to create another class , declare it as friend for your wizard page and add to wizard as a mutable member. after that you may emit it's signal instead of wizard's.
class ConstEmitter: public QObject
{
Q_OBJECT
...
friend class MyWizardPage;
Q_SIGNALS:
void sigLog(QString text);
};
class MyWizardPage
: public QWizardPage
{
Q_OBJECT
public:
MyWizardPage();
protected:
mutable CostEmitter m_emitter;
Q_SIGNALS:
void sigLog(QString text);
};
int MyWizardPage::nextId() const
{
Q_EMIT m_emitter.sigLog("Something interesting happened");
}
MyWizardPage::MyWizardPage()
{
connect(&m_emitter,SIGNAL(sigLog(QString)),this,SIGNAL(sigLog(QString)));
}
or you may just use
int MyWizardPage::nextId() const
{
Q_EMIT const_cast<MyWizardPage*>(this)->sigLog("Something interesting happened");
}
that is not recommended way, because const_cast is a hack, but it's much shorter :)

Resources