Home > Mobile >  How to enable Figurecanvaskivyagg fit MDBoxLayout automatically?
How to enable Figurecanvaskivyagg fit MDBoxLayout automatically?

Time:12-11

I was trying to use display seaborn plot in kivy. Sometime the figure cann't fit into the MDBoxLayout. I checked the sizes of FigureCanvasKivyAgg and MDBoxLayout. But in the MDBoxLayout, the figure is not cropped. Is there a way to enable the plot to fit the MDBoxLayout automatically? Thanks in advance.

enter image description here

Platform: Windows 10 Python version: 3.7 Required packages:

certifi==2021.10.8
charset-normalizer==2.0.9
cycler==0.11.0
docutils==0.18.1
fonttools==4.28.3
idna==3.3
Kivy==2.0.0
kivy-deps.angle==0.3.0
kivy-deps.glew==0.3.0
kivy-deps.sdl2==0.3.1
Kivy-Garden==0.1.4
kivymd==0.104.2
kiwisolver==1.3.2
matplotlib==3.1.1
numpy==1.21.4
packaging==21.3
pandas==1.3.4
Pillow==8.4.0
Pygments==2.10.0
pyparsing==3.0.6
pypiwin32==223
python-dateutil==2.8.2
pytz==2021.3
pywin32==302
requests==2.26.0
scipy==1.7.3
seaborn==0.11.2
setuptools-scm==6.3.2
six==1.16.0
tomli==1.2.2
urllib3==1.26.7

Python code:

import logging

from kivymd.app import MDApp
from kivy.lang import Builder
import seaborn as sns
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
from kivymd.uix.tab import MDTabsBase
from kivymd.uix.floatlayout import MDFloatLayout


class Tab(MDFloatLayout, MDTabsBase):
    '''Class implementing content for a tab.'''
    #content_text = StringProperty("")

class MainApp(MDApp):
    def __init__(self, **kwargs):
        super(MainApp, self).__init__(**kwargs)
        self.kv = Builder.load_string('''
#CustomTab@FloatLayout MDTabsBase:
#    
Screen: 
    MDTabs:
        Tab:
            title: "Tab 2"
            content_text: f"This is an example text for {self.title}"
                
            ScrollView:
                do_scroll_y: True
                MDGridLayout:
                    cols: 2
                    spacing: "10dp"
                    MDBoxLayout:
                        id: xxx
                        MDRaisedButton:
                            id: button4read_mtx
                            text: "Draw"
                            opposite_colors: True
                            on_release: app.plot_violin()
                            disabled: False
                        MDRaisedButton:
                            id: button4size
                            text: "Size"
                            opposite_colors: True
                            on_release: app.print_size()
                            disabled: False
                    MDBoxLayout:
                        size_hint: (0.5, None)
                        height: self.size[0]
                        id: mdbl4plot
                        orientation: "vertical"
                        #size_hint: (1,3)
                        #height: "400dp"
                        id: mdbl4plot
        Tab:
            title: "Tab 2"
''')

    def build(self):
        return self.kv
    def plot_violin(self):
        self.root.ids.mdbl4plot.clear_widgets()
        sns.set_theme(style="whitegrid")
        tips = sns.load_dataset("tips")
        ax = sns.violinplot(x="day", y="total_bill", data=tips)
        ax.figure.set_figheight(1)
        ax.figure.set_figwidth(1)
        #ax.set_autoscale_on(True)
        ax.autoscale(tight=True)
        figagg=FigureCanvasKivyAgg(ax.figure)
        print(figagg)
        #print(dir(figagg))
        logging.info("figagg size: " str(figagg.size))
        print(figagg.size_hint)
        logging.info("mdbl4plot size: " str(self.root.ids.mdbl4plot.size))
        self.root.ids.mdbl4plot.add_widget(figagg)
    def print_size(self):
        print("mdbl4plot size"   str(self.root.ids.mdbl4plot.size))

if __name__ == '__main__':
    MainApp().run()

CodePudding user response:

Seems like a bug in either matplotlib or FigureCanvasKivyAgg, but you may be able to work around it by using the tight_layout() method. Try replacing the two lines:

    ax.figure.set_figheight(1)
    ax.figure.set_figwidth(1)

with:

    ax.figure.tight_layout(pad=5)

I came up with a pad value of 5 by trial and error.

  • Related