Method for Connecting Button to Method
-
Hello everyone,
i am new to QT and am trying to create a Method in my QT Widgets-Application with wich i can connect a new Method to run when the button is clicked.
I have tried it like this:
in my widget.cpp:
void Widget::connectPushButtonToMethod(QObject* object, const char* method)
{
disconnect(ui->pushButton, &QPushButton::clicked, nullptr, nullptr);
connect(ui->pushButton, &QPushButton::clicked, object, method);
}in my story.cpp:
void Story::firstMethod()
{
qDebug() << "First Method";
w->setTextToLabel("First");
w->connectPushButtonToMethod(this, SLOT(secondMethod()));
}Goal is to create a public widget-Method to connect the Button to a new Method (of any class) to run the next time it is clicked.
Main Problem (probably) lies in the way the signals and slots are used. Everything else seems to be working fine.
Has anyone got any ideas? :)
-
Hello everyone,
i am new to QT and am trying to create a Method in my QT Widgets-Application with wich i can connect a new Method to run when the button is clicked.
I have tried it like this:
in my widget.cpp:
void Widget::connectPushButtonToMethod(QObject* object, const char* method)
{
disconnect(ui->pushButton, &QPushButton::clicked, nullptr, nullptr);
connect(ui->pushButton, &QPushButton::clicked, object, method);
}in my story.cpp:
void Story::firstMethod()
{
qDebug() << "First Method";
w->setTextToLabel("First");
w->connectPushButtonToMethod(this, SLOT(secondMethod()));
}Goal is to create a public widget-Method to connect the Button to a new Method (of any class) to run the next time it is clicked.
Main Problem (probably) lies in the way the signals and slots are used. Everything else seems to be working fine.
Has anyone got any ideas? :)
@tfre
You are mixing old and new styleconnect()
syntax. Don't. Use only new. Get rid of anyconst char* method
andSLOT()
(orSIGNAL()
, don't use them. Unless you really know why you're doing it, and then don't mix against&QPushButton::clicked
new style.Goal is to create a public widget-Method to connect the Button to a new Method (of any class) to run the next time it is clicked.
Sounds over-engineered.
Make
Widget
exposepublic QPushButton *pushButton() { return ui->pushButton; }
andStory
goconnect(w->pushButton(), &QPushButton::clicked, this, &Story::secondMethod);
.Another way is to have
Widget
expose its own newpublic void pushButtonClicked()
signal, which it does internally viaconnect(ui->pushButton, &QPushButton::clicked, this, &Widget::pushButtonClicked);
Now
Story
can connect to that without knowing about internalQPushButton
:connect(w, &Widget::pushButtonClicked, this, &Story::secondMethod);
-
@tfre
You are mixing old and new styleconnect()
syntax. Don't. Use only new. Get rid of anyconst char* method
andSLOT()
(orSIGNAL()
, don't use them. Unless you really know why you're doing it, and then don't mix against&QPushButton::clicked
new style.Goal is to create a public widget-Method to connect the Button to a new Method (of any class) to run the next time it is clicked.
Sounds over-engineered.
Make
Widget
exposepublic QPushButton *pushButton() { return ui->pushButton; }
andStory
goconnect(w->pushButton(), &QPushButton::clicked, this, &Story::secondMethod);
.Another way is to have
Widget
expose its own newpublic void pushButtonClicked()
signal, which it does internally viaconnect(ui->pushButton, &QPushButton::clicked, this, &Widget::pushButtonClicked);
Now
Story
can connect to that without knowing about internalQPushButton
:connect(w, &Widget::pushButtonClicked, this, &Story::secondMethod);
@JonB Thank you for your reply. I went a few steps back and figured out how signals and slots in general work and managed to get a basic understanding.
I have managed to connect a button to a method and after clicking it it automatically reconnects to another method. (this took me 3 hours)
Now i would like to make that as a general function/method in which the button(button1, button2, button3, ...), the class of the method(probably as an object) and the method (of said class/object) is handed over and then get connected.
I am not sure how i can hand over methods as parameters.
Edit: It might sound over-engineered, but it is quite important that i manage to get it working that way to reduce the effort for my team that will be using it.
-
@JonB Thank you for your reply. I went a few steps back and figured out how signals and slots in general work and managed to get a basic understanding.
I have managed to connect a button to a method and after clicking it it automatically reconnects to another method. (this took me 3 hours)
Now i would like to make that as a general function/method in which the button(button1, button2, button3, ...), the class of the method(probably as an object) and the method (of said class/object) is handed over and then get connected.
I am not sure how i can hand over methods as parameters.
Edit: It might sound over-engineered, but it is quite important that i manage to get it working that way to reduce the effort for my team that will be using it.
@tfre
Then you will need to await someone more expert than I am in the area of either (a) usingSIGNAL
/SLOT()
(orQMetaObject::invokeMethod()
?) to do it viachar *
approach or (b) C++ template wizard who can tell you how to write it that way, hopefully. -
@tfre
Then you will need to await someone more expert than I am in the area of either (a) usingSIGNAL
/SLOT()
(orQMetaObject::invokeMethod()
?) to do it viachar *
approach or (b) C++ template wizard who can tell you how to write it that way, hopefully.Hi,
Can you explain what you want to provide to your team ?
I understand that you want to make your library easy to use for others but it sounds like you are trying to hide some stuff rather than making it easy to understand. -
Hi,
Can you explain what you want to provide to your team ?
I understand that you want to make your library easy to use for others but it sounds like you are trying to hide some stuff rather than making it easy to understand.@tfre
Looks to me as if the use case is that clicking on the same button triggers different behaviors by dispatching to different methods in specific cases. That can be done by re-connecting the signal, but I am not sure if generalizing such a thing is the most elegant and easy-to-debug implementation. I would rather assign a status (maybe represented by an enumeration) to the button, that can also lead to different button icons of needed. Then you connect the button to one method and dispatch in a switch statement. Much easier and more transparent.But as @SGaist rightfully said: maybe you wanna explain your use case and show more code.
-
@tfre
Looks to me as if the use case is that clicking on the same button triggers different behaviors by dispatching to different methods in specific cases. That can be done by re-connecting the signal, but I am not sure if generalizing such a thing is the most elegant and easy-to-debug implementation. I would rather assign a status (maybe represented by an enumeration) to the button, that can also lead to different button icons of needed. Then you connect the button to one method and dispatch in a switch statement. Much easier and more transparent.But as @SGaist rightfully said: maybe you wanna explain your use case and show more code.
I will try my best to explain what i need: (it is for an uni project btw)
The User will be presented with a Text-Output and two (or more) buttons to choose a path. (Think of it like a story in which you can choose an option on what to do next)
My team is creating the scenarios as methods of classes.
I want to reuse the same buttons for the entire duration of the programs running time.
What i would like to do is give them a tool to connect their methods to the buttons when their scenario is beeing played.
After that i want to give the next scnario (next method) the ability to reconnect the buttons to their choices and so on.I know that is would be possible to do all of this manually with an endless switch/if construct (would probably easier) but i still want them to have minimal effort (maybe 1-3 lines of code for each connection).
What i have managed so far is to hand over the button-object as one of the parameters. (I haven't yet tried to call on the "connectButtonToMethod-Method from another class)
void Widget::execute()
{
QPushButton* buttonPointer = ui->pushButton;// void (test::*methodPtr)() = &test::cout1;
this->connectButtonToMethod(buttonPointer);
}void Widget::connectButtonToMethod(QPushButton* buttonPointer)
{
qDebug() << "Active connectButtonToMethod-Method";
qDebug() << buttonPointer << Qt::endl;disconnect(buttonPointer, &QPushButton::clicked, nullptr, nullptr);
connect(buttonPointer, &QPushButton::clicked, testobj, &test::cout1);
}What i would like to do is also have object and class/method as variable parameters.
I hope this makes it more clear :)
-
I will try my best to explain what i need: (it is for an uni project btw)
The User will be presented with a Text-Output and two (or more) buttons to choose a path. (Think of it like a story in which you can choose an option on what to do next)
My team is creating the scenarios as methods of classes.
I want to reuse the same buttons for the entire duration of the programs running time.
What i would like to do is give them a tool to connect their methods to the buttons when their scenario is beeing played.
After that i want to give the next scnario (next method) the ability to reconnect the buttons to their choices and so on.I know that is would be possible to do all of this manually with an endless switch/if construct (would probably easier) but i still want them to have minimal effort (maybe 1-3 lines of code for each connection).
What i have managed so far is to hand over the button-object as one of the parameters. (I haven't yet tried to call on the "connectButtonToMethod-Method from another class)
void Widget::execute()
{
QPushButton* buttonPointer = ui->pushButton;// void (test::*methodPtr)() = &test::cout1;
this->connectButtonToMethod(buttonPointer);
}void Widget::connectButtonToMethod(QPushButton* buttonPointer)
{
qDebug() << "Active connectButtonToMethod-Method";
qDebug() << buttonPointer << Qt::endl;disconnect(buttonPointer, &QPushButton::clicked, nullptr, nullptr);
connect(buttonPointer, &QPushButton::clicked, testobj, &test::cout1);
}What i would like to do is also have object and class/method as variable parameters.
I hope this makes it more clear :)
-
-
I will try my best to explain what i need: (it is for an uni project btw)
The User will be presented with a Text-Output and two (or more) buttons to choose a path. (Think of it like a story in which you can choose an option on what to do next)
My team is creating the scenarios as methods of classes.
I want to reuse the same buttons for the entire duration of the programs running time.
What i would like to do is give them a tool to connect their methods to the buttons when their scenario is beeing played.
After that i want to give the next scnario (next method) the ability to reconnect the buttons to their choices and so on.I know that is would be possible to do all of this manually with an endless switch/if construct (would probably easier) but i still want them to have minimal effort (maybe 1-3 lines of code for each connection).
What i have managed so far is to hand over the button-object as one of the parameters. (I haven't yet tried to call on the "connectButtonToMethod-Method from another class)
void Widget::execute()
{
QPushButton* buttonPointer = ui->pushButton;// void (test::*methodPtr)() = &test::cout1;
this->connectButtonToMethod(buttonPointer);
}void Widget::connectButtonToMethod(QPushButton* buttonPointer)
{
qDebug() << "Active connectButtonToMethod-Method";
qDebug() << buttonPointer << Qt::endl;disconnect(buttonPointer, &QPushButton::clicked, nullptr, nullptr);
connect(buttonPointer, &QPushButton::clicked, testobj, &test::cout1);
}What i would like to do is also have object and class/method as variable parameters.
I hope this makes it more clear :)
@tfre
IMHO, abstracting the connect statement makes things rather more complicated than easier. What’s wrong about the path class making its connections in the constructor? If it is essential to centralize this, it could be done by providing a base class that does the connection plumbing and the path specific classes just inherit from that base classs.
On a side note, please use the code formatting options in the editor for formatting code, that makes it much easier to read. Thanks! -
For whatever reason i was under the impression that i could only use the "connect(...)" function within the widget.cpp file. :|
Having realised that i can just have all of the buttons emit a signal when clicked and use slots in any class to recieve that and connect from there. :)) -
For whatever reason i was under the impression that i could only use the "connect(...)" function within the widget.cpp file. :|
Having realised that i can just have all of the buttons emit a signal when clicked and use slots in any class to recieve that and connect from there. :))@tfre
Good that you have found a pragmatic solution. Maybe mark the thread solved.Just two practical hints.
(1) In case you want to connect to a signal from a class that (for overhead reasons) doesn't inherit from
QObject
: You can connect to a lambda wrapper, that calls a member function:// Wrap member function in a lambda to avoid inheriting from QObject auto wrapper = [this](const QString &arg){myMemberFunction(arg); }; const auto result = QObject::connect(myLineEditPointer, &QLineEdit::textChanged, wrapper); qDebug() << __FUNCTION__ << __LINE__ << result;
(2) Debug
QObject::connect()
doesn't fatal out if the connection fails.
I find it very helpful toqDebug()
its return value (see above).
Guess why I find it so helpful: Because I occasionally miss the obvious. Just like you :-)