Позиционирование элемента Matplotlib - PullRequest
0 голосов
/ 03 мая 2020

Я пытаюсь встроить (полярную) радиолокационную карту в окно Tkinter, но столкнулся с некоторыми проблемами при позиционировании некоторых элементов в matplotlib figure.

Вот мой код:

from math import pi
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import tkinter as tk
from random import randint

def draw_diagram(categories, values, overlay, fig):
    fig.clear()
    length = len(values)
    ax = setup_ax(fig, categories)
    draw(values, ax, length, fill='red')
    draw(overlay, ax, length, fill='orange', label='Potential')
    l = ax.legend(bbox_to_anchor=(1.15, 1.15), loc="upper right")

def setup_ax(fig, categories):
    ax = fig.add_subplot(111, polar=True)
    ax.set_theta_offset(pi / 2)
    ax.set_theta_direction(-1)
    ax.set_yticklabels([])
    ax.set_xticklabels(categories)
    ax.set_ylim(0, 100)
    return ax

def draw(values, ax, length, fill, label='Current'):
    x_as = [n / float(length) * 2 * pi for n in range(length)]    
    ax.plot(x_as, values, fill, linewidth=0.5, linestyle='solid', label=label, zorder=-1)
    ax.fill(x_as, values, fill, alpha=0.3)
    for lbl, i in zip(ax.get_xticklabels(), range(length)):
        angle = i / float(length) * 2 * pi
        if angle in (0, pi):
            lbl.set_horizontalalignment('center')
        elif 0 < angle < pi:
            lbl.set_horizontalalignment('left')
        else:
            lbl.set_horizontalalignment('right')

win = tk.Tk()
win.rowconfigure(0, weight=1)
win.columnconfigure(0, weight=1)
win.geometry('300x300')

frame = tk.Frame(win)
frame.rowconfigure(0, weight=1)
frame.columnconfigure(0, weight=1)
frame.grid(sticky='nesw')

fig = Figure(dpi=100)
draw_diagram(['LONG HEADING HERE'] * 8, [65]*8, [90]*8, fig)
graph_canvas = FigureCanvasTkAgg(fig, master=frame)
graph_canvas.draw()
graph_canvas.get_tk_widget().grid(sticky='nesw')
win.mainloop()

Вывод:

Matplotlib image produced

Мои основные проблемы:

  1. xlabels может быть длинным, и я не уверен, как заставить их автоматически помещаться в рамку, будь то путем уменьшения размера шрифта, их поворота или разделения текста на несколько строк.
  2. Легенда должна быть в верхней - правый угол рамки (не диаграммы), как показано в примерах ниже.
  3. Не такая уж крупная сделка, но линия, проведенная вокруг каждого графика, не закрыта с одной стороны.

Мои другие попытки

# 1

Адаптируя код из этот ответ вместо этого, чтобы метод draw был:

def draw(values, ax, length, fill, label='Current'):
    x_as = [n / float(length) * 2 * pi for n in range(length)]    
    ax.plot(x_as, values, fill, linewidth=0.5, linestyle='solid', label=label,
            zorder=-1)
    ax.fill(x_as, values, fill, alpha=0.3)
    for lbl, i in zip(ax.get_xticklabels(), range(length)):
        angle = i / float(length) * 360
        x,y = lbl.get_position()
        lbl = ax.text(x,y+1, lbl.get_text(), transform=lbl.get_transform(),
                      ha=lbl.get_ha(), va=lbl.get_va())
        lbl.set_rotation(angle)
    ax.set_xticklabels([])

Дает :

Output 2

Я не уверен, как правильно расположить метки x. Распечатка x, y позиций каждой этикетки в for -l oop все дает 0 0.

# 2

Вращающиеся этикетки, угол которых не кратен 90 , с адаптированным кодом, поэтому функция draw:

def draw(values, ax, length, fill, label='Current'):
    x_as = [n / float(length) * 2 * pi for n in range(length)]    
    ax.plot(x_as, values, fill, linewidth=0.5, linestyle='solid', label=label,
            zorder=-1)
    ax.fill(x_as, values, fill, alpha=0.3)
    for lbl, i in zip(ax.get_xticklabels(), range(length)):
        angle = i / float(length) * 360
        if angle % 90 == 0:
            angle = 0
        else:
            angle = angle - 90
        x,y = lbl.get_position()
        lbl = ax.text(x,y+1, lbl.get_text(), transform=lbl.get_transform(),
                      ha=lbl.get_ha(), va=lbl.get_va())
        lbl.set_rotation(angle)

Дает (с оригиналом для сравнения):

Output 3

Помимо других вопросов, легенда теперь также неуместна, чего я хотел бы избежать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...