PDA

View Full Version : get function called by QPushbutton?



Nfrancisj
25th May 2017, 01:00
Hi,
Is there a way to get the function name that was executed by a button?


thanks

d_stranz
25th May 2017, 03:37
Is there a way to get the function name that was executed by a button?

I assume you mean, "When my slot is invoked, which signal from which object was the one that invoked it?"

Inside your slot:


You get the QObject pointer of the object that emitted the signal using QObject::sender()
You get the index (signal number) of the signal using QObject::senderSignalIndex()
Using the sender's QObject pointer, you get its QMetaObject pointer using QObject::metaObject()
Using the QMetaObject pointer and the index, you get the QMetaMethod using QMetaObject::method()
Using QMetaMethod, you get the function (signal) name (as a QByteArray) using QMetaMethod::name()
You can turn the QByteArray into a QString using the QString constructor that takes a QByteArray reference as argument



Easy. But if that's not what you wanted, your question doesn't make a lot of sense.

Nfrancisj
25th May 2017, 06:09
Sorry, was in a rush.
Say I have a window with a button. When I clicked the button it changes the text on the button to "Clicked" via a function.



myBtn = QPushButton("Click Me")
myBtn.clicked.connect(changeLabel)

def changeLabel()
myBtn.setText("Clicked")


I have the button object, what I'd like to get is the "changeLabel" function, so I can call it via another button/function.
Here is my issue... I have a software, Nuke, and it's written in PyQt/Pyside. The developers documented everything in Nuke and how to access it, except, they left one out. The PAUSE button. And... guess what...my company wants me to build a tool that requires me to mess with the PAUSE. It is a QPushButton, and I want to know the name of the function that gets called when I click it.

I'll take a look at your suggestions tomorrow at work.. QMetaMethod has peaked my interest.

jefftee
25th May 2017, 15:34
The function that changes the label's text is setText, no?

d_stranz
25th May 2017, 16:06
It is a QPushButton, and I want to know the name of the function that gets called when I click it.

Well, the code I posted will get you the name of the button's method that is called when it is clicked, but you have to be in a slot connected to that button in order to find that out. I think you are asking the reverse question: "I have a button instance, what slots is its clicked() signal connected to?"

That's the (unfortunately) protected method QObject::receivers(), which you can't call from the outside even if you do have a pointer to the button instance. Your Nuke QPushButton is a concrete class and you can't derive from it.

So basically, from my original code you can find out "Who's calling me?", but unless you can derive from QPushButton you can't find out "Who is this button calling?"

jefftee
25th May 2017, 16:14
Rather than try to figure out the name of the slot, couldn't/shouldn't they just use QPushButton::setText to change the button's text? I'm not seeing the value in finding and executing the slot as opposed to just setting the text directly.

Nfrancisj
25th May 2017, 18:21
@JeffTee : The code I posted is just a quick mock-up that describes the actual issue. I'm not trying to setText, instead, I'm trying to get the function called by the Slot. What I'm trying to get is LINE 4 in my code example.

@d_stranz :


So basically, from my original code you can find out "Who's calling me?", but unless you can derive from QPushButton you can't find out "Who is this button calling?"


BUMMER!! Well..that blows. :(

OKAY...Plan B.
I haven't researched this yet, but I'll ask while I have your ear. Is there a way, given I have the button object, to execute/push the button via code? Say I add another button to my simple code example where the clicked SIGNAL of the second button executes the clicked SLOT of the first button.

Thanks

Nfrancisj
26th May 2017, 03:42
@JeffTee.
Ahh...I apologize. I now understand what your comment means. Sometimes the members in the Nuke framework are modified/masked and what is .setText() might be something else.

Although I will continue to search, for now D_Stranz suggestion is what will do what I want.
I'm using QMetaObject and the invoke method to trigger the button.

d_stranz
26th May 2017, 16:43
Is there a way, given I have the button object, to execute/push the button via code?

Sure. QAbstractButton::click() is a public (slot) method. You can call it just like any other public method of a class if you have a pointer to the instance of the class. So if you implement your own Pause button, you can add a connection between your button's clicked() signal and the Nuke button's click() slot. When you click your button, it -should- do the same things as if you had pushed Nuke's button instead because the Nuke button will in turn issue its own clicked() signal to all of the slots connected to it. (This assumes that these other slots don't check who the caller is before doing their thing).

If you think about it, this kind of functionality is required in order to do automated GUI testing. The test code has to be able to emulate what a real user with a mouse would do - like push buttons, for one.

Nfrancisj
27th May 2017, 06:25
Oh nice! Didn't know about .click(). Good to know... I was using .invoke(). Seems to do the same thing. Know of any benefit for choosing one over the other?

I'm not sure if this is okay or not, but I'm going to ask another question. í ½í¸„ If it's not, I'll start a new thread.

Other than the .objectName(), is there any other way to ID a QWidget? I'm noticing a lot of Qwidgets in Nuke have no name.

d_stranz
28th May 2017, 15:58
Other than the .objectName(), is there any other way to ID a QWidget? I'm noticing a lot of Qwidgets in Nuke have no name.

Names are optional. In C++, I usually just keep pointers to widgets I want to remember.


Oh nice! Didn't know about .click()

If you don't see something you are looking for in a Qt class, -always- check the base classes. The methods that provide convenient things that apply to all derived types are often found there.

Nfrancisj
30th May 2017, 21:50
Names are optional. In C++, I usually just keep pointers to widgets I want to remember.

right, but I didn't build the software. I'm getting the widget using .parent() and . children(), then storing them in a list and iterating through to find what I want. Alot of the widgets dont have names like you said.
The problem is I am assuming the array get populated the same everytime and I'm using the index to access the child.

Is there any other way to id a widget?

d_stranz
31st May 2017, 00:55
QObject::objectName() and the pointer to the instance are the only ways I know of.

If you are looking for a specific widget of a specific type (like a QPushButton) you can always iterate through all the children, do a qobject_cast< QPushButton * > on each, and then call text() for those with non-null pointers until you find the one you want. If the widget text is internationalized, this is harder to do reliably, but if you are targeting a single language version then it won't be so bad.

If the parent widget is built the same way each time, then I think the index would be stable. If the widget is dynamic (eg. different versions for different players, levels of the game, etc.) then there's no guarantee of anything.