134 lines
3.6 KiB
Python
134 lines
3.6 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
ZetCode Tkinter e-book
|
|
|
|
This script produces a long-running task of calculating
|
|
a large Pi number, while keeping the GUI responsive.
|
|
This is an example written for Windows.
|
|
|
|
Author: Jan Bodnar
|
|
Last modified: January 2016
|
|
Website: www.zetcode.com
|
|
"""
|
|
|
|
from tkinter import (Tk, BOTH, Text, E, W, S, N, END,
|
|
NORMAL, DISABLED, StringVar)
|
|
from tkinter.ttk import Frame, Label, Button, Progressbar, Entry
|
|
from tkinter import scrolledtext
|
|
|
|
from multiprocessing import Process, Manager, Queue
|
|
from queue import Empty
|
|
from decimal import Decimal, getcontext
|
|
|
|
|
|
DELAY1 = 80
|
|
DELAY2 = 20
|
|
|
|
# Queue must be global
|
|
q = Queue()
|
|
|
|
class Example(Frame):
|
|
|
|
def __init__(self, parent):
|
|
Frame.__init__(self, parent, name="frame")
|
|
|
|
self.parent = parent
|
|
self.initUI()
|
|
|
|
|
|
def initUI(self):
|
|
|
|
self.parent.title("Pi computation")
|
|
self.pack(fill=BOTH, expand=True)
|
|
|
|
self.grid_columnconfigure(4, weight=1)
|
|
self.grid_rowconfigure(3, weight=1)
|
|
|
|
lbl1 = Label(self, text="Digits:")
|
|
lbl1.grid(row=0, column=0, sticky=E, padx=10, pady=10)
|
|
|
|
self.ent1 = Entry(self, width=10)
|
|
self.ent1.insert(END, "4000")
|
|
self.ent1.grid(row=0, column=1, sticky=W)
|
|
|
|
lbl2 = Label(self, text="Accuracy:")
|
|
lbl2.grid(row=0, column=2, sticky=E, padx=10, pady=10)
|
|
|
|
self.ent2 = Entry(self, width=10)
|
|
self.ent2.insert(END, "100")
|
|
self.ent2.grid(row=0, column=3, sticky=W)
|
|
|
|
self.startBtn = Button(self, text="Start",
|
|
command=self.onStart)
|
|
self.startBtn.grid(row=1, column=0, padx=10, pady=5, sticky=W)
|
|
|
|
self.pbar = Progressbar(self, mode='indeterminate')
|
|
self.pbar.grid(row=1, column=1, columnspan=3, sticky=W+E)
|
|
|
|
self.txt = scrolledtext.ScrolledText(self)
|
|
self.txt.grid(row=2, column=0, rowspan=4, padx=10, pady=5,
|
|
columnspan=5, sticky=E+W+S+N)
|
|
|
|
|
|
def onStart(self):
|
|
|
|
self.startBtn.config(state=DISABLED)
|
|
self.txt.delete("1.0", END)
|
|
|
|
digits = int(self.ent1.get())
|
|
accuracy = int(self.ent2.get())
|
|
|
|
self.p1 = Process(target=generatePi, args=(q, digits, accuracy))
|
|
self.p1.start()
|
|
self.pbar.start(DELAY2)
|
|
self.after(DELAY1, self.onGetValue)
|
|
|
|
|
|
def onGetValue(self):
|
|
|
|
if (self.p1.is_alive()):
|
|
|
|
self.after(DELAY1, self.onGetValue)
|
|
return
|
|
else:
|
|
|
|
try:
|
|
|
|
self.txt.insert('end', q.get(0))
|
|
self.txt.insert('end', "\n")
|
|
self.pbar.stop()
|
|
self.startBtn.config(state=NORMAL)
|
|
|
|
except Empty:
|
|
print("queue is empty")
|
|
|
|
# Generate function must be a top-level module funtion
|
|
def generatePi(q, digs, acc):
|
|
|
|
getcontext().prec = digs
|
|
|
|
pi = Decimal(0)
|
|
k = 0
|
|
n = acc
|
|
|
|
while k < n:
|
|
pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1)) - \
|
|
(Decimal(2)/(8*k+4)) - (Decimal(1)/(8*k+5))- \
|
|
(Decimal(1)/(8*k+6)))
|
|
k += 1
|
|
|
|
q.put(pi)
|
|
|
|
|
|
def main():
|
|
|
|
root = Tk()
|
|
root.geometry("400x350+300+300")
|
|
app = Example(root)
|
|
root.mainloop()
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main() |