accessing button handlers in multiple python modules
02 Aug 2018 22:40 #115462
by cmorley
Replied by cmorley on topic accessing button handlers in multiple python modules
You might look at stepconf and mulitfilebuilder.py.
Stepconf loads multiple GLADE files.
Now stepconf only uses one python files for call backs but I think that is by design rather then by obligation.
Chris M
Stepconf loads multiple GLADE files.
Now stepconf only uses one python files for call backs but I think that is by design rather then by obligation.
Chris M
Please Log in or Create an account to join the conversation.
03 Aug 2018 14:39 #115524
by tripwire
Replied by tripwire on topic accessing button handlers in multiple python modules
Thanks for everyone's replies and suggestions.
It looked like the get_handlers() function would be the solution, because that function can be placed in each python module, but I couldn't get it to work because it seems the connect_signals() is the only place to actually connect the signals with handlers and I don't understand how get_handlers() helps with that.
But anyway, I did write a simpler version of the load_handlers() function in gscreen.py that gathers signal handlers from multiple python files and places them in a dictionary suitable for connect_signals(). I will post it later today...
It looked like the get_handlers() function would be the solution, because that function can be placed in each python module, but I couldn't get it to work because it seems the connect_signals() is the only place to actually connect the signals with handlers and I don't understand how get_handlers() helps with that.
But anyway, I did write a simpler version of the load_handlers() function in gscreen.py that gathers signal handlers from multiple python files and places them in a dictionary suitable for connect_signals(). I will post it later today...
Please Log in or Create an account to join the conversation.
03 Aug 2018 20:41 #115552
by tripwire
Replied by tripwire on topic accessing button handlers in multiple python modules
Here is a working version of a single Glade (xml) file referencing 2 python modules for it's signal handlers. The "magic" function is mainly a simplification of the load_handlers() function in gscreen.py.
The Glade file:
The "main" python file:
The "external" python module:
There are a few areas of uncertainty but it basically works. I'm certainly open to suggestions/clarifications to improve the code.
The Glade file:
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="2.18"/>
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkWindow" id="window1">
<property name="can_focus">False</property>
<signal name="destroy" handler="onDestroy" swapped="no"/>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
<object class="GtkButton" id="button1">
<property name="label" translatable="yes">button w. local handler</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="pressed" handler="onButton1Pressed" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button2">
<property name="label" translatable="yes">button w. external handler</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<signal name="pressed" handler="onButton2Pressed" swapped="no"/>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">label</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
The "main" python file:
#!/usr/bin/env python
import gtk
import external_module
# trampoline and load_handlers are used for custom displays
# (Copied from gscreen.py. I don't know how it works but seems necessary. Guru help?)
#
class Trampoline(object):
def __init__(self,methods):
self.methods = methods
print("Trampoline instance")
def __call__(self, *a, **kw):
for m in self.methods:
m(*a, **kw)
class Handler:
def onDestroy(self, *args):
print("quit app")
gtk.main_quit()
def onButton1Pressed(self, button):
print("Button1 Pressed")
self.builder.get_object("label1").set_text("Button 1 pressed")
# This function scans the given class object for signal handlers
# and adds them to a (class-global) dictionary, which we'll pass to
# connect_signals().
#
# This allows us to add signal handlers from "self" as well as from classes in external python modules
#
def _load_handlers(self, object):
#print("Registering handlers in object %s" % (object))
#for object in objects:
if isinstance(object, dict):
methods = dict.items()
else:
methods = map(lambda n: (n, getattr(object, n, None)), dir(object))
for method,f in methods:
if method.startswith('_'):
continue
if callable(f):
print("Registering callback %s" % (method))
if method in self.handlers:
# Note, I would sometimes get an error here but it would occur at the end of the iteration process.
# I found that I could replace the following line with a simple print warning.
self.handlers[method].append(f)
else:
self.handlers[method] = [f]
# Wrap lists in Trampoline, unwrap single functions
# (Copied from gscreen.py. I don't know how it or the Trampoline class works
# but it seems necessary.) Python guru help?
for n,v in list(self.handlers.items()):
try:
if len(v) == 1:
self.handlers[n] = v[0]
else:
self.handlers[n] = Trampoline(v)
except:
continue
# I kept getting the error, "no len(v) for type instancemethod" but that was always after the iteration was complete
# so I'm simply trapping and ignoring the error. (Guru help needed...)
def __init__(self):
self.builder = gtk.Builder()
self.builder.add_from_file("multi-module-test.glade")
# Get an instance of the external python module
self.xmod = external_module.externalHandler(self.builder)
# Create a dictionary to hold the signal-handler pairs
self.handlers = {}
# Call the magic function to load signal handlers from this and any other class module
#
self._load_handlers(self.xmod)
self._load_handlers(self)
#self.handlers = {"onButton1Pressed": self.onButton1Pressed, "onDestroy": self.onDestroy, "onButton2Pressed": self.xmod.onButton2Pressed}
self.builder.connect_signals(self.handlers)
self.window = self.builder.get_object("window1")
self.window.show_all()
try:
app = Handler()
except KeyboardInterrupt:
sys.exit(0)
gtk.main()
The "external" python module:
#!/usr/bin/env python
import gtk
class externalHandler:
def onButton2Pressed(self, button):
self.builder.get_object("label2").set_text("Button 2 pressed")
print("Button2 Pressed")
def __init__(self, builder):
self.builder = builder
There are a few areas of uncertainty but it basically works. I'm certainly open to suggestions/clarifications to improve the code.
Please Log in or Create an account to join the conversation.
03 Aug 2018 20:58 #115553
by cmorley
Replied by cmorley on topic accessing button handlers in multiple python modules
Glad you got something working.
In General, the magic function searches for callable functions, some are inside a class some are outside. It adjusts the function call signature to suit. Then passes that to connect_signals() to parse so GTK can find the functions.
I'm curious - why don't you use gscreen to load your GUI code - thats what it was made for.
Chris M
In General, the magic function searches for callable functions, some are inside a class some are outside. It adjusts the function call signature to suit. Then passes that to connect_signals() to parse so GTK can find the functions.
I'm curious - why don't you use gscreen to load your GUI code - thats what it was made for.
Chris M
Please Log in or Create an account to join the conversation.
03 Aug 2018 23:58 #115565
by tripwire
I was under the impression that gscreen is a pre-built GUI. I wanted to build one from scratch.
Replied by tripwire on topic accessing button handlers in multiple python modules
I'm curious - why don't you use gscreen to load your GUI code - thats what it was made for.
I was under the impression that gscreen is a pre-built GUI. I wanted to build one from scratch.
Please Log in or Create an account to join the conversation.
04 Aug 2018 00:35 #115570
by cmorley
Replied by cmorley on topic accessing button handlers in multiple python modules
Gscreen is infrastructure for controlling linuxcnc with a GTK2 interface.
There are many example screens -
gscreen
gaxis
spartan
industrial
etc.
all of them are gscreen based
Tere is a very basic example in the maunal:
linuxcnc.org/docs/2.7/html/gui/gscreen.h..._sheet_custom_screen
Chris M
There are many example screens -
gscreen
gaxis
spartan
industrial
etc.
all of them are gscreen based
Tere is a very basic example in the maunal:
linuxcnc.org/docs/2.7/html/gui/gscreen.h..._sheet_custom_screen
Chris M
Please Log in or Create an account to join the conversation.
04 Aug 2018 01:39 #115572
by tripwire
OK, thanks. I'll check that out...
Replied by tripwire on topic accessing button handlers in multiple python modules
Gscreen is infrastructure for controlling linuxcnc with a GTK2 interface.
OK, thanks. I'll check that out...
Please Log in or Create an account to join the conversation.
Moderators: HansU
Time to create page: 0.134 seconds