everyone!
I am having a problem using QObject::connect with some custom classes I've created. First of all, I have created 2 classes that inherit from QObject, they are called: Valve and PushButton. They are instantiated inside controllers called PanelController and SynopticController, which are also QObjects. And these controllers are instantiated inside another class called MasterController, also a QObject. I find this information useful since I think it is a problem of referencing the classes or the way I might be instantiating my classes inside these controllers. I strongly think this, because in my main method, when I do the following snippet of code, the connection works:
...
avionics::synoptic::Valve valveTest(nullptr, avionics::synoptic::ValveName::ABV);
avionics::panel::PushButton pushButtonTest(nullptr, avionics::panel::PanelNames::RECIRC);
QObject::connect(&pushButtonTest, &avionics::panel::PushButton::onStateColorChanged, &valveTest, &avionics::synoptic::Valve::updateState);
...
Basically, the controller classes are:
// MasterController
class MasterController : public QObject {
...
private:
panel::PanelController* panelController{nullptr};
synoptic::SynopticController* synopticController{nullptr};
}
// Panel Controller
class PanelController : public QObject {
...
explicit PanelController(QObject *parent = nulptr){
this->pushButtons.append(new avionics::panel::PushButton(_panelController, avionics::panel::PanelNames::RECIRC));
}
private:
QList<avionics::panel::PushButton*> pushButtons{};
}
// SynopticController
class SynopticController : public QObject {
private:
QList<avionics::synoptic::Valve*> iceValves{};
explicit SynopticController(QObject *parent = nullptr) {
antiIcePneumaticLines.append(new avionics::synoptic::PneumaticLine(_synopticController, avionics::synoptic::PneumaticLineName::APU_2_ABV));
}
}
My problem is that when I do the same call for the QObject::connect either from my MasterController constructor or my main method, the signal doesn't call the slot function. I want to connect pushButtons to valves, and to do this I am using getters from my controllers. The call to QObject::connect that doesn't work is:
QObject::connect(panelController->getpushButtons().at(1), &avionics::panel::PushButton::onStateColorChanged, synopticController->getValves().at(1), &avionics::synoptic::Valve::updateState);
// Example of getter
QList<avionics::panel::PushButton*> PanelController::getPushButtons(){
return pushButtons;
}
I've put some prints inside the method that emits the signal and tried debugging it, but the signal is emitted and the slot isn't called. The classes return from the getters are not undefined or null, I've checked it. Let me know if something wasn't clear. Thanks in advance!
Related
I should use setlocalport for my socket connection but the property is protected and i have an error of compilation.
This is in qt application.
m_pSocket = new QTcpSocket();
m_pSocket->setLocalPort(m_iLocalPort);
error: ‘void QAbstractSocket::setLocalPort(quint16)’ is protected
If you want to use protected member like a public one, then you should provide a custom class that is the child of the class whose protected method you intend to use. There is nothing that would forbid you to create a child class inheriting QTcpSocket, and then using the protected method you want. Example for the QTcpSocket case that has been described here can be the following.
// Let us define CustomTcpSocket, i.e. the class inheriting QTcpSocket
#pragma once
#include <QTcpSocket>
class CustomTcpSocket
: public QTcpSocket
{
Q_OBJECT
public:
CustomTcpSocket(QObject* parent = nullptr);
virtual ~CustomTcpSocket();
// This method will be used to call QTcpSocket::setLocalPort which is protected.
void SetLocalPort(quint16 port);
};
Then, we provide the implementation itself.
#include "CustomTcpSocket.h"
CustomTcpSocket::CustomTcpSocket(QObject* parent)
: QTcpSocket(parent)
{
}
CustomTcpSocket::~CustomTcpSocket()
{
}
void CustomTcpSocket::SetLocalPort(quint16 port)
{
// Since method is protected, and scope is the child one, we can easily call this method here.
QAbstractSocket::setLocalPort(port);
}
Now we can easily use this newly created class in the following way.
auto customTcpSocketInstance = new CustomTcpSocket();
customTcpSocketInstance->SetLocalPort(123456);
Through usage of polymorphism, instances of CustomTcpSocket should be accepted by other Qt's APIs. However, there is no guarantee it will work as you would expect it to. Qt developers wanted this method to be protected for some of the reasons. So, use it with caution.
I would like to send a member parentWidget, definited in a class function, to another class by a connection because I want to to add it in a list.
Unfornately I have got a error with this member permissions.
The respond error is:
C2248: 'QGraphicsWidget::QGraphicsWidget': cannot access private member declared in class 'QGraphicsWidget'
So here is my function
void DiagramScene::insertWidget(DiagramItem::DiagramType diagramtype)
{
QGraphicsWidget parentWidget;
//some code
connect(this,SIGNAL(sendToItemList(QGraphicsWidget)),diagramitem,SLOT(addToItemList(QGraphicsWidget)));
emit this->sendToItemList(parentWidget);
}
and this is my slot:
void DiagramItem::addToItemList(QGraphicsWidget widget)
{
QGraphicsWidget * newWidget;
memmove(newWidget,&widget,sizeof(QGraphicsWidget));
items.append(newWidget);
}
QGraphicsWidget inherits QObject, so it is uncopyable. The addToItemList function receives its argument by value, which leads to a copy attempt. One possible solution is to change the function's argument type to QGraphicsWidget* and create the object as QGraphicsWidget *parentWidget = new QGraphicsWidget(). This would also eliminate a very strange and incorrect use of memmove from your code.
I might be wrong but as far as I know you can't copy QGraphicsWidget since it inherits from QObject. (Can be read here)
My suggestion:
void DiagramScene::insertWidget(DiagramItem::DiagramType diagramtype)
{
QGraphicsWidget* parentWidget = new QGraphicsWidget();
//some code
connect(this,SIGNAL(sendToItemList(QGraphicsWidget)),diagramitem,SLOT(addToItemList(QGraphicsWidget)));
emit this->sendToItemList(parentWidget);
}
void DiagramItem::addToItemList(QGraphicsWidget* widget)
{
items.append(widget);
}
Using Qt 5.4, I'm having trouble with a signal emitted from a child class. This is the situation:
There is a
class Player : public QDialog{
Q_OBJECT
/*...*/
public slots:
void ReactToAdapter(Adapter::state_t newState);
private:
Adapter* adapter;
}
The
class Adapter : public QObject{
Q_OBJECT
public:
enum state_t {/*...*/}
signals:
void StateChagned(state_t newState);
}
is purely virtual. One of its Implementations is given as
class AdapterCAN : public Adapter{
O_OBJECT
/*...*/
}
AdapterCAN is emitting the StateChagnedwithin one of its methodes.
state_t is visible everywhere through includes. All three classes have the Q_OBJECT macro.
When I try to do
Player::ConnectToCANBus(/*...*/){
adapter = new AdapterCAN(/*...*/);
connect(adapter, SIGNAL(StateChanged(Adapter::state_t),
this, SLOT(ReactToAdapter(Adapter::state_t));
}
This creates the error message
QObject::connect: No such signal AdapterCAN::StateChanged(Adapter::state_t) in ..\player.cpp:90 during runtime.
It looks like the signal is not inherited!? Anyone having any ideas what I might be doing wrong? Thanks!
Changing the definition of the signal to
class Adapter : public QObject{
/*...*/
void StateChagned(state_t);
}
solved it. The qualified name has to be left out.
Thanks to #vahancho for pointing this out!
If anyone finds here, please check your connect function for errors. I once wrote such a stupid error, but the compiler did not give any error report.
connect(m_pInitEncFromDvd1, SIGNAL(signalFinish(int,QStirng)),
this, SLOT(slotDVD1InitFinish(int,QString)),
(Qt::ConnectionType)(Qt::ConnectionType::AutoConnection | Qt::ConnectionType::UniqueConnection));
Pay attention to
"SIGNAL(signalFinish(int,QStirng))"
, I accidentally write QString as QStirng, and it works perfectly after correction.
I've a simple Qt Question. I want that automatically generated UIC files are derived from a custom interface class like in:
Intention
class MyUiInterface {
public:
virtual void setupUi(QWidget* w) = 0;
virtual void retranslateUi(QWidget*w) = 0;
};
Generated UIC file should look like:
class Ui_MyWidget {
public:
void setupUi(QWidget* w) {
...
}
void retranslateUi(QWidget* w) {
...
}
};
namespace Ui {
class MyWidget : public MyUiInterface , public Ui_MyWidget {};
}
Why?
Every Ui::Class would then implement MyUiInterface. In each class that derives from Ui::Class (see The Multiple Inheritance Approach) I would be able to call setupUi and retranslateUi which makes sense if the class that derives from UI::Class class is a base class either. I want every widget to be derived from my abstrcat base class MyWidgetBase. Consider following:
class MyWidgetBase abstract : public QWidget, protected MyUiInterface {
protected:
void changeEvent(QEvent *e) {
QWidget::changeEvent(e);
if (e->type() == QEvent::LanguageChange) {
retranslateUi(this); // Still abstract here
}
}
};
class MyWidget : public MyWidgetBase : public Ui::MyWidget {
};
The effect is, every time MyWidget::changeEvent() is callled, retranslateUi of that specific class is called. Otherwise changeEvent had to be reimplemented in each class. This would be a bit against "code reuse" concept.
I think Qt UIC is not able to handle this situation isn't it? Is there a similar way to solve this problem?
Unfortunately, reading XML Schema for ui files is telling us that this is not possible to automate using uic compiler.
However, it is unclear to me why you would want to implement that automatically - even if the Uic somehow manages to implement your interface, you will still need to add bodies of the functions by hand, editing generated .h file, as I am sure that there is no way to include custom code in xml file which will translate as C++ code.
Why you just don't reimplement setupUi and retranslateUi in your MyWidget class? Every Ui class will have one of these classes, so you can implement this on this level, instead of base class. It is possible that I am missing something, but I see this as an appropriate way to do this.
class MyWidget : public MyWidgetBase, public Ui::MyWidget {
public:
void setupUi(QWidget* w) {
...
}
void retranslateUi(QWidget* w) {
...
}
};
With this approach, you don't need to reimplement changeEvent() in any of your custom widgets, and changeEvent will still call the appropriate retranslateUi().
(C++/Qt) I have a smart pointer to a QObject. Let's say a QWeakPointer. For some external reason (something that might happen in another object or due to an event), it is possible that the pointed object gets destroyed. Since I have a smart pointer there will be no dangling reference, so there's no problem. But I always have to check if the pointer is null or not.
I'm thinking of using the null pattern in order to avoid checking this all the time but I'm not sure if this is possible or convenient with a QObject. The idea would be that the pointer points to the object and in case it gets destroyed, the smart pointer changes its pointed object to a null object. Is this a good idea or should I forget it and just check if the pointer is NULL all the time?
Let's show you an example. We have a worker who uses a tool to do its work:
class Worker : public QObject
{
Q_OBJECT
public:
Worker(QObject *parent = 0);
void work()
{
if(m_tool)
m_tool->use();
emit workCompleted();
};
signals:
workCompleted();
public slots:
void setTool(QWeakPointer<Tool> tool);
private:
QWeakPointer<Tool> m_tool;
};
class Tool : public QObject
{
Q_OBJECT
public:
Tool();
public slots:
void use() =0;
};
class Screwdriver : public Tool
{
Q_OBJECT
public:
Screwdriver() : Tool();
public slots:
void use()
{
// do something
};
};
class Hammer : public Tool;
class Saw : public Tool;
...
In this case, the Tool is a public domain object of a library, which is used by the Worker. I'm developing such library. So the worker is using a screwdriver but it gets broken and gets destroyed. No problem:
if(m_tool)
m_tool->use();
emit workCompleted();
m_tool is 0 so it simply does nothing. But we have to check that it's not null everytime.
Now let's say we had a NullTool object:
class NullTool : public Tool
{
Q_OBJECT
public:
NullTool() : Tool();
public slots:
void use()
{
// does nothing
};
};
When the tool was destroyed, our pointer would be smart and would know it should point to a NullTool instance. So Worker::work() could be implemented like this:
void Worker::work()
{
m_tool->use();
emit workCompleted();
};
m_tool->use() would then get called on the NullTool which does nothing, so there would be no need to check the pointer is not null.
Is this a good idea? Is it possible with the smart pointer classes Qt provides or should I subclass QWeakPointer?
I think the null object pattern makes most sense for value-like classes. Examples are QString or QVariant, were you don't want to have code like if ( str && !str->isEmpty() ) but just do if ( !str.isEmpty() ). For QObjects, which are not values but have "an identity", I never found this useful.
I don't understand clearly your use case, but your program can be signaled when the object has been destroy by connecting the following signal from QObject:
void destroyed ( QObject * obj = 0 );
I don't see any problem in your idea. You just have to compare the work that it takes to implement it compared to the work for checking the pointer every time. Let's your checking the pointer 10.000 times it's a good idea to use your approach. Side note: Your null object pattern rely on the fact that Tool::use() has no side effects whatsoever.
Take care that possible side affects in Tool::use() don't get in the way when you replace it polymorphically with NullTool::use(). In other words: Be sure you don't break the Liskov Substitution Principle.