[Tutor] Pygubu designer question

Dennis Lee Bieber wlfraed at ix.netcom.com
Tue Feb 1 09:58:53 EST 2022


On Tue, 1 Feb 2022 17:53:02 +1100, Phil <phillor9 at gmail.com> declaimed the
following:

>I've spent most of the afternoon experimenting with Pygubu builder. I 
>haven't done much with Tkinter so my knowledge is a bit thin. Pygubu 
>uses a callback mechanism rather than the bind method that I'm more 
>familiar with. What I'm trying to achieve is read the contents of an 
>edit box when returned is pressed. I've done this in the past with 
>"entry.bind('Return', on_change)" if I remember correctly.
>

	Documentation of pygubu is extremely sparse -- this is the first I've
heard of it, and all I find on-line are equivalent to "Hello world". I also
don't use Tkinter so any following comments are essentially what I
understand from searches.

>This is taken from the file that Pygubu generates:

	First thing I got from searching is that the interface editor builds an
XML file describing the GUI... It might be helpful to see what /that/
contains (especially as image attachments are stripped, so the screen shots
of what you defined can not be provided without using a 3rd-party hosting
service and giving URLs).

	https://github.com/alejandroautalan/pygubu/wiki/CommandProperties is
the closest I come to information on this, and even this is an example that
doesn't require arguments, et al. to be passed.

>
>        self.entry1.configure(exportselection='true', relief='flat', 
>takefocus=False, validate='focusout')
>
>         self.entry1.delete('0', 'end')
>         self.entry1.insert('0', _text_)
>         self.entry1.place(anchor='sw', height='30', width='100', 
>x='10', y='100')
>         self.entry1.configure(validatecommand=self.callback)
>
>There are other entry1 options but I think validatecommand is all that I 
>need. I've searched the Internet for any clues but haven't turned up 
>anything relevant.
>

	Referring to the linked page, what did you enter in the properties for
the widget in question? Note: the example also has a tab for "bindings",
which may also be of concern.

>My programme includes the following:
>
># define the function callbacks
>def on_button1_click():
>     messagebox.showinfo('Message', 'You pressed me') # no problems here
>
>def callback(self):

	"self" is probably not what is being passed -- especially as the
indentation implies this is a top-level function, and not defined as part
of some class. If "self" were being passed, it (the "self" object) would
have to have been provided to whatever operation invokes the callback in
the first place.

>     #print(entry1.get()) # entry1 is unknown and self.entry1 didn't 
>help but that's another problem
>
	Did you just try printing "self" to find out just what you really
received. Possibly it IS the entry1 object apparently created earlier...

>         # Configure callbacks
>         callbacks = {
>             'on_button1_clicked': on_button1_click,
>             'callback' : callback # This doesn't look to be correct
>         }
>
>         builder.connect_callbacks(callbacks)

	As I understand the limited documentation, this associates the callback
function(s) with the names defined in the XML/editor property pages. So we
are back to: what did you call the "command" (or other property) when
defining the form/widget. {Hmmm, the property editor shows a separate field
for "class_" which might be how one links to methods [and gets a "self"
parameter?] vs a top-level function}.

>
>The word 'here' is printed when the programme is first run. I press the 

	Which implies that something is defined to call "callback" upon /some/
event happening... It sounds a lot like that is taking place on the
rendering of the widgets.

>button so that the entry box loses focus and that's when the error 
>message is displayed.
>
>The error message is Exception in Tkinter callback
>Traceback (most recent call last):
>   File "/usr/lib/python3.9/tkinter/__init__.py", line 1892, in __call__
>     return self.func(*args)
>TypeError: 'NoneType' object is not callable
>

	Whatever .func() is at that point is not a function... So either
somewhere in the code where a function needs to be /passed/ it was instead
called -- and returned a None which was passed... OR perhaps the XML/editor
properties defined a name for a callback, and you have not provided a
function linked to that name.

>I know that I need to read up on Tkinter but someone who may be familiar 
>with callbacks and Pygubu may be able to help.

	Callbacks are just functions that get registered to named events
associated with widgets. The GUI main loop processing receives the events
from the I/O system, matches the event name (and possibly widget) to a
table of Event:callback, and invokes the callback function -- typically
passing event specifics (widget object or arguments defined by the event
type) so the callback can act upon it.

	I do take exception to Mr. Gauld's statement that ALL GUIs function via
callbacks. While it is the norm for tk, GTK, and wX -- all of which
typically consist of one defining an "application" class and specifying
event name<>callback linkages on the form widgets, followed by creating an
instance of that call, and then calling a .run() or .mainloop() method,
there is a more basic model. The native programming on the Amiga (yes, I'm
invoking a 30 odd-year-old system) required one to code explicit dispatch
loops for windows. Said code style (in Python pseudo-code) would look
something like:

	while True:
		event = readNextEvent()
		if event.name == "something":
			somethingCallBack(event.value)
		elif event.name == "more":
			moreCallBack(event.value)
		...

	PySimpleGUI also uses a similar dispatch loop with Tkinter/GTK/wX --
masking the normal event loop style (I suspect internally there is one
callback that just queues events, so that the event read processes them in
queue order).


-- 
	Wulfraed                 Dennis Lee Bieber         AF6VN
	wlfraed at ix.netcom.com    http://wlfraed.microdiversity.freeddns.org/



More information about the Tutor mailing list