44import logging
55import math
66import os .path
7+ import pathlib
78import sys
89import tkinter as tk
910import tkinter .filedialog
@@ -499,11 +500,8 @@ def create_with_canvas(cls, canvas_class, figure, num):
499500 'images/matplotlib_large.png' ))
500501 icon_img_large = ImageTk .PhotoImage (
501502 file = icon_fname_large , master = window )
502- try :
503- window .iconphoto (False , icon_img_large , icon_img )
504- except Exception as exc :
505- # log the failure (due e.g. to Tk version), but carry on
506- _log .info ('Could not load matplotlib icon: %s' , exc )
503+
504+ window .iconphoto (False , icon_img_large , icon_img )
507505
508506 canvas = canvas_class (figure , master = window )
509507 manager = cls (canvas , num , window )
@@ -846,15 +844,15 @@ def _Spacer(self):
846844 return s
847845
848846 def save_figure (self , * args ):
849- filetypes = self .canvas .get_supported_filetypes ().copy ()
850- default_filetype = self .canvas .get_default_filetype ()
847+ filetypes = self .canvas .get_supported_filetypes_grouped ()
848+ tk_filetypes = [
849+ (name , " " .join (f"*.{ ext } " for ext in exts ))
850+ for name , exts in sorted (filetypes .items ())
851+ ]
851852
852- # Tk doesn't provide a way to choose a default filetype,
853- # so we just have to put it first
854- default_filetype_name = filetypes .pop (default_filetype )
855- sorted_filetypes = ([(default_filetype , default_filetype_name )]
856- + sorted (filetypes .items ()))
857- tk_filetypes = [(name , '*.%s' % ext ) for ext , name in sorted_filetypes ]
853+ default_extension = self .canvas .get_default_filetype ()
854+ default_filetype = self .canvas .get_supported_filetypes ()[default_extension ]
855+ filetype_variable = tk .StringVar (self , default_filetype )
858856
859857 # adding a default extension seems to break the
860858 # asksaveasfilename dialog when you choose various save types
@@ -863,14 +861,18 @@ def save_figure(self, *args):
863861 # defaultextension = self.canvas.get_default_filetype()
864862 defaultextension = ''
865863 initialdir = os .path .expanduser (mpl .rcParams ['savefig.directory' ])
866- initialfile = self .canvas .get_default_filename ()
864+ # get_default_filename() contains the default extension. On some platforms,
865+ # choosing a different extension from the dropdown does not overwrite it,
866+ # so we need to remove it to make the dropdown functional.
867+ initialfile = pathlib .Path (self .canvas .get_default_filename ()).stem
867868 fname = tkinter .filedialog .asksaveasfilename (
868869 master = self .canvas .get_tk_widget ().master ,
869870 title = 'Save the figure' ,
870871 filetypes = tk_filetypes ,
871872 defaultextension = defaultextension ,
872873 initialdir = initialdir ,
873874 initialfile = initialfile ,
875+ typevariable = filetype_variable
874876 )
875877
876878 if fname in ["" , ()]:
@@ -879,9 +881,16 @@ def save_figure(self, *args):
879881 if initialdir != "" :
880882 mpl .rcParams ['savefig.directory' ] = (
881883 os .path .dirname (str (fname )))
884+
885+ # If the filename contains an extension, let savefig() infer the file
886+ # format from that. If it does not, use the selected dropdown option.
887+ if pathlib .Path (fname ).suffix [1 :] != "" :
888+ extension = None
889+ else :
890+ extension = filetypes [filetype_variable .get ()][0 ]
891+
882892 try :
883- # This method will handle the delegation to the correct type
884- self .canvas .figure .savefig (fname )
893+ self .canvas .figure .savefig (fname , format = extension )
885894 except Exception as e :
886895 tkinter .messagebox .showerror ("Error saving file" , str (e ))
887896
0 commit comments