2017-10-18 1 views
1

Konnte nichts finden, wie man die Checkbuttons 'box' in Matplotlib in eine Zeile vs in einem Spaltenformat formatiert. Ich fand heraus, ich könnte die tatsächlichen Kontrollkästchen und die Etiketten (mit get_position auf den Text-Objekten und set_xy auf den Rechteck-Objekten) verschieben, aber das scheint nicht der beste Weg, wie ich sie separat verschiebe und sie scheinen nicht das gleiche Koordinatensystem verwenden.Matplotlib Checkbuttons in einer Reihe

Gibt es eine einfachere Möglichkeit, meine Checkbuttons von einer Spalte in eine Zeile zu drehen?

Antwort

2

Es gibt keine einfache Möglichkeit, die Kontrollkästchen in einer Zeile anstelle einer Spalte anzuzeigen. Der Grund ist, dass sie in Bezug auf Achsenkoordinaten fest codiert sind. Natürlich können Sie die Teile herum bewegen, aber das klingt ziemlich umständlich.

Eine andere Option wäre, die Klasse CheckButtons zu unterklassifizieren und ein eigenes Layout zu implementieren. Jetzt muss viel beachtet werden, wie viel Platz zwischen Etiketten und Checkboxen usw. ist.

Auf der anderen Seite gibt es tatsächlich ein nettes Matplotlib-Element, das alle Knöpfe haben würde Wende betreffend Labelspacing, Padding etc. verfügbar und das funktioniert mit Zeilen und Spalten: der Legende.

Jetzt dachte ich, warum nicht die Kontrollkästchen als klickbare Legende erzeugen. Dies ist, was der Code unten tut. Es Unterklassen CheckButtons und erstellt eine Legende in seine Achsen. Diese Legende enthält die Boxen als Griffe und die Beschriftungen als Beschriftungen. Die gute Sache ist jetzt, dass Sie in der Lage sind, die Checkbuttons nach Ihren Wünschen mit allen Werkzeugen der usual legend allows for: fontsize, markerfirst, frameon, fancybox, shadow, framealpha, facecolor, edgecolor, mode, bbox_transform, title, borderpad, labelspacing, handlelength, handletextpad, borderaxespad, columnspacing zu gestalten.

Die wichtigste hier ist sicher n_col, die Sie auf die Anzahl der Spalten setzen können, die Sie möchten.

Ich nahm die CheckButtons example von der Matplotlib-Seite und verwendet diese benutzerdefinierte Checkbuttons-Klasse darauf.

import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib.widgets import CheckButtons,AxesWidget 

class PremiumCheckButtons(CheckButtons,AxesWidget): 
    def __init__(self, ax, labels, actives, linecolor="k", showedge=True, **kw): 
     AxesWidget.__init__(self, ax) 

     ax.set_xticks([]) 
     ax.set_yticks([]) 
     ax.set_navigate(False) 
     if not showedge: 
      ax.axis("off") 
     linekw = {'solid_capstyle': 'butt', "color" : linecolor} 
     class Handler(object): 
      def legend_artist(self, legend, orig_handle, fontsize, handlebox): 
       x0, y0 = handlebox.xdescent, handlebox.ydescent 
       height = handlebox.height 
       self.line1 = plt.Line2D([x0,x0+height],[y0,y0+height], **linekw) 
       self.line2 = plt.Line2D([x0,x0+height],[y0+height,y0], **linekw) 
       self.rect = plt.Rectangle((x0,y0),height, height, 
              edgecolor="k", fill=False) 
       handlebox.add_artist(self.rect) 
       handlebox.add_artist(self.line1) 
       handlebox.add_artist(self.line2) 
       return [self.line1, self.line2, self.rect] 

     self.box = ax.legend(handles = [object() for i in labels ], 
          labels = labels, 
          handler_map={object: Handler()}, **kw) 

     self.lines = [(h[0],h[1]) for h in self.box.legendHandles] 
     self.rectangles = [h[2] for h in self.box.legendHandles] 
     self.labels = self.box.texts 

     for i,(l1,l2) in enumerate(self.lines): 
      l1.set_visible(actives[i]) 
      l2.set_visible(actives[i]) 

     self.connect_event('button_press_event', self._clicked) 

     self.cnt = 0 
     self.observers = {} 


t = np.arange(0.0, 2.0, 0.01) 
s0 = np.sin(2*np.pi*t) 
s1 = np.sin(4*np.pi*t) 
s2 = np.sin(6*np.pi*t) 

fig, (rax,ax) = plt.subplots(nrows=2, gridspec_kw=dict(height_ratios = [0.1,1])) 
l0, = ax.plot(t, s0, visible=False, lw=2) 
l1, = ax.plot(t, s1, lw=2) 
l2, = ax.plot(t, s2, lw=2) 
plt.subplots_adjust(left=0.2) 

check = PremiumCheckButtons(rax, ('2 Hz', '4 Hz', '6 Hz'), (False, True, True), 
          showedge = False, ncol=3) 


def func(label): 
    if label == '2 Hz': 
     l0.set_visible(not l0.get_visible()) 
    elif label == '4 Hz': 
     l1.set_visible(not l1.get_visible()) 
    elif label == '6 Hz': 
     l2.set_visible(not l2.get_visible()) 
    fig.canvas.draw_idle() 
check.on_clicked(func) 

plt.show() 

enter image description here

Zusätzlich zu den all legend Argumente nimmt die oben PremiumCheckButtons Klasse linecolor Die Argumente, die Farbe des x der Checkbox (standardmäßig schwarz) und showedge einzustellen. showedge kann verwendet werden, um den Rahmen der Achsen anzuzeigen, in denen sich die "Legende" befindet, und kann eingeschaltet werden, um diese Achsen für Debugging-Zwecke zu sehen. Z.B. Sie müssen sicherstellen, dass die vollständige Legende innerhalb der Achsen liegt, damit die Schaltflächen anklickbar sind.

+0

Dies ist ein WOW! Sehr coole Erweiterung. –