Gabor Gabor - 1 year ago 106
Python Question

draw horizontal bars on the same line

I have to draw a gantt resource type of chart.
Idea is to draw several horizontal bars on the same line (corresponding to a resource) each length represented by start date and and date

this is the expected result:
enter image description here

Altogether we have around 200 resources and max. 50 task for each to display, so performance is important.

Any idea?

In addition the tasks should be draggable by mouse.
An solution (Fat GUI (pyQt, wxwidget, tkinter, ...) or web based Flask, web2py, etc) is OK

Answer Source

Actually, I'm gonna cheat and post you something straight from the Matplotlib Documentation. This should get you started with draggable objects in mpl. you'll have to come up with your own dynamic object creation code...

full credit to the guys over at mpl:

# draggable rectangle with the animation blit techniques; see
import numpy as np
import matplotlib.pyplot as plt

class DraggableRectangle:
    lock = None  # only one can be animated at a time
    def __init__(self, rect):
        self.rect = rect = None
        self.background = None

    def connect(self):
        'connect to all the events we need'
        self.cidpress = self.rect.figure.canvas.mpl_connect(
            'button_press_event', self.on_press)
        self.cidrelease = self.rect.figure.canvas.mpl_connect(
            'button_release_event', self.on_release)
        self.cidmotion = self.rect.figure.canvas.mpl_connect(
            'motion_notify_event', self.on_motion)

    def on_press(self, event):
        'on button press we will see if the mouse is over us and store some data'
        if event.inaxes != self.rect.axes: return
        if DraggableRectangle.lock is not None: return
        contains, attrd = self.rect.contains(event)
        if not contains: return
        print('event contains', self.rect.xy)
        x0, y0 = self.rect.xy = x0, y0, event.xdata, event.ydata
        DraggableRectangle.lock = self

        # draw everything but the selected rectangle and store the pixel buffer
        canvas = self.rect.figure.canvas
        axes = self.rect.axes
        self.background = canvas.copy_from_bbox(self.rect.axes.bbox)

        # now redraw just the rectangle

        # and blit just the redrawn area

    def on_motion(self, event):
        'on motion we will move the rect if the mouse is over us'
        if DraggableRectangle.lock is not self:
        if event.inaxes != self.rect.axes: return
        x0, y0, xpress, ypress =
        dx = event.xdata - xpress
        dy = event.ydata - ypress

        canvas = self.rect.figure.canvas
        axes = self.rect.axes
        # restore the background region

        # redraw just the current rectangle

        # blit just the redrawn area

    def on_release(self, event):
        'on release we reset the press data'
        if DraggableRectangle.lock is not self:
            return = None
        DraggableRectangle.lock = None

        # turn off the rect animation property and reset the background
        self.background = None

        # redraw the full figure

    def disconnect(self):
        'disconnect all the stored connection ids'

fig = plt.figure()
ax = fig.add_subplot(111)
rects =, 20*np.random.rand(10))
drs = []
for rect in rects:
    dr = DraggableRectangle(rect)
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download