Используя библиотеку Gtk+,  Drawing Area Widget и cairo.Context объект загружаем шарик (картинку) в окно программы и создаём движение как в пинг-понг. Создаём программу на Python помощью конструктора Glade и IDE IDLE.

В IDE Glade создайте новый проект.

Создайте Окно класса GtkWindow, на вкладке Основные свойства присвойте ему идентификатор ID: window. Там же, на вкладке Основные свойства присвойте окну Заголовок GtkDrawingArea и проставьте размер и галочки Ширина по умолчанию 800 и Высота по умолчанию 600. На вкладке Сигналы в разделе GtkWidget событию destroy задайте обработчик on_destroy.

Поверх окна window разместите Display GtkDrawingArea. На вкладке Основные свойства задайте ему имя colorDraw. 

В IDE Glade сохраните проект под именем, например, examle. В результате вы получите файл example.glade:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
  <requires lib="gtk+" version="3.20"/>
  <object class="GtkWindow" id="window">
    <property name="can_focus">False</property>
    <property name="hexpand">True</property>
    <property name="vexpand">True</property>
    <property name="title" translatable="yes">GtkDrawingArea</property>
    <property name="default_width">800</property>
    <property name="default_height">600</property>
    <signal name="destroy" handler="on_destroy" swapped="no"/>
    <child>
      <placeholder/>
    </child>
    <child>
      <object class="GtkDrawingArea" id="colorDraw">
        <property name="visible">True</property>
        <property name="can_focus">False</property>
      </object>
    </child>
  </object>
</interface>

В текстовом редакторе или, например, в IDE IDLE напишите программу example.py следующего содержания:

#!/usr/bin/python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: t; c-basic-offset: 4; tab-width:$

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GObject
import os, random, time, math, cairo
XML_FILE = "example.glade"

x = y = xv = yv = 0
pi = 0.0

def create_from_png(image_name):
    # ensure we can read image when working from another dir
    cwd = os.getcwd()
    dir_path = os.path.dirname(os.path.realpath(__file__))
    os.chdir(dir_path)
    ims = cairo.ImageSurface.create_from_png(image_name)
    os.chdir(cwd)
    return ims

img = create_from_png('blue.png')

def do_draw(self, cr):
    global pi, x, y, xv, yv, img
    width = self.get_allocated_width()
    height = self.get_allocated_height()
    if pi == .0:
        pi = math.pi
        x = random.randint(1, width-50)
        y = random.randint(1, height-50)
        xv = random.randint(-6 , 6)
        yv = random.randint(-6 , 6)

    cr.set_source_surface(img, x, y)    
    cr.paint()

    x += xv
    y += yv
    xv = -xv if (x > width-49 or x < 0) else xv
    yv = -yv if (y > height-49 or y < 0) else yv

def timeout():
    time.sleep(0.005)
    colordr.queue_draw()
    return True

class Handler:
    def on_destroy(self, *args):
        Gtk.main_quit()

builder = Gtk.Builder()
builder.add_from_file(XML_FILE)
builder.connect_signals(Handler())
win = builder.get_object("window")
colordr = builder.get_object("colorDraw")
colordr.connect('draw', do_draw)
win.show_all()
GObject.idle_add(timeout)
Gtk.main()

Наш проект состоит их 2-х файлов example.py иexample.glade. Теперь можно запускать нашу программу через терминал в папке проекта или через IDE IDLE:

dior@U18pro:~/Python/Example/Gtk Drawin Area$ ./example.py

Работает: