java2python 发表于 2020-6-25 10:29:53

把sympy装入matplatlib再装进thinker后的问题

先说情况:
再把sympy装进matplatlib,再开一个条形窗口放按钮(至于这么干有啥意义,不是讨论的内容)

就是这样的效果,参考的东西太多了,七拼八凑搞起来的(问题求助就贴就不列举感谢网址了)
点击matplotlib下的按钮可以变化左边条形图的表示内容,准备了4个样本

右边点击图形表示,可以变变化右上窗口的表示内容(实际有问题,因为调用走一个调用matplotlib,再调用sympy的过程,途中有隐含窗体被创建,代码中努力消去这个窗口,执行20多次,还是会出窗体数量超标的警告),这个数据也准备了4个图形函数样本。左边matplotlib的话,只是单纯,数据清空,再填入,再表示,按多少次都没有问题。希望的是,右边按钮和左边同样,无论按多少次都不会处警告
为啥要加sympy呢,主要是他有隐函数模拟比如:x**2+y**2-5=0,这是一个圆方程,但是如果复杂的话,很难转成y=f(x)这样的形式,这个比较牛,所以想把他装进来。另外刷新,是因为想可以手动输入方程,然后点图形显示(实际它有许多方程的表示法,这个隐方程的网上例子太少了,连他官网也没啥例子,更不用说怎么装到matplotlib,还要提供按键接受输入框输入的方程,所以这个没有实现,只是用了plot_parametric(cos(x), sin(x), (x, 0, 2*pi), show=False)这样的方程形式)。关闭窗口还是要按“关闭”按钮,因为里面执行了代码“plt.close('all')”,会关闭所有窗体(包括隐含的),直接按windows的“×”可能会内存泄漏。。。

想法源于:数学之美——你见过哪些优美的数学方程曲线?

这里面:极坐标r=f(θ)可能没问题,有些类似:(x^2+y^2-1)^2=x^3,好像没法解,当然可以区域模拟:给范围,用足够小的分辨率,一个坐标一个坐标模拟,然后结果是等式两边相减接近0。不过想到python有许多库,不用自己做,果然找到了sympy,然后想把sympy装到thinker,没有直接装的例子,无从下手,找到sympy装到matplatlib例子,然后matplatlib装入thinker官网就有例子的,再就是既然装了两个,再加一个按钮条,加了按钮条总不能什么都不做,就想要上边两个窗体的刷新(数据都列举在代码中了,可以直接运行的,右边按钮点30次一定会出窗体数超标吧。。。):
import tkinter as tk
from tkinter import *
from pandas import DataFrame
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from sympy.plotting.plot import plot_parametric
import sympy.geometry.util
from sympy import *
from sympy.abc import x,y,z
from sympy import plot_implicit
#ezplot = lambda exper: plot_implicit(parse_expr(exper))#用了匿名函数

class App:
    data1 = [{'Country': ['US','CA','GER','UK','FR'],
             'GDP_Per_Capita':
            },
            {'Country': ['US','CA','GER','UK','FR'],
             'GDP_Per_Capita':
            },
            {'Country': ['US','CA','GER','UK','FR'],
             'GDP_Per_Capita':
            },
            {'Country': ['US','CA','GER','UK','FR'],
             'GDP_Per_Capita':
            }]
    data1_ptr= 0
    line2_ptr= 0
   
    def __init__(self):
      #------------------------------------------------
      #tkinter 画面划分
      #------------------------------------------------
      root= tk.Tk()
      root.resizable(0,0)

      embed = tk.Frame(root, width = 1100, height = 550) #creates embed frame for pygame window
      embed.grid(columnspan = (1100), rowspan = 500) # Adds grid
      embed.pack(side = TOP) #packs window to the left

      buttonwin = tk.Frame(root, width = 1100, height = 50)
      buttonwin.pack(side = BOTTOM)
      #------------------------------------------------
      #
      #------------------------------------------------
      
      #控件定义区 =====================================
      button_mat_b = Button(buttonwin,text = 'matlab再表示', width=11, command=self.show_mat)
      button_mat_b.place(x=200,y=0)

      btnwin_fl_l = tk.Label(buttonwin, text='式子:')
      btnwin_fl_l.place(x=300,y=5)
      inputfl = StringVar()
      btnwin_fl_e = tk.Entry(buttonwin, width=70,textvariable = inputfl)
      btnwin_fl_e.place(x=350,y=5)
      button_show_b = Button(buttonwin,text = '图形表示', width=11, command=self.show_fl)
      button_show_b.place(x=850,y=0)
      button_show_b = Button(buttonwin,text = '关闭窗口', width=11, command=self.exit)
      button_show_b.place(x=1000,y=0)
      
      #matplotlib,matplotlib内嵌sympy子窗体
      figure1 = plt.Figure(figsize=(6,5), dpi=100)
      ax1 = figure1.add_subplot(111)
      bar1 = FigureCanvasTkAgg(figure1, embed)
      bar1.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH)
      df1 = DataFrame(App.data1,columns=['Country','GDP_Per_Capita'])
      df1 = df1[['Country','GDP_Per_Capita']].groupby('Country').sum()
      df1.plot(kind='bar', legend=True, ax=ax1)
      ax1.set_title('Country Vs. GDP Per Capita')

      figure2 = plt.Figure(figsize=(5,4), dpi=100)
      p2 = self.get_plot_parametric()
      ax2 = figure2.add_subplot(111)
      self.move_sympyplot_to_axes(p2, ax2)
      line2 = FigureCanvasTkAgg(figure2, embed)
      line2.get_tk_widget().pack(side=tk.RIGHT, fill=tk.BOTH)
      
      #---------------------------- 对外接口
      App.root       = root
      App.bar1       = bar1
      App.figure1    = figure1
      App.ax1      = ax1
      App.figure2    = figure2
      App.line2      = line2
      App.ax2      = ax2
      
    #按钮动作区 =====================================
    def exit(self):
      plt.close('all')
      App.root.quit()   # stops mainloop
      App.root.destroy()# this is necessary on Windows to prevent
      
    def show_mat(self):
      App.data1_ptr = (App.data1_ptr+1)%4
      App.figure1.clear()
      App.ax1.clear()
      App.ax1 = App.figure1.add_subplot(111)
      App.df1 = DataFrame(App.data1,columns=['Country','GDP_Per_Capita'])
      App.df1 = App.df1[['Country','GDP_Per_Capita']].groupby('Country').sum()
      App.df1.plot(kind='bar', legend=True, ax=App.ax1)
      App.ax1.set_title('Country Vs. GDP Per Capita')
      App.bar1.draw()
      
    def get_plot_parametric(self):
      App.line2_ptr = (App.line2_ptr+1) % 4
      if App.line2_ptr == 0:
            return plot_parametric(cos(x), sin(x), (x, 0, 2*pi), show=False)
      elif App.line2_ptr == 1:
            return plot_parametric(cos(x), x, (x, 0, 2*pi), show=False)
      elif App.line2_ptr == 2:
            return plot_parametric(cos(x), cos(x), (x, -5, 5), show=False)
      else:
            return plot_parametric(2*x, sin(x), (x, 0, 2*pi), show=False)

    def show_fl(self):
      App.figure2.clear()
      App.p2 = self.get_plot_parametric()
      App.ax2 = App.figure2.add_subplot(111)
      self.move_sympyplot_to_axes(App.p2, App.ax2)
      App.line2.draw()

    def move_sympyplot_to_axes(self,p, ax):
      backend = p.backend(p)
      backend.ax = ax
      # Fix for > sympy v1.5
      backend._process_series(backend.parent._series, ax, backend.parent)
      backend.ax.spines['right'].set_color('none')
      backend.ax.spines['bottom'].set_position('zero')
      backend.ax.spines['top'].set_color('none')
      #plt.close(backend.fig)
      plt.close(plt.figure())
      
App().root.mainloop()

java2python 发表于 2020-6-25 18:20:12

顶上去,审核了帖子沉了
页: [1]
查看完整版本: 把sympy装入matplatlib再装进thinker后的问题