吳欣瑤
本例中我們通過Python編程編寫一個具有簡單交互界面的小程序。用戶輸入一次函數(shù)y=kx+b中k,b兩個常數(shù)的值就可以畫出函數(shù)圖像(圖1)。
首先做出一個圖形用戶界面(GUI)來接收數(shù)據(jù)。此程序使用Python的tkinter模塊來做GUI。tkinter 共有三種幾何布局管理器,分別是pack布局、grid布局、place布局。這三種均用于同一父組件下的組件布局,但是也是有區(qū)別的。pack按添加順序排列組件;grid按行列形式排列組件;place允許程序員指定組件的大小和位置。
這里用簡便易用的grid來布局,它的基本參數(shù)及用法如表1所示。
通俗地講,grid布局就是把每個控件放置在單元格中,整個窗體就是一張表格。因此可以使用Excel或WPS表格等工具來做一個界面的效果圖,如圖2所示。值得注意的是,參數(shù)row和column都是從0開始的,所以應修改成圖3所示的格式:
接下來就把這個界面書寫成代碼,如圖4。
代碼中使用通配符“*”引入了三個模塊。tkinter模塊用于圖形界面編程,turtle模塊用于繪制坐標系與函數(shù)圖像,math模塊用于計算函數(shù)圖像與x軸的夾角。
此處創(chuàng)建了兩個特殊的字符串變量v1和v2,它們是StringVar(字符串變量)。這種變量的特殊之處在于它需要通過get()方法來訪問里面的值。在后面編寫程序獲取值的時候就會用到get()方法了。然后設置兩個輸入框(e1、e2)的textvariable參數(shù)分別為v1和v2,用戶輸入到輸入框e1和e2中的內(nèi)容就會分別被放入變量v1和v2中。
在繪制函數(shù)圖像之前,需要建立一個平面直角坐標系xOy(x軸,y軸以及以它們的交點O為原點建立的坐標系稱為xOy)。坐標系使用turtle模塊繪制,turtle模塊的部分函數(shù)及意義如表2所示。
在繪制x軸與y軸時,都需要畫一個小箭頭表示正方向,那么如何在一條直線的末端畫出箭頭呢?turtle畫箭頭的路徑如圖5所示:
將繪制箭頭的步驟(1.右轉(zhuǎn)30°;2.后退20步;3.前進20步,回到原位置; 4.左轉(zhuǎn)60°; 5.后退20步)寫成一個函數(shù),以便后續(xù)使用,代碼如圖6:
接著繪制坐標軸,turtle繪制坐標軸的路徑如圖7所示:
預設坐標系寬600高800。將繪制平面直角坐標系的步驟寫成代碼,如圖8:
在每次繪制完箭頭后(步驟4、步驟11),都會向右轉(zhuǎn)120°。這是因為在arrow()函數(shù)繪制完箭頭后,小海龜(筆)的朝向是軸線朝向偏左30°,為了方便后面前進30步和繪制文字的步驟,便向右旋轉(zhuǎn)120°,使其朝向變成軸線朝向偏右90°,即與軸線垂直。
在繪制字母x、y以及原點O時,用到了write()函數(shù)。Write()函數(shù)的font參數(shù)需要傳入一個三元組,元組的第一項是字體名;第二項是文字大小;第三項是文字樣式,一般有三種文字樣式:正常(normal)、粗體(bold)、斜體(italic)。
在程序中,僅僅知道函數(shù)的解析式,想要確定直線并用turtle繪制出來就必須有三步操作:第一步,取直線上的兩點(任意兩點即可);第二步,求出兩點的水平距離和鉛垂距離,并通過反三角函數(shù)atan得到圖像與x軸的夾角的弧度值;第三步,將弧度值轉(zhuǎn)換為角度值(圖9)。
首先寫一個事件響應函數(shù)click(event),用get()函數(shù)從字符串變量v1和v2中取得用戶輸入的值。get()函數(shù)的返回值類型是字符串,而字符串不能直接參與數(shù)字運算,所以需要把它們轉(zhuǎn)換成整數(shù)或是浮點數(shù)。但為了支持用戶輸入運算表達式,這里使用eval()函數(shù),eval()函數(shù)可以將一個字符串表達式執(zhí)行并返回結(jié)果。把eval()函數(shù)返回的值直接儲存到變量k、b中,方便后面計算使用(圖10)。
除了正比例函數(shù)之外的其他一次函數(shù)的圖像,都會與y軸和x軸分別有一個交點(如圖中點P1、P2)。這兩個交點和原點正好構(gòu)成一個直角三角形,那么兩交點的水平距離和鉛垂距離,如圖9中x、y所示,這兩條線段就相當于是直角三角形的兩直角邊。在這里使用反三角函數(shù)atan,把y/x帶進去,即atan(y/x),就可以求得函數(shù)圖像與x軸的夾角θ的弧度值。注意,atan函數(shù)計算結(jié)果(rad)是弧度值,不是角度值,因此需要進行轉(zhuǎn)換。轉(zhuǎn)換公式為:1弧度=(180/π)°。在代碼中π取近似值3.1415,精度就足夠了。轉(zhuǎn)換之后就得到了函數(shù)圖像與x軸的夾角θ的角度值(angle)。接著,使用goto()函數(shù)移動到函數(shù)圖像與x軸的交點,即點P2。然后判斷斜率k(k≠0)的正負性,如果斜率k是正數(shù),則函數(shù)圖像向上傾斜,否則向下傾斜。知道了傾斜方向就可以根據(jù)夾角θ的角度值(angle)用setheading()函數(shù)設置turtle的絕對方向。然后再沿著這個方向后退400步再前進800步就能繪制出一條準確的直線(函數(shù)圖像)了。
眾所周知,正比例函數(shù)是一種必過原點的特殊一次函數(shù)(圖11)。所以,由此就知道了該函數(shù)圖像上的一點(原點O,也是P1),再取函數(shù)圖像上當x=1時的點(1,k)就能構(gòu)成一個直角三角形,然后使用atan函數(shù)并轉(zhuǎn)換成角度,方法與非正比例函數(shù)(其他一次函數(shù))中所述方法相同。最后,用b1.bind把事件響應函數(shù)click和左鍵單擊的事件(<Button-1>)綁定在一起,如此一來當用戶使用鼠標左鍵單擊按鈕b1時,就會執(zhí)行函數(shù)click中的操作(圖12)。