Fehler beim Löschen des Feldinhalts

Fragen zu Tkinter.
Antworten
Kniffte
User
Beiträge: 64
Registriert: Dienstag 27. September 2016, 11:05

Hallo Zusammen,

Um mein Problem vereinfacht zu veranschaulichen, folgender Code:

Code: Alles auswählen

import tkinter as tk  # python 3.x
# import Tkinter as tk # python 2.x

class Example(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.scaling_factor = tk.DoubleVar()

        self.entry = tk.Entry(self, textvariable=self.scaling_factor)
        self.entry.pack(side="top", fill="x")

        self.scaling_factor.trace('w', self._instant_scaling)


    def _instant_scaling(self, *args):
        scaled_length = 2 * self.scaling_factor.get()
        print(scaled_length)


if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()
Dieser erzeugt beim Löschen des Feldinhaltes bzw. beim vollständigen Markieren des Inhaltes und Eingabe einer neuen Zahl folgende Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Users\Seb\Miniconda3\envs\py_34\lib\tkinter\__init__.py", line 1538, in __call__
    return self.func(*args)
  File "entryval.py", line 19, in _get_value
    self.scaling_factor.get()
  File "C:\Users\Seb\Miniconda3\envs\py_34\lib\tkinter\__init__.py", line 377, in get
    return getdouble(self._tk.globalgetvar(self._name))
ValueError: could not convert string to float:

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "entryval.py", line 27, in <module>
    root.mainloop()
  File "C:\Users\Seb\Miniconda3\envs\py_34\lib\tkinter\__init__.py", line 1125, in mainloop
    self.tk.mainloop(n)
  File "C:\Users\Seb\Miniconda3\envs\py_34\lib\tkinter\__init__.py", line 1542, in __call__
    self.widget._report_exception()
AttributeError: 'DoubleVar' object has no attribute '_report_exception'
Klar ist, dass ich hier nen 'ValueError' abfangen muss, weil er nen leeren String in eine Float umwandeln will.
Füge also try...except hinzu:

Code: Alles auswählen

import tkinter as tk  # python 3.x
# import Tkinter as tk # python 2.x

class Example(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        self.scaling_factor = tk.DoubleVar()

        self.entry = tk.Entry(self, textvariable=self.scaling_factor)
        self.entry.pack(side="top", fill="x")

        self.scaling_factor.trace('w', self._instant_scaling)


    def _instant_scaling(self, *args):
        try:
            scaled_length = 2 * self.scaling_factor.get()
            print(scaled_length)
        except ValueError:
            pass


if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()
Da ich nun die Eingabe des Users nicht unterbrechen will mit irgendeiner Fehlermeldung/ Messagebox, verwende ich 'pass' im except Abschnitt.
Ist dies so schlechter Stil und es gibt dafür eine "saubere" Alternative?
(über die Validierung der Eingabe ist es mir nicht gelungen...mithilfe von: https://stackoverflow.com/a/4140988)

Gruß Seb
BlackJack

@Kniffte: In den ``except``-Zweig gehört eine sinnvolle Behandlung der Ausnahme. Wenn es Sinn macht im Ausnahmefall nichts zu tun, dann ist ``pass`` das passende.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Es wäre gut, gleich eine allgemeine Lösung für alle Eingabefelder zu machen.

Das stelle ich mir so vor:

Code: Alles auswählen

class Actions:

    def __init__(self,dictionary,where = None):

        self.default_where = where
        self.dictionary = dictionary

    def get(self,key):
        return str(self.dictionary[key])

    def set(self,key,value,where = None):

        try:
            value = self.convert(key,value)
            self.dictionary[key] = value

            if not where:
                where = self.default_where
            self.act(key,value,where)

        except ValueError:
            pass

    # dummy definitions ===================
    # this is the base class and the class whichgb inherits
    # this base class shall contain the implementation of
    # the following two methods
    
    def convert(self,key,value):

        if key == 'scale':
            value = float(value)

        return value

    def act(self,key,value,where):
        print('acted:',key,value,where)
        
    

# lets test it ================================================

myactions = Actions({ 'scale': 1.0} )

print('get1', myactions.get('scale'))

myactions.set('scale',1.5)
print('get2', myactions.get('scale'))

myactions.set('scale',"2.23")
print('get3', myactions.get('scale'))

myactions.set('scale',"wrdlbrmpfd")
print('get4', myactions.get('scale'))
Antworten