Tkinter Arc für Monte Carlo Simulation

Fragen zu Tkinter.
Antworten
BlackJack

Hat noch Verbesserungspotential…

Code: Alles auswählen

#!/usr/bin/python
# coding: utf8
from __future__ import absolute_import, division, print_function
import Tkinter as tk
from itertools import islice, izip
from math import sqrt
from random import random
from tkMessageBox import showerror


class Simulation(object):

    def __init__(self):
        random_values = iter(random, None)
        self.random_coordinates = izip(random_values, random_values)
        self.total_count = 0
        self.hit_count = 0

    def __iter__(self):
        return self

    def next(self):
        result = x, y = next(self.random_coordinates)
        self.total_count += 1
        if sqrt(x**2 + y**2) <= 1:
            self.hit_count += 1
        return result

    @property
    def pi(self):
        return 4 * (self.hit_count / self.total_count)


class SimulationUI(tk.Frame):
    
    BATCH_SIZE = 1000

    def __init__(self, master, canvas_size=500):
        tk.Frame.__init__(self, master)
        self.canvas_size = canvas_size
        self.simulation = None
        self.sample_count = None
        self.canvas = tk.Canvas(
            self,
            height=self.canvas_size,
            width=self.canvas_size,
            background='green',
        )
        self.canvas.create_arc(
            -self.canvas_size,
            0,
            self.canvas_size,
            self.canvas_size * 2,
            fill='blue',
            outline='',
        )
        self.canvas.pack()
        self.iteration_count_var = tk.IntVar(self, value=100000)
        self.result_var = tk.StringVar(self, value='-')
        frame = tk.Frame(self)
        tk.Label(frame, text='# Iterations:').pack(side=tk.LEFT)
        tk.Entry(
            frame, textvariable=self.iteration_count_var
        ).pack(side=tk.LEFT)
        self.start_button = tk.Button(
            frame, text='Start', command=self.do_start
        )
        self.start_button.pack(side=tk.LEFT)
        frame.pack()
        tk.Label(self, textvariable=self.result_var).pack()

    def plot(self, coordinate):
        x, y = (c * self.canvas_size for c in coordinate)
        self.canvas.create_line(x, y, x, y + 1, fill='red', tags='dot')

    def do_start(self):
        self.canvas.delete('dot')
        try:
            self.sample_count = self.iteration_count_var.get()
        except ValueError:
            showerror('No Number', 'Iteration count must be a number.')
        else:
            if self.sample_count < 1:
                showerror('To Small', 'Iteration count has to be 1 or greater.')
            else:
                self.start_button['state'] = tk.DISABLED
                self.simulation = Simulation()
                self.run_simulation()

    def run_simulation(self):
        for coordinate in islice(
            self.simulation, min(self.sample_count, self.BATCH_SIZE)
        ):
            self.plot(coordinate)
        self.sample_count = max(0, self.sample_count - self.BATCH_SIZE)
        self.result_var.set(format(self.simulation.pi, '.20f'))
        if self.sample_count:
            self.after_idle(self.run_simulation)
        else:
            self.start_button['state'] = tk.NORMAL


def main():
    root = tk.Tk()
    root.title('Monte-Carlo Simulation for Pi')
    simulation_ui = SimulationUI(root)
    simulation_ui.pack()
    root.mainloop()


if __name__ == '__main__':
    main()
Antworten