Can i use SIGNAL/SLOT on QPolygon? - qt

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"

Related

using QList<T> in a connect( ) call

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 *)));

How to subclass QIODevice and read /dev/input/eventX

I have read the QIODevice doc, but still don't know how to archive that.
What I want to do is to create a KeyBoard class deriving from QIODevice. which opens /dev/input/eventX. I hope that my code can use the readyRead() signal of KeyBoard. (QFile does not emit readyRead() signal)
class KeyBoard : public QIODevice {
public:
KeyBoard();
~KeyBoard();
protected:
qint64 readData(char *data, qint64 size);
qint64 writeData(const char *data, qint64 size);
};
What do I need to do in readData() and writeData()?
And how does my code use this class? (I just use the QCoreApplication, no gui)
Use QSocketNotifier on the open file handle. You can read from the device using QFile,or abuse QSerialPort, i.e. QSerialPort m_port{"input/eventX"}. See this answer for an example of using QSocketNotifier with stdin; /dev/input/eventX requires a similar approach.
Here's an example that works on /dev/stdio, but would work identically on /dev/input/eventX.
// https://github.com/KubaO/stackoverflown/tree/master/questions/dev-notifier-49402735
#include <QtCore>
#include <fcntl.h>
#include <boost/optional.hpp>
class DeviceFile : public QFile {
Q_OBJECT
boost::optional<QSocketNotifier> m_notifier;
public:
DeviceFile() {}
DeviceFile(const QString &name) : QFile(name) {}
DeviceFile(QObject * parent = {}) : QFile(parent) {}
DeviceFile(const QString &name, QObject *parent) : QFile(name, parent) {}
bool open(OpenMode flags) override {
return
QFile::isOpen()
|| QFile::open(flags)
&& fcntl(handle(), F_SETFL, O_NONBLOCK) != -1
&& (m_notifier.emplace(this->handle(), QSocketNotifier::Read, this), true)
&& m_notifier->isEnabled()
&& connect(&*m_notifier, &QSocketNotifier::activated, this, &QIODevice::readyRead)
|| (close(), false);
}
void close() override {
m_notifier.reset();
QFile::close();
}
};
int main(int argc, char **argv) {
QCoreApplication app{argc, argv};
DeviceFile dev("/dev/stdin");
QObject::connect(&dev, &QIODevice::readyRead, [&]{
qDebug() << "*";
if (dev.readAll().contains('q'))
app.quit();
});
if (dev.open(QIODevice::ReadOnly))
return app.exec();
}
#include "main.moc"

QLabel click event using Qt?

I'm new in Qt and have a question.
I have QLabel and QLineEdit objects, and when QLabel text is clicked on, I want to set this text in QLineEdit.
Also I have read that QLabel has not clicked signal.
Can you explain how can I do this and write code for me ?!
Either style another type of QWidget such as a specific QPushButton to look like a QLabel and use its clicked() signal or inherit QLabel yourself and emit your own clicked() signal.
See this example:
https://wiki.qt.io/Clickable_QLabel
If you choose the latter option you can pass the text in the signal. Then connect the necessary signals/slots up between the QLabel and the QLineEdit like so:
QObject::connect(&label, SIGNAL(clicked(const QString& text)),
&lineEdit, SLOT(setText(const QString& text)));
A simple way to accomplish that, without a need for any subclassing, is a signal source that monitors the events on some object and emits relevant signals:
// main.cpp - this is a single-file example
#include <QtWidgets>
class MouseButtonSignaler : public QObject {
Q_OBJECT
bool eventFilter(QObject * obj, QEvent * ev) Q_DECL_OVERRIDE {
if ((ev->type() == QEvent::MouseButtonPress
|| ev->type() == QEvent::MouseButtonRelease
|| ev->type() == QEvent::MouseButtonDblClick)
&& obj->isWidgetType())
emit mouseButtonEvent(static_cast<QWidget*>(obj),
static_cast<QMouseEvent*>(ev));
return false;
}
public:
Q_SIGNAL void mouseButtonEvent(QWidget *, QMouseEvent *);
MouseButtonSignaler(QObject * parent = 0) : QObject(parent) {}
void installOn(QWidget * widget) {
widget->installEventFilter(this);
}
};
The emit keyword is an empty macro, Qt defines it as follows:
#define emit
It is for use by humans as a documentation aid prefix only, the compiler and moc ignore it. As a documentation aid, it means: the following method call is a signal emission. The signals are simply methods whose implementation is generated for you by moc - that's why we have to #include "main.moc" below to include all the implementations that moc has generated for the object class(es) in this file. There's otherwise nothing special or magical to a signal. In this example, you could look in the build folder for a file called main.moc and see the implementation (definition) of void MouseButtonSignaler::mouseButtonEvent( .. ).
You can then install such a signaler on any number of widgets, such as a QLabel:
int main(int argc, char ** argv) {
QApplication app(argc, argv);
MouseButtonSignaler signaler;
QWidget w;
QVBoxLayout layout(&w);
QLabel label("text");
QLineEdit edit;
layout.addWidget(&label);
layout.addWidget(&edit);
signaler.installOn(&label);
QObject::connect(&signaler, &MouseButtonSignaler::mouseButtonEvent,
[&label, &edit](QWidget*, QMouseEvent * event) {
if (event->type() == QEvent::MouseButtonPress)
edit.setText(label.text());
});
w.show();
return app.exec();
}
#include "main.moc"
You need to create one Custom Label class, which will inherit QLabel. Then you can use MouseButtonRelease event to check clicking of Label and emit your custom signal and catch in one SLOT.
Your .h file will be as below:
class YourLabelClass : public QLabel{
signals:
void myLabelClicked(); // Signal to emit
public slots:
void slotLabelClicked(); // Slot which will consume signal
protected:
bool event(QEvent *myEvent); // This method will give all kind of events on Label Widget
};
In your .cpp file, your constructor will connect signal & slot as below :
YourLabelClass :: YourLabelClass(QWidget* parent) : QLabel(parent) {
connect(this, SIGNAL(myLabelClicked()), this, SLOT(slotLabelClicked()));
}
Remaining event method and SLOT method will be implemented as below:
bool YourLabelClass :: event(QEvent *myEvent)
{
switch(myEvent->type())
{
case(QEvent :: MouseButtonRelease): // Identify Mouse press Event
{
qDebug() << "Got Mouse Event";
emit myLabelClicked();
break;
}
}
return QWidget::event(myEvent);
}
void YourLabelClass :: slotLabelClicked() // Implementation of Slot which will consume signal
{
qDebug() << "Clicked Label";
}
For Changing a Text on QLineEdit, you need to create a Custom Class and share object pointer with custom QLabel Class. Please check test code at this link
In the above example the header needs Q_OBJECT:
class YourLabelClass : public QLabel{
Q_OBJECT
signals:

undefined reference to `Counter::valueChanged(int)'

i'm trying to learn qt.this is my first example that I'm practicing.but i have this error:C:\Qt2\Qt5.2.1\Tools\QtCreator\bin\recognize_signal_slot\main.cpp:19: error: undefined reference to `Counter::valueChanged(int)'
I don't know what I should do..someone told me you should put your class in header file.but I couldn't understand what he said.can anyone tell me step by step.thank you so much.
here is my code in main.cpp :
#include <QCoreApplication>
#include <QObject>
class Counter : public QObject
{
int m_value;
public:
int value() const { return m_value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
};
void Counter::setValue(int value)
{
if (value != m_value)
{
m_value = value;
emit valueChanged(value);
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Counter d, b;
QObject::connect(&d, SIGNAL(valueChanged(int)),
&b, SLOT(setValue(int)));
d.setValue(12); // a.value() == 12, b.value() == 12
return a.exec();
}
[What's Wrong?]
You signals & slots are not invoked by Meta-Object-Compiler (MOC).
Suggested reading: Why Does Qt Use Moc for Signals and Slots?.
[Solution]
Step 1. Add Q_OBJECT macro to the QObject derivatives that use signals & slots.
class Counter : public QObject
{
Q_OBJECT // <-----HERE
int m_value;
public:
int value() const { return m_value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
};
Step 2. move your class declaration to counter.h and implementation to counter.cpp. Since MOC searches header files that contain Q_OBJECT, it's better to keep your QObject classes and main well separate, even for a small test project.
Step 3. Clean all ---> run qmake ---> rebuild (qmake will automatically call MOC to translate signals & slots syntax into compilable C++ code)

Qt - How to get real size of maximized window that I have pointer to?

I have a method that get pointer to widget where should be setted some other widgets. I have to resize the main window, where that widget is placed and then I should get the real size of that widget.
I’ve tried to do this like:
void MyClass::setWidgets(QList<QWidget*> list, QWidget *parentWidget)
{
QWidget* mainWindow = parentWidget->window();
mainWindow->showMaximized();
int width = parentWidget->size().width();
int height = parentWidget->size().height();
/*... rest of method...*/
}
That method is call from other class.
But I read that I should wait for resizeEvent. Could anyone explain me how I should do this or if there is any option to get that size differently?
If you want to get events for a different object, you can install an event filter using QObject::installEventFilter.
A simple example for ResizeEvent is:
filter.hpp
#ifndef FILTER_HPP
#define FILTER_HPP
#include <QtGui>
class ResizeFilter : public QObject
{
Q_OBJECT
public:
ResizeFilter();
protected:
bool eventFilter(QObject *obj, QEvent *event);
};
#endif
filter.cpp
#include "filter.hpp"
ResizeFilter::ResizeFilter() : QObject() {}
bool ResizeFilter::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::Resize)
{
QResizeEvent* resizeEv = static_cast<QResizeEvent*>(event);
qDebug() << resizeEv->size();
}
return QObject::eventFilter(obj, event);
}
main.cpp
#include <QtGui>
#include "filter.hpp"
int main(int argc, char** argv)
{
QApplication app(argc, argv);
ResizeFilter filter;
QWidget window;
window.installEventFilter(&filter);
window.showMaximized();
return app.exec();
}
filter.pro
TEMPLATE = app
HEADERS = filter.hpp
SOURCES = main.cpp filter.cpp
When testing this on my PC it gave the output:
QSize(840, 420)
QSize(1280, 952)

Resources