Para agregar algo que quizás no sea necesario, pero me parece que queda pendiente.
Nota que add() recibe 1 solo argumento, no dos. El argumento de add() es una tupla de dos valores, de ahí que sea necesario usar doble paréntesis:
add(-1, 10) # dos argumentos, -1 y 10
add((-1, 10)) # 1 argumento, la tupla (-1, 10)
Y para resumir la respuesta a la primera pregunta:
Código Python:
Ver originalsuper(Ejemplo, obj).__init__(parent, title=title, size=(390, 350))
Quiere decir algo como:
Entre todos los ancestros de la clase Ejemplo (clases de las que herede, y todo el árbol hasta "object"), busca la primera que implemente un método __init__ (salteando a la propia Ejemplo), y llama a ese método con los parámetros dados. Además, llama a ese método __init__ encontrado como si fuese un método de obj.
Basicamente es llamar a un método de una clase padre, solo que un poco más complicado porque Python permite herencia múltiple, y tiene la flexibilidad añadida de que, si quiero, puedo hacerlo desde fuera de la clase Ejemplo, porque super() es una función global.