2016-03-29 9 views
0

Ich habe eine einfache Primzahl-Checker, die Speicherprobleme bei 16 Ziffern plus lief, wenn ich auf dem mobilen Gerät lief. Ich dachte mir, ich könnte das beheben, indem ich den Primzahlprüfer in einem separaten Thread als GUI ausführen lasse. Durch andere Beispiele zu schauen, hat mir nicht geholfen, aber ich habe stattdessen zufällige Teile aus verschiedenen Beispielen hinzugefügt. Wie auch immer, hier ist der Code.Wie starte ich einen neuen Thread, um Berechnungen durchzuführen, um Speicherfehler in der GUI von kivy zu vermeiden?

from kivy.app import App 
from kivy.uix.label import Label 
from kivy.uix.widget import Widget 
from kivy.uix.textinput import TextInput 
from kivy.uix.button import Button 
from kivy.properties import ObjectProperty 
from kivy.clock import mainthread 
from kivy.lang import Builder 

from numpy import remainder, sqrt, floor 

from datetime import datetime 
import threading 


Builder.load_string(''' 
<MainScreen>: 
    number: number_input 
    check: check_button 
    answer: answer 
    time: time 

    canvas: 

     Color: 
      rgba: .2, .2, .5, .5 
     Rectangle: 
      pos: self.pos 
      size: self.size 


     # answer button 
     Color: 
      rgba: .5, .8, .8, .5 
     Rectangle: 
      pos: 0, root.height/3 
      size: root.width/2, root.height/10 

     # time button 
     Color: 
      rgba: .2, .5, .5, .5 
     Rectangle: 
      pos: 0, root.height/6 
      size: root.width, root.height/10 


    TextInput: 

     id: number_input 
     pos: root.width/4, 2 * root.height/3 
     size: root.width/2, root.height/10 
     multiline: False 
     input_filter: 'int' 
     hint_text: 'Enter number' 
     write_tab: False 


    Button: 

     id: check_button 
     pos: root.width/2, root.height/3 
     size: root.width/2, root.height/10 
     text: 'Check' 
     on_press: 
      root.start_second_thread() 

    Label: 

     id: answer 
     text: 'Answer' 
     pos: 0, root.height/3 
     size: root.width/2, root.height/10 

    Label: 

     id: time 
     pos: 0, root.height/6 
     size: root.width, root.height/10 
     text: 'Time taken' 
''') 

class MainScreen(Widget): 

    number = ObjectProperty(None) 
    check = ObjectProperty(None) 
    answer = ObjectProperty(None) 
    time = ObjectProperty(None) 

    def start_second_thread(self): 

     thread2 = threading.Thread(target=self.prime_checker) 
     thread2.start() 
     #thread2.join() 
     print(threading.activeCount()) 

    def prime_checker(self, *args): 

     ans = '' 
     now = datetime.now() 
     if self.number.text == '': 
      #self.answer.text = 'No number entered' 
      ans = 'No number entered' 
      end = datetime.now() - now 
      #self.time_checker(end) 

     elif len(self.number.text) > 17: 
      #self.answer.text = 'Too big for now' 
      ans = 'Too big for now' 
      end = datetime.now() - now 
      #self.time_checker(end) 

     else: 
      numb = int(self.number.text) 
      upper_limit = int(floor(sqrt(numb))) 
      tested = False 

      if numb < 2: 
       #self.answer.text = 'Not Prime' 
       ans = 'Not Prime' 
       end = datetime.now() - now 
       #self.time_checker(end) 

      elif numb == 2: 
       #self.answer.text = 'Prime' 
       ans = 'Prime' 
       end = datetime.now() - now 
       #self.time_checker(end) 

      elif numb % 2 == 0: 
       #self.answer.text = 'Not Prime, 2' 
       ans = 'Not Prime, 2' 
       end = datetime.now() - now 
       #self.time_checker(end) 

      else: 
       for i in range(3, upper_limit, 2): 
        #if numb % i == 0: 
        if remainder(numb, i) == 0: 
         #self.answer.text = 'Not Prime, {}'.format(i) 
         ans = 'Not Prime, {}'.format(i) 
         tested = True 
         end = datetime.now() - now 
         #self.time_checker(end) 
         break 

       if tested == False: 
        #self.answer.text = 'Prime' 
        ans = 'Prime' 
        end = datetime.now() - now 
        #self.time_checker(end) 

     self.update_main_thread(ans, end) 

    def time_checker(self, some_time): 

     some_time = 'This took {0} seconds and {1} milliseconds'.format(some_time.seconds, float(some_time.microseconds)/1000) 
     #self.time.text = some_time 

    @mainthread 
    def update_main_thread(self, ans, tim): 
     self.answer.text = ans 
     tim = 'This took {0} seconds and {1} milliseconds'.format(tim.seconds, float(tim.microseconds)/1000) 
     self.time.text = tim 


class PrimeNumberCheckerApp(App): 

    def build(self): 

     return MainScreen() 

if __name__ == '__main__': 
    PrimeNumberCheckerApp().run() 

Ich bin sicher, dass eine Tonne von Dingen gibt es ich besser machen kann, auf die Vorschläge sind willkommen; Am wichtigsten ist mir jedoch, warum die Zeile print (threading.activeCount()) 1 statt 2 ausgibt. Danke.

+0

Sind Sie sicher, dass der Thread nicht einfach fertig ist, bevor Sie zur Druckanweisung gelangen? – Natecat

+0

Nun, ich denke, ich habe die Print-Anweisung nie an den richtigen Ort gebracht. Ich habe es einen Tag lang versucht und nach dem Lesen Ihres Kommentars und dem Verschieben der Druckanweisungspaarzeilen tut es jetzt, was ich wollte. Vielen Dank. Auf eine Randnotiz, werde ich Frage schließen, wenn ich herausfinden, wie. – pizz

Antwort

0

Dank Natecat scheint der Thread gerade vor der Druckanweisung zu enden. Wenn jemand anderes auf Problem ähnlich läuft, habe ich gerade die Druckanweisung um ein paar Zeilen nach

verschoben, um zu bekommen, was ich erwartet habe. Danke Natecat für die schnelle Antwort.

Verwandte Themen