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);
}
Related
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!
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.
Not too sure how to formulate my question and I hope that this is more clear. I want to have a baseclass that looks something like this:
class Base : public QObject {
Q_OBJECT
void doSomething() { emit test(this); }
virtual void doSomethingElse() = 0;
signals:
void test(Base*);
}
And then in the derived class do this:
class Derived : public Base {
void doSomethingElse() { emit test(this); }
}
If I now listen to the signals of this object and do I listen to test(Derived*) or/and test(Base*)?
The moc generates at compile time a list of the slots and signals based on the way you declared them in the classes that use the Q_OBJECT macro.
This list is a list of strings, so if you declared:
signals:
void test(Base*);
the item in the list would be the string "test(Base*)" (you can see that list in the variable qt_meta_YourClass of the file moc_yourclass.cpp in the output directory).
The macros SIGNAL and SLOT also return strings, connect() canonize them so they are formatted like the one from the moc generated list, and compares them to those in that list.
When you derive the class, the string hasn't changed, so you still have to use SIGNAL(test(Base*)).
You shouldn't include senders as parameters of signals. You can simply use QObject::sender() to get the QObject that has sent the signal.
eg:
emit test();
Then in a slot:
void Listener::someObject_test() {
QObject* sender = QObject::sender();
// or:
Derived* sender = (Derived*)QObject::sender();
}
As the derived class does not have its own signal, you will listen the test(Base*).
(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.
I bumped into an additional question that I needed in regards to this: Using an IEnumerable<T> as a delegate return type
From the above solution, the following was suggested:
class Example
{
//the delegate declaration
public delegate IEnumerable<T> GetGridDataSource<T>();
//the generic method used to call the method
public void someMethod<T>(GetGridDataSource<T> method)
{
method();
}
//a method to pass to "someMethod<T>"
private IEnumerable<string> methodBeingCalled()
{
return Enumerable.Empty<string>();
}
//our main program look
static void Main(string[] args)
{
//create a new instance of our example
var myObject = new Example();
//invoke the method passing the method
myObject.someMethod<string>(myObject.methodBeingCalled);
}
}
Notice that in someMethod, the delegate "method()" is called. Is there anyway to set a class-level delegate that is called later on?
I.e:
class Example {
//the delegate declaration
public delegate IEnumerable<T> GetGridDataSource<T>();
//this fails because T is never provided
private GetGridDataSource<T> getDS;
//the generic method used to call the method
public void someMethod<T>(GetGridDataSource<T> method)
{
getDS = method;
}
public void anotherMethod() {
getDS();
}
}
Depending on what you are trying to achieve and where you have flexibility in your design, there are a number of options. I've tried to cover the ones that I feel most probably relate to what you want to do.
Multiple values of T in a single instance of a non-generic class
This is basically what you seem to want. However, because of the generic nature of the method call, you'll need a class level variable that can support any possible value of T, and you will need to know T when you store a value for the delegate.
Therefore, you can either use a Dictionary<Type, object> or you could use a nested type that encapsulates the class-level variable and the method, and then use a List<WrapperType<T>> instead.
You would then need to look up the appropriate delegate based on the required type.
class Example {
//the delegate declaration
public delegate IEnumerable<T> GetGridDataSource<T>();
//this works because T is provided
private Dictionary<Type, object> getDSMap;
//the generic method used to call the method
public void someMethod<T>(GetGridDataSource<T> method)
{
getDSMap[typeof(T)] = method;
}
//note, this call needs to know the type of T
public void anotherMethod<T>() {
object getDSObj = null;
if (this.getDSMap.TryGetValue(typeof(T), out getDSObj))
{
GetGridDataSource<T> getDS = getDSObj as GetGridDataSource<T>;
if (getDS != null)
getDS();
}
}
Single value of T in a single instance of a non-generic class
In this case, you could store the delegate instance in a non-typed delegate and then cast it to the appropriate type when you need it and you know the value of T. Of course, you'd need to know T when you first create the delegate, which negates the need for a generic method or delegate in the first place.
Multiple values of T in multiple instances of a generic class
Here you can make your parent class generic and supply T up front. This then makes the example you have work correctly as the type of T is known from the start.
class Example<T> {
//the delegate declaration
public delegate IEnumerable<T> GetGridDataSource<T>();
//this works because T is provided
private GetGridDataSource<T> getDS;
//the generic method used to call the method
public void someMethod<T>(GetGridDataSource<T> method)
{
getDS = method;
}
public void anotherMethod() {
if (getDS != null)
getDS();
}
}
You either need to make the type generic as well, or use plain Delegate and cast back to the right type when you need to invoke it. You can't just use T outside a generic context - the compiler will think you're trying to refer to a normal type called T.
To put it another way - if you're going to try to use the same type T in two different places, you're going to need to know what T is somewhere in the type... and if the type isn't generic, where is that information going to live?