class_docstr: EmitterGroup instances manage a set of related
  :class:`EventEmitters <vispy.event.EventEmitter>`.
  Its primary purpose is to provide organization for objects
  that make use of multiple emitters and to reduce the boilerplate code
  needed to initialize those emitters with default connections.
  
  EmitterGroup instances are usually stored as an 'events' attribute on
  objects that use multiple emitters. For example::
  
       EmitterGroup  EventEmitter
               |       |
      Canvas.events.mouse_press
      Canvas.events.resized
      Canvas.events.key_press
  
  EmitterGroup is also a subclass of
  :class:`EventEmitters <vispy.event.EventEmitter>`,
  allowing it to emit its own
  events. Any callback that connects directly to the EmitterGroup will
  receive *all* of the events generated by the group's emitters.
  
  Parameters
  ----------
  source : object
      The object that the generated events apply to.
  auto_connect : bool
      If *auto_connect* is True (default), then one connection will
      be made for each emitter that looks like
      :func:`emitter.connect((source, 'on_' + event_name))
      <vispy.event.EventEmitter.connect>`.
      This provides a simple mechanism for automatically connecting a large
      group of emitters to default callbacks.
  emitters : keyword arguments
      See the :func:`add <vispy.event.EmitterGroup.add>` method.
class_docstr_tok: ["EmitterGroup","instances","manage","a","set","of","related",":","class",":","`","EventEmitters","<","vispy.event.EventEmitter",">","`",".","Its","primary","purpose","is","to","provide","organization","for","objects","that","make","use","of","multiple","emitters","and","to","reduce","the","boilerplate","code","needed","to","initialize","those","emitters","with","default","connections",".","EmitterGroup","instances","are","usually","stored","as","an","'events","'","attribute","on","objects","that","use","multiple","emitters",".","For","example",":",":","EmitterGroup","EventEmitter","|","|","Canvas.events.mouse_press","Canvas.events.resized","Canvas.events.key_press","EmitterGroup","is","also","a","subclass","of",":","class",":","`","EventEmitters","<","vispy.event.EventEmitter",">","`",",","allowing","it","to","emit","its","own","events",".","Any","callback","that","connects","directly","to","the","EmitterGroup","will","receive","*","all","*","of","the","events","generated","by","the","group","'s","emitters",".","Parameters","--","--","--","--","--","source",":","object","The","object","that","the","generated","events","apply","to",".","auto_connect",":","bool","If","*","auto_connect","*","is","True","(","default",")",",","then","one","connection","will","be","made","for","each","emitter","that","looks","like",":","func",":","`","emitter.connect","(","(","source",",","'on_","'","+","event_name",")",")","<","vispy.event.EventEmitter.connect",">","`",".","This","provides","a","simple","mechanism","for","automatically","connecting","a","large","group","of","emitters","to","default","callbacks",".","emitters",":","keyword","arguments","See","the",":","func",":","`","add","<","vispy.event.EmitterGroup.add",">","`","method","."]
docstr: Add one or more EventEmitter instances to this emitter group.
  Each keyword argument may be specified as either an EventEmitter
  instance or an Event subclass, in which case an EventEmitter will be
  generated automatically::
  
      # This statement:
      group.add(mouse_press=MouseEvent,
                mouse_release=MouseEvent)
  
      # ..is equivalent to this statement:
      group.add(mouse_press=EventEmitter(group.source, 'mouse_press',
                                         MouseEvent),
                mouse_release=EventEmitter(group.source, 'mouse_press',
                                           MouseEvent))
docstr_tok: ["Add","one","or","more","EventEmitter","instances","to","this","emitter","group",".","Each","keyword","argument","may","be","specified","as","either","an","EventEmitter","instance","or","an","Event","subclass",",","in","which","case","an","EventEmitter","will","be","generated","automatically",":",":","#","This","statement",":","group.add","(","mouse_press=MouseEvent",",","mouse_release=MouseEvent",")","#","..","is","equivalent","to","this","statement",":","group.add","(","mouse_press=EventEmitter","(","group.source",",","'mouse_press","'",",","MouseEvent",")",",","mouse_release=EventEmitter","(","group.source",",","'mouse_press","'",",","MouseEvent",")",")"]
code: def add(self, auto_connect=None, **kwargs):
      """Add one or more EventEmitter instances to this emitter group.
      Each keyword argument may be specified as either an EventEmitter
      instance or an Event subclass, in which case an EventEmitter will be
      generated automatically::
  
          # This statement:
          group.add(mouse_press=MouseEvent,
                    mouse_release=MouseEvent)
  
          # ..is equivalent to this statement:
          group.add(mouse_press=EventEmitter(group.source, 'mouse_press',
                                             MouseEvent),
                    mouse_release=EventEmitter(group.source, 'mouse_press',
                                               MouseEvent))
      """
      if auto_connect is None:
          auto_connect = self.auto_connect
  
      # check all names before adding anything
      for name in kwargs:
          if name in self._emitters:
              raise ValueError(
                  "EmitterGroup already has an emitter named '%s'"
                  % name
              )
          elif hasattr(self, name):
              raise ValueError(
                  "The name '%s' cannot be used as an emitter; "
                  "it is already an attribute of EmitterGroup" % name
              )
  
      # add each emitter specified in the keyword arguments
      for name, emitter in kwargs.items():
          if emitter is None:
              emitter = Event
  
          if inspect.isclass(emitter) and issubclass(emitter, Event):
              emitter = EventEmitter(
                  source=self.source, type=name, event_class=emitter
              )
          elif not isinstance(emitter, EventEmitter):
              raise Exception(
                  "Emitter must be specified as either an "
                  "EventEmitter instance or Event subclass. "
                  "(got %s=%s)" % (name, emitter)
              )
  
          # give this emitter the same source as the group.
          emitter.source = self.source
  
          setattr(self, name, emitter)
          self._emitters[name] = emitter
  
          if auto_connect and self.source is not None:
              emitter.connect(
                  (self.source, self.auto_connect_format % name)
              )
  
          # If emitters are connected to the group already, then this one
          # should be connected as well.
          if self._emitters_connected:
              emitter.connect(self)
  
imports: from __future__ import division
  from collections import OrderedDict
  import inspect
  import traceback
  import weakref
  from .logs import logger, _handle_exception
label_desc: Use image node_id 4 for calling the EmitterGroup obj's underlying member method code with example usage: obj.add(auto_connect) without return types