[PYTHON] Traitement de fichiers multiples avec Kivy + Matplotlib + Draw Graph sur GUI

En me référant à diverses informations sur le net, j'ai également étudié l'interface graphique et travaillé sur un programme d'interface graphique permettant d'afficher entrée / sortie + traitement + graphique.

Environnement d'exécution

Windows10 Python 3.7.7 Kivy 1.11.1 L'interface graphique semble être populaire ces dernières années, j'ai donc défié Kivy.

GUI fait

La ligne supérieure est un bouton pour l'entrée / sortie et le traitement des fichiers. Sous le bouton se trouve la zone d'affichage du graphique. Le graphique est sélectionné et affiché dans le menu déroulant sur la gauche.

AnalysisGUI.jpg

Code créé

Voici les détails du code. Le code côté kivy décrit le contenu lié à l'interface graphique (mise en page, sélection de fichier, fonction à appeler lorsqu'un bouton est pressé, etc.), et le code côté Python décrit le traitement réel. Premier Python

main.py


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import openpyxl
import os

from kivy.uix.boxlayout import BoxLayout
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.properties import ObjectProperty 
from kivy.uix.popup import Popup
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg

class LoadDialog(FloatLayout):
    load = ObjectProperty(None)
    cancel = ObjectProperty(None)
    Analysis = ObjectProperty(None)        
    current_dir = os.path.dirname(os.path.abspath(__file__))
 
class SaveDialog(FloatLayout):
    save = ObjectProperty(None)
    text_input = ObjectProperty(None)
    cancel = ObjectProperty(None)
    current_dir = os.path.dirname(os.path.abspath(__file__))  

class MainBoard(BoxLayout):
    file_name = ObjectProperty(None)
    info = ObjectProperty(None)
    bar_graph = ObjectProperty(None)
    lbl4spinner = ObjectProperty([])
    
    def __init__(self, **kwargs):
        super(MainBoard, self).__init__(**kwargs)
        self.master_flg = 0
        self.lbl=[]
        self.Data=[]
        
    def dismiss_popup(self):
        self._popup.dismiss()

    def show_load(self):
        content = LoadDialog(load=self.load, cancel=self.dismiss_popup, Analysis=self.Analysis)
        self._popup = Popup(title="Load file", content=content,size_hint=(0.9, 0.9))
        self._popup.open()

    def show_save(self):
        if self.master_flg==0:
            self.info.text = 'Load masterfile first, please'
        else:
            content = SaveDialog(save=self.save, cancel=self.dismiss_popup)
            self._popup = Popup(title="Save file", content=content, size_hint=(0.9, 0.9))
            self._popup.open()

    def load(self, path, filename, chkflg):
        try:
            if chkflg==1:
                self.file_name.text=str(filename.pop(0))
            else:
                self.file_name.text=str(filename[0])
        except Exception as e:
            self.info.text=str(type(e))+' : '+str(e) 
            
        Matrix=pd.DataFrame([])
        for i in range(len(filename)):
            NewData = pd.read_excel(filename[i])
            tmp_Data=NewData.iloc[0:,1:]
            tmp_Data.index=NewData.iloc[:,0]
            Matrix=pd.concat([Matrix,tmp_Data])
        
        self.lbl=list(Matrix.index)
        self.Data = Matrix
        self.dismiss_popup()
    
    def save(self, path, dirname):
        with pd.ExcelWriter(os.path.join(path, dirname)) as writer:
            self.Data.to_excel(writer)  
        self.dismiss_popup()         
    
    def Analysis(self):
        try:
            self.Data=self.Data*2
            self.lbl4spinner=map(str,self.lbl)#Liste à passer au spinner
            self.master_flg=1
            self.info.text = 'Analysis completed!'
        except Exception as e:
            self.info.text=str(type(e))+' : '+str(e) 
    
    def on_spinner_select(self,text):
        row_no=self.lbl.index(text)
        Forgraph=self.Data.iloc[row_no,:]
        plt.clf()
        bar_plt=plt.bar(Forgraph.index, Forgraph)
        self.ids.bar_graph.clear_widgets()
        self.ids.bar_graph.add_widget(FigureCanvasKivyAgg(plt.gcf()))
        
class MainApp(App):
    title = 'une analyse'
    def build(self):
        return MainBoard()
        
if __name__ == '__main__':
    MainApp().run()

Puis Kivy

main.kv


<MainBoard>:
    info: info
    file_name: file_name
    bar_graph: bar_graph
    
    
    BoxLayout:
        orientation: 'vertical'
        pos: root.pos
        size: root.size
        
        canvas.before:
            Color: 
                rgba: 0.9, 0.9, 0.9, 1
            Rectangle:
                pos: self.pos
                size: self.size
                
        Label:
            id : info
            text: 'load file first, please'
            size_hint_y: 0.1
            canvas.before:
                Color: 
                    rgba: 0, 0, 0, 1
                Rectangle:
                    pos: self.pos
                    size: self.size
            
        BoxLayout:
            orientation: 'horizontal'
            size_hint_y: 0.1
            
            TextInput:
                id: file_name
                font_size: 12
                size_hint_x: 0.7
                           
        BoxLayout:
            orientation: 'horizontal'
            size_hint_y: 0.1
            
            Button:
                text: 'Load & Analysis'
                size_hint_x: 0.2
                on_press: root.show_load()
                
            Button:
                text: 'Save data'
                size_hint_x: 0.2
                on_press: root.show_save()
                 
            Button:
                text: "Exit"
                id: btnExit
                size_hint_x: 0.2               
                on_press: app.root_window.close()  

        BoxLayout:
            orientation: 'horizontal'
            size_hint_y: 0.7
   
            Spinner:
                text: "No."
                values: root.lbl4spinner
                size_hint: 0.1, 0.1
                pos_hint: {'center_x': .5, 'center_y': .5}
                on_text: root.on_spinner_select(self.text)
                
            BoxLayout:
                id: bar_graph
                
<LoadDialog>:

    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"
            
        FileChooser:
            id: filechooser
            path:root.current_dir
            multiselect: True
            filters: ['*.xlsx']
            FileChooserIconLayout

        BoxLayout:
            size_hint_y: None
            height: 30
 
            Button:
                text: "Load selected file(s)"
                on_press: root.load(filechooser.path, filechooser.selection,0)
                on_release: root.Analysis()
                
            Button:
                text: "Load all files"
                on_press: root.load(filechooser.path,filechooser.files,1)
                on_release: root.Analysis()
            
            Button:
                text: "Cancel"
                on_release: root.cancel()
                
<SaveDialog>:
   
    BoxLayout:
        size: root.size
        pos: root.pos
        orientation: "vertical"
        
        BoxLayout:
            size_hint_y: 0.1
            Button:
                text: 'ListView'
                on_release: filechooser.view_mode = 'list'
            Button:
                text: 'IconView'
                on_release: filechooser.view_mode = 'icon'
                
        FileChooser:
            id: filechooser
            path:root.current_dir
            on_selection: dir_name.text = self.selection and self.selection[0] or ''
            filters: ['*.xls','*.xlsx']
            FileChooserListLayout

        TextInput:
            id: dir_name
            size_hint_y: None
            height: 30
            multiline: False

        BoxLayout:
            size_hint_y: None
            height: 30

            Button:
                text: "Save"
                on_release: root.save(filechooser.path, dir_name.text)         
                            
            Button:
                text: "Cancel"
                on_release: root.cancel()

Commentaire

Le programme de base utilise le Filechooser de Kivy. Filechooser lui-même a des documents officiels et des explications de nombreux ancêtres, il est donc omis. Je n'expliquerai que où j'ai trébuché.

En raison du flux, le programme ne coule pas du haut, mais il va et vient entre le code Kivy et le code Py, donc je vais expliquer le long du flux.

1 Sélection de fichiers

--Lorsque vous appuyez sur le bouton Load de l'interface graphique après avoir démarré le programme, la fonction Show Load sera appelée depuis le côté Kivy.

main.kv


            Button:
                text: 'Load & Analysis'
                size_hint_x: 0.2
                on_press: root.show_load()

main.py


    def show_load(self):
        content = LoadDialog(load=self.load, cancel=self.dismiss_popup, Analysis=self.Analysis)
        self._popup = Popup(title="Load file", content=content,size_hint=(0.9, 0.9))
        self._popup.open()

main.kv


        FileChooser:
            id: filechooser
            path:root.current_dir
            multiselect: True
            filters: ['*.xlsx']
            FileChooserIconLayout

--Placez 3 boutons en suivant le code ci-dessus. (1) Lors de la sélection et de la spécification d'un fichier lu en cliquant sur (filechooser.selection) (2) Lors de la lecture de tous les fichiers du répertoire courant (filechooser.files) (3) Bouton Annuler. Lorsque vous appuyez sur les boutons ① et ②, la fonction de chargement est appelée en premier. Le dernier numéro de l'argument de la fonction de chargement est le numéro d'identification (car il appelle la même fonction).

main.kv


        BoxLayout:
            size_hint_y: None
            height: 30
 
            Button:
                text: "Load selected file(s)"
                on_press: root.load(filechooser.path, filechooser.selection,0)
                on_release: root.Analysis()
                
            Button:
                text: "Load all files"
                on_press: root.load(filechooser.path,filechooser.files,1)
                on_release: root.Analysis()
            
            Button:
                text: "Cancel"
                on_release: root.cancel()

2 Lire le fichier

--Dans la fonction Load côté Python, utilisez l'adresse du fichier passé de Filechooser (passé au format List) pour extraire les données de xls. La partie suivante est le code pour afficher l'adresse sur l'interface graphique. --A ce moment, si vous lisez tous les fichiers du répertoire en même temps, soyez prudent car l'adresse du répertoire (les fichiers ne sont pas liés) se trouve au début de la liste. Pour cela, nous avons extrait la première section de la liste. --```excepté Ececpiion as e: La partie après `` `affiche le contenu lorsqu'une erreur se produit.

main.pv


    def load(self, path, filename, chkflg):
        try:
            if chkflg==1:
                self.file_name.text=str(filename.pop(0))
            else:
                self.file_name.text=str(filename[0])
        except Exception as e:
            self.info.text=str(type(e))+' : '+str(e) 

main.pv


        Matrix=pd.DataFrame([])
        for i in range(len(filename)):
            NewData = pd.read_excel(filename[i])
            tmp_Data=NewData.iloc[0:,1:]
            tmp_Data.index=NewData.iloc[:,0]
            Matrix=pd.concat([Matrix,tmp_Data])
        
        self.lbl=list(Matrix.index)
        self.Data = Matrix
        self.dismiss_popup()

3. 3. une analyse

--Dans LoadDialog du côté kivy, la fonction Analysis est appelée par ```on_release: root.Analysis () `` `après la fonction Load.

main.pv


    def Analysis(self):
        try:
            self.Data=self.Data*2
            self.lbl4spinner=map(str,self.lbl)#Liste à passer au spinner
            self.master_flg=1
            self.info.text = 'Analysis completed!'
        except Exception as e:
            self.info.text=str(type(e))+' : '+str(e) 

Quatre. affichage graphique

main.kv


            Spinner:
                text: "No."
                values: root.lbl4spinner
                size_hint: 0.1, 0.1
                pos_hint: {'center_x': .5, 'center_y': .5}
                on_text: root.on_spinner_select(self.text)
                
            BoxLayout:
                id: bar_graph

main.py


    def on_spinner_select(self,text):
        row_no=self.lbl.index(text)
        Forgraph=self.Data.iloc[row_no,:]
        plt.clf()
        bar_plt=plt.bar(Forgraph.index, Forgraph)
        self.ids.bar_graph.clear_widgets()
        self.ids.bar_graph.add_widget(FigureCanvasKivyAgg(plt.gcf()))

5.Save --Save est omis car il est traité de la même manière que Load.

6. Autre

main.py


class MainBoard(BoxLayout):
    file_name = ObjectProperty(None)
    info = ObjectProperty(None)
    bar_graph = ObjectProperty(None)
    lbl4spinner = ObjectProperty([])

main.kv


<MainBoard>:
    info: info
    file_name: file_name
    bar_graph: bar_graph

main.py


    def __init__(self, **kwargs):
        super(MainBoard, self).__init__(**kwargs)
        self.master_flg = 0
        self.lbl=[]
        self.Data=[]

Sites pris en charge

J'ai notamment évoqué les informations relatives à Kivy sur le site suivant. document officiel kivy: Filechooser Après tout, le premier est le document officiel. Désir de freelance Cela a été utile comme point de départ. La disposition de cette interface graphique est également mentionnée ici. blog narito Cela a été très utile pour comprendre la relation entre Kivy et Python. stackoverflow : Python - Kivy framework - Spinner values list Affichage de la liste sur Spinner, je pense que j'aurais été bloqué sans ce post.

Ce que je veux améliorer à l'avenir

J'utilise des identifiants pour le dessin graphique, mais je veux le décrire avec Object Propaty.

Recommended Posts

Traitement de fichiers multiples avec Kivy + Matplotlib + Draw Graph sur GUI
Dessinez le japonais avec matplotlib sur Ubuntu
Dessinez un graphique lâche avec matplotlib
Dessinez un graphique avec l'interface graphique PySimple
Comment dessiner un graphique à barres qui résume plusieurs séries avec matplotlib
Dessinez une surface plane avec un graphique 3D matplotlib
Dessinez un graphique en traitant avec Pandas groupby
[Python] Comment dessiner plusieurs graphiques avec Matplotlib
Dessinez une ligne de pliage / diagramme de dispersion avec python matplotlib pour fichier CSV (2 colonnes)
Graphique de bande avec matplotlib
[Python] Comment dessiner un graphique linéaire avec Matplotlib
Étudier les mathématiques avec Python: dessiner un graphe sympy (scipy) avec matplotlib
Graphique des données Excel avec matplotlib (1)
Dessinez un graphique avec NetworkX
Dessiner un fichier netCDF avec python
Méthode de dessin graphique avec matplotlib
Graphique des données Excel avec matplotlib (2)
Créer un graphique SVG avec matplotlib avec heroku (affiché en japonais)
Dessinez un graphique avec networkx
Animer plusieurs graphiques avec matplotlib
Tracez un graphe avec Julia + PyQtGraph (2)
matplotlib: insérer un commentaire dans le graphique de l'axe des temps
Tracez un graphique avec Julia + PyQtGraph (1)
Dessinez un graphique avec Julia + PyQtGraph (3)
Dessiner un graphique du taux de rétention avec Matplotlib
Dessinez un graphique avec des pandas + XlsxWriter
Dessinez facilement des graphiques avec matplotlib
Dessinez Riapnov Fractal avec Python, matplotlib
Créer une application graphique par Kivy (y compris matplotlib)
(Matplotlib) Je veux dessiner un graphique avec une taille spécifiée en pixels
Comment titrer plusieurs figures avec matplotlib
[Python] Définissez la plage du graphique avec matplotlib
Programmation GUI à l'aide de kivy ~ Partie 4 Divers boutons ~
Comment dessiner un graphique avec Matplotlib
Afficher le graphe xy de Matplotlib avec PySimpleGUI.
Dessinez une figure sur la couche d'entités avec ArcPy
Sélection de zone de boîte par GUI sur le tracé Matplotlib
Ecrire des graphiques SVG avec matplotlib avec heroku
Dessinez une étiquette d'axe hiérarchique avec matplotlib + pandas
Routage basé sur des règles sur des machines avec plusieurs cartes réseau
Graphiques de fonctions triangulaires avec numpy et matplotlib
Dessinez simplement un graphique en spécifiant un fichier
Dessinez un graphique avec PyQtGraph Part 1-Drawing
Créer un graphique avec des bordures supprimées avec matplotlib