Spazieren in der GUI

Fragen zu Tkinter.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Ich weiß nicht ob Ihr wisst, dass man in der GUI spazieren gehen kann. Was man dazu braucht, ist einfach nur ein tkinter Programm, wie etwa dieses: http://www.python-kurs.eu/tkinter_buttons.php

Und das muss man nur geringfügig anpassen. Das habe ich dann so gemacht:

Code: Alles auswählen

from spazieren import *

import threading
class MyThread(threading.Thread):
	def run(self):
		while True:
			a = input("> ")
			try: eval(compile(a,'<string>', 'exec'))
			except: print("Error:",a)

mythread = MyThread()
mythread.daemon = True
mythread.start()

class App:
  def __init__(self, master):
    frame = Frame(master)
    frame.pack()
    self.button = Button(frame, 
                         text="QUIT", fg="red",
                         command=frame.quit)
    self.button.pack(side=LEFT)
    self.slogan = Button(frame,
                         text="Hello",
                         command=self.write_slogan)
    self.slogan.pack(side=LEFT)
  def write_slogan(self):
    print("Tkinter is easy to use!")

root = Tk()
app = App(root)
root.mainloop()
Statt from tkinter import * habe ich geschrieben: from spazieren import *
Und dann habe ich über einen Thread manuelle Eingaben implementiert. Außerdem mußte ich die python2 print Anweisung auf python3 anpassen. Und was man dazu noch braucht, ist das Modul spazieren:

Code: Alles auswählen

import tkinter as StatTkInter
from tkinter import *
from copy import copy


class Create_Selection:

	def __init__(self,widget=None,container = None):
		if widget == None: # only for initialisation
			self._widget = None
			self._container = None
		else:
			self._widget = widget
			if container != None and container.isContainer: self._container = container
			else:
				master = widget.master
				if master == None: self._container = widget
				else: self._container = master

	def selectContainer(self): self._widget = self._container

	def selectWidget(self,widget):
		self._widget = widget
		master = widget.master
		if master == None: self._container = widget
		else: self._container = master

	def selectOut(self):
		self.selectWidget(self._container)

	def selectIn(self):
		if self._widget.isContainer: self._container = self._widget
		
_Selection=Create_Selection()
_Application=Create_Selection()

def this():
	global _Selection
	return _Selection._widget

def ls():
	if _Selection._container is _Selection._widget:
		print("=> "+"\\.")
	else:
		print("   "+"\\.")

	for n,e in _Selection._container.Dictionary.elements.items():
		isNameSelected = False
		number = len(e)
		if _Selection._widget in e:
			print("=>",end=" ")
			isNameSelected = True
		else:
			print("  ",end=" ")

		if number == 1: print (n)
		else:
			if isNameSelected:
				i = 0
				while i < number and not e[i] is _Selection._widget: i = i+1
				print (n + " : " + str(i+1) + " of " + str(number) + " => index ["+str(i)+"]")
	
			else: print (n + " : " + str(number))


def goto(name,nr=-1):
	widget = _Selection._container.Dictionary.getEntry(name,nr)
	if widget != None: 
		_Selection._widget = widget

def widget(name,nr=-1):
	return _Selection._container.Dictionary.getEntry(name,nr)

def goIn(): _Selection.selectIn()
def goOut(): _Selection.selectOut()
def goCont(): _Selection.selectContainer()

def goApp():
	global _Selection
	_Selection = copy(_Application)

def _getMasterAndNameAndSelect(name,altname):
	if type(name) == str: return _Selection._container,name,True
	elif type(name) == tuple: return name[0],name[1],False
	else: return name,altname,False


def _initGuiElement(kwargs,tkClass,element,myname,altname,isContainer=False):
	element.tkClass = tkClass
	master,myname,select = _getMasterAndNameAndSelect(myname,altname)
	element.tkClass.__init__(element,master,**kwargs)
	element.master = master
	element.isContainer = isContainer
	GuiElement.__init__(element,myname,select)


class GuiDictionary:

	def __init__(self): self.elements = {}

	def setElement(self,name,thisone):
		if not name in self.elements: self.elements[name] = [thisone]
		else: self.elements[name].append(thisone)

	def getEntry(self,name,nr=-1):
		if name in self.elements: return self.elements[name][nr]
		return None


class GuiElement:
	def __init__(self,name="nn",select=True):
		if select: _Selection._widget = self
		if self.master != None: self.master.Dictionary.setElement(name,self)
		if self.isContainer: 
			self.Dictionary = GuiDictionary()

	def destroy(self):
		self.tkClass.destroy(self)
		goApp()

class Tk(GuiElement,StatTkInter.Tk):
	def __init__(self,myname="Application",**kwargs):
		global _Application
		global _Selection
		_initGuiElement(kwargs,StatTkInter.Tk,self,myname,"Application",True)
		_Application = Create_Selection(self,self)
		_Selection = copy(_Application)

class Message(GuiElement,StatTkInter.Message):
	def __init__(self,myname="Message",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Message,self,myname,"Message")
	
class Label(GuiElement,StatTkInter.Label):
	def __init__(self,myname="Label",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Label,self,myname,"Label")

class Button(GuiElement,StatTkInter.Button):
	def __init__(self,myname="Button",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Button,self,myname,"Button")

class Radiobutton(GuiElement,StatTkInter.Radiobutton):
	def __init__(self,myname="Radiobutton",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Radiobutton,self,myname,"Radiobutton")
		
class Checkbutton(GuiElement,StatTkInter.Checkbutton):
	def __init__(self,myname="Checkbutton",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Checkbutton,self,myname,"Checkbutton")

class Entry(GuiElement,StatTkInter.Entry):
	def __init__(self,myname="Entry",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Entry,self,myname,"Entry")

class Text(GuiElement,StatTkInter.Text):
	def __init__(self,myname="Text",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Text,self,myname,"Text")

class Listbox(GuiElement,StatTkInter.Listbox):
	def __init__(self,myname="Listbox",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Listbox,self,myname,"Listbox")

class Spinbox(GuiElement,StatTkInter.Spinbox):
	def __init__(self,myname="Spinbox",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Spinbox,self,myname,"Spinbox")

class Frame(GuiElement,StatTkInter.Frame):
	def __init__(self,myname="Frame",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Frame,self,myname,"Frame",True)

class LabelFrame(GuiElement,StatTkInter.LabelFrame):
	def __init__(self,myname="LabelFrame",**kwargs):
		_initGuiElement(kwargs,StatTkInter.LabelFrame,self,myname,"LabelFrame",True)
			
class Scale(GuiElement,StatTkInter.Scale):
	def __init__(self,myname="Scale",**kwargs):
		self.tkClass = StatTkInter.Scale
		_initGuiElement(kwargs,StatTkInter.Scale,self,myname,"Scale")
		
class PanedWindow(GuiElement,StatTkInter.PanedWindow):
	def __init__(self,myname="PanedWindow",**kwargs):
		_initGuiElement(kwargs,StatTkInter.PanedWindow,self,myname,"PanedWindow")

class Canvas(GuiElement,StatTkInter.Canvas):
	def __init__(self,myname="Canvas",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Canvas,self,myname,"Canvas",True)

class Menubutton(GuiElement,StatTkInter.Menubutton):
	def __init__(self,myname="Menubutton",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Menubutton,self,myname,"Menubutton",True)

class Menu(GuiElement,StatTkInter.Menu):
	def __init__(self,myname="Menu",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Menu,self,myname,"Menu")
			
class Scrollbar(GuiElement,StatTkInter.Scrollbar):
	def __init__(self,myname="Scrollbar",**kwargs):
		_initGuiElement(kwargs,StatTkInter.Scrollbar,self,myname,"Scrollbar")
Wenn man nun das erste Modul startet, dann startet es ganz normal. Aber jetzt kann man in die Konsole etwas eingeben. Und das wäre der Befehl: ls()
Dann sieht man einen Pfeil auf einen Punkt zeigend. Das ist die root. Und dann sieht man einen Frame. Zu dem Frame kan man dann hingehen:

goto('Frame')
ls()

Der Zeiger steht jetzt auf dem Frame. Jetzt kann man in den Frame hineingehen:

goIn()
ls()

Der Zeiger steht wieder auf einem Punkt. Das ist der Frame von innen. Man sieht dort zwei Buttons. Zu einem von diesem kann man ja auch mal hingehen:

goto('Button')
ls()

Wenn man bei gleichem Namen, keine Indexangabe macht, wird der letzte ausgewählt. Doch welcher ist das? Kann man testen:

print(this()['text'])

this() ist das ausgewählte Element. Man kann nun mal die Farbe ändern:

this()['fg'] = '#005000'

Dann wird er grün. Man kann auch auf den Button mit der Maus klicken und natürlich funktioniert dieser noch. Man kann auch einen Button hinzumachen:

Button('MyButton',text = "Mein Knopf).pack()
ls()

Statt dem Master gibt man hier einen Namen an. Oder wenn man den Namen wegläßt, heißt er eben auch 'Button'. Wenn mehrere widgets mit gleichem Namen da sind, dann wählt man sie mit Index:

goto('Button',0)
ls()

Wenn der Button stört, kann man ihn auch wegmachen: this().destroy()

Aus Sicherheitsgründen befindet man sich nach destroy aber wieder in der Root. Man könnte eine veränderte GUI auch abspeichern. Aber da habe ich zur Zeit ein Format, das zwar auch mit dem Modul spazieren geht, aber nicht mit normalem tkinter. Abgespeichert sieht es dann so aus:

Code: Alles auswählen

from spazieren import *

Frame('Frame')
goIn()

Button('Button',text="""QUIT""",fg='red')
Button('Button',text="""Hello""")

widget('Button',0).pack(side='left')
widget('Button',1).pack(side='left')

goOut()

widget('Frame').pack()
So wollen es aber wohl die meisten nicht haben. Habt ihr einen Vorschlag, wie man das abspeichern könnte, damit es normal tkinter kompatibel ist?
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Ist natürlich mühsam, sich manuell durch die GUI zu bewegen. Deshalb habe ich den GuiCreator mit grafischer Oberfläche, der in einem TopLevel Window läuft.
Und GUI erstellen und ändern geht damit schnell. Die Frage ist aber jetzt, was ist ein brauchbares Abspeicherformat für tkinter also für ohne modul 'spazieren', welches in einer erweiterten Form 'DynTkInter' heisst.

Angenommen jemand hätte die GUI editiert und auch Namen vergeben, etwa so:

Code: Alles auswählen

from spazieren import *
 
Frame('myFrame')
goIn()
 
Button('buttonQuit',text="""QUIT""",fg='red')
Button('buttonHello',text="""Hello""")
 
widget('buttonQuit').pack(side='left')
widget('buttonHello').pack(side='left')
 
goOut()
 
widget('Frame').pack()
Dann könnte ich diese Namen ja als Variablennamen hernehmen und dann so etwas generieren:

Code: Alles auswählen

from tkinter import *
root = Tk()

def buildGui(parent):

	myFrame=Frame() ### name myFrame
	
	def buildGui(parent):

		buttonQuit = Button(parent,text="""QUIT""",fg='red') ### name buttonQuit
		buttonHello = Button(parent,text="""Hello""") ### name buttonHello
	
		buttonQuit.pack(side='left')
		buttonHello.pack(side='left')

		### CODE ========================================================


		### =============================================================

	buildGui(myFrame)
	myFrame.pack()

	### CODE ============================================================


	### =================================================================

buildGui(root)
del buildGui

root.mainloop()
Und dabei habe ich mir gedacht, wenn ich hinter die betreffende Zeile, in der ein Widget definiert wird einen Kommentar '### name myname' dahinter schreibe, könnte ich beim nächsten Aufruf mir den Namen wieder besorgen.
Und wenn man seinen Code in den Block '### CODE' reinschreibt, kann ich nach dem Editieren der GUI alles zusammen mit Code wieder abspeichern.
Den Code könnte man während des Editierens auch ändern und testen. Allerdings wenn man da die lokalen Widget Variablennamen benützt, das geht nicht. Denn die gibt es zu diesem Zeitpunkt nicht. Zu diesem Zeitpunkt können die Widgets nur mit widget('myname') referenziert werden. Naja, das kann man sich später überlegen, ob man beim GUI Editieren auch Code schreiben und Testen anbietet und wie man das dann eventuell für Variablennamen machen könnte statt für widgets('name')
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Alfons Mittelmeyer hat geschrieben:Und GUI erstellen und ändern geht damit schnell. Die Frage ist aber jetzt, was ist ein brauchbares Abspeicherformat für tkinter also für ohne modul 'spazieren', welches in einer erweiterten Form 'DynTkInter' heisst.
Ich denke es gibt grob zwei Konzepte: Ein Datenformat, welches man dann immer einbindet oder fertigen Code generieren.

Ein Datenformat nutzten, macht z.B. pygubu, siehe: https://github.com/alejandroautalan/pygubu#usage

Hat alles Vor- und Nachteile. Mal auf die schnelle:

PRO Datenformat:
* schöne Trennung
* man kann den GUI Editor immer weiter benutzten
CON Datenformat:
* man muß immer ein modul nutzten, damit die GUI aus dem Datenformat generiert wird

PRO "Code Generierung":
* Man kann eigene Änderungen vornehmen
CON "Code Generierung":
* Man kann den GUI-Editor nicht wieder verwenden, wenn man irgendwas geändert hat
* Keine ganz so schöne Trennung


Ich würde erstmal mir alles ansehen, was es so gibt und dann überlegen, was du wirklich machen willst.
Ich denke auch, das ein GUI Editor auch einiges an Zeit beanspruchen wird.
Ist es nicht Sinnvoller sich bei einem bestehenden Projekt zu beteiligen?!?

Ein paar Links gibt es u.a. hier: https://wiki.python.org/moin/GuiProgramming und http://stackoverflow.com/a/14142360

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@jens Der Gui Editor ist fertig, nur ist der Code grauenhaft. Habe keine Funktionen verwendet. Und um keine zu haben, aus Strings kompiliert. Um keine Variablen zu haben auf Stack gepushed und gepopped. Und noch ein Dictionary für temporäres Merken. Jetzt da ich weiß, wie ich es anders machen kann, ist Umschreiben kein Problem. Und ich möchte einen schönen Code haben, bevor ich ihn veröffentliche.
Was noch fehlt: die Speicherroutine ist nicht für normales tkinter. Und eine Laderoutine, aus der ich von normalem tkinter die Namen bekomme, muss ich auch noch machen. Aber alles keine Schwierigkeit.

Und zu den Formaten, da denke ich zuerst das eine, dann das andere. Es ist ja auch so, dass nicht jeder normale Widgets haben will, sondern seine eigenen Klassen verwenden will. Da wäre es gut, dass er sich dann lediglich die config, layout und noch ein paar Informationen abholt.

Aber zuerst mach ich mal direkt tkinter Code generieren, weil man da Beispiele gleich fertig hat.
Naja Formate sind kein Problem, muß man nur eine entsprechende Speicherroutine dafür implementieren.

Gut, was auch nicht besonders professionell ist, ist das Design des GuiCreators. Schaut nicht so aus, wie man es etwa von professionellen Windows Programmen gewohnt ist.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Release early, release often
Klar kann man warten, bis es "fertig" und "schön" ist... Aber wozu? und wird dieser Zustand jemals erreicht? (Damit meine ich nicht explizit deinen Code!)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jens hat geschrieben:
Release early, release often
Klar kann man warten, bis es "fertig" und "schön" ist... Aber wozu? und wird dieser Zustand jemals erreicht? (Damit meine ich nicht explizit deinen Code!)
Wenn man etwa in einer Woche den Code schön umschreiben kann, dann denke ich dass ich dieses tun sollte. Es war ja der Zweck unserer Diskussionen, Anhaltspunkte zu gewinnen, wie ich es besser machen kann, ohne Speicher zu verschwenden. Wäre zwar für den GuiCreator nicht nötig gewesen. Aber wollte dieses Konzept exemplarisch verwirklichen.

Naja fertig? Neue Features will man immer wieder mal haben. Dafür gibt es dann Releases
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Ach so, Code zur Laufzeit ändern und testen ist auch kein Problem. Dafür kann man dann eine interface Funktion benutzen, die man für normal auskommentiert :

Code: Alles auswählen

#def testing(buttonHelp = widget('buttonHelp'),buttonQuit=widget('buttonQuit)):
if True: # wegen Einrückung, auszukommentieren für den testing Fall
    buttonQuit xxxxxx
    buttonHelp xxxxxx

#testing()
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: zu Deinem Testing, ist mir nicht klar, wie man was zur Laufzeit auskommentieren kann. Dir ist klar, dass Default-Argumente zur Compile-Zeit ausgewertet werden und damit ein >>buttonHelp = widget('buttonHelp')<< nicht funktionieren kann, weil zur Compilezeit das Widget noch nicht existiert.
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Testen sollte man IMHO eh unter möglichst realen Bedingungen. Also so wenig Mockups wie möglich...

btw. gibt es eigentlich ein Testing Toolkit für Tkinter?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jens hat geschrieben:Testen sollte man IMHO eh unter möglichst realen Bedingungen. Also so wenig Mockups wie möglich...

btw. gibt es eigentlich ein Testing Toolkit für Tkinter?
Ein Toolkit gibt es nicht. Es sind keine Mockups. Das Programm läuft unter ganz normalen realen Bedingungen. Nur besteht die Möglichkeit während der Laufzeit sich durch die GUI zu bewegen, die Gui zu editieren und auch den Code, der im besagten Codeblock steht, zu editieren und neu aufzurufen. Dabei wird auch eine Syntaxüberprüfung vorgenommen. Ein nachfolgender Crash bei Programmfehlern wird allerdings nicht abgefangen. Das muß man selber tun. Vor dem Run wird dieser Codeblock in eine externe Datei gespeichert, damit man ihn nach einem Crash wieder bekommt. Bevor man während dem Programmlauf Code modifiziert, sollte man seine Anwendung erst sichern.

Laden einer Anwendung vom GuiEditor aus gibt es in zwei Versionen: mit oder ohne laufenden Code (in besagten Codeblocks). Man kann aber nach Laden ohne laufenden Code danach Codeteile ausführen lassen. Oder man lädt die Anwendung nach abspeichern neu mit laufendem Code. Man kann seine Anwendung auch in Module splitten. Man kann seine gesplitteten Module auch wieder zusammenfügen. Auch alles zu einem einzigen großen Modul.

Man kann Teilanwendungen in beliebige Frames laden und wie gesagt alles unter realen Bedingungen.

Der GuiEditor ist Teil der Anwendung und läuft in einem TopLevel Window. Und wenn man ihn schließt, ist er weg. Über eine Task mit input und Funktionsaufrufen läßt er sich wieder jederzeit neu laden. Zweimal ihn parallel zu haben ist nicht zu empfehlen, was zwar wie Stereo oder Synchron aussieht, aber man will ja nicht, dass zwei Widgets gleichzeitig angelegt werden.
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: leider tut Dein Spaziergang bei mir nicht:

Code: Alles auswählen

> ls()
=> \.
   Frame
> Tcl_WaitForEvent: Notifier not initialized
Abort trap: 6
Ich gehe mal davon aus, dass es daran liegt, dass Du versuchst, von einem Thread aus auf die GUI zuzugreifen.
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

Hi Alfons
Wollte einmal dein Skript ausprobieren und nach wenigen Schritten spazieren kam es ins stolpern :-):

Code: Alles auswählen

> ls()
=>  \.
    Frame
> goto('Frame')
> ls()
    \.
    Frame
> goln()
Error: goln()
Habe ich hier eventuell einen Fehlschritt gemacht?
N.B: Wäre noch gut wenn nach einem Start der Focus direkt aufs Terminal gesetzt würde.
(Mein Setup: Ubuntu 14.04 LTS & Python 3.4)

Gruss wuf :wink:
Take it easy Mates!
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

wuf hat geschrieben:Hi Alfons
Wollte einmal dein Skript ausprobieren und nach wenigen Schritten spazieren kam es ins stolpern :-):

Code: Alles auswählen

> ls()
=>  \.
    Frame
> goto('Frame')
> ls()
    \.
    Frame
> goln()
Error: goln()
Habe ich hier eventuell einen Fehlschritt gemacht?
N.B: Wäre noch gut wenn nach einem Start der Focus direkt aufs Terminal gesetzt würde.
(Mein Setup: Ubuntu 14.04 LTS & Python 3.4)

Gruss wuf :wink:
Ja, den Fehler sieht man im Code Teil, weil dort ein großes i nicht wie ein kleines L aussieht.
Es handelt sich richtig um "go in" zusammengeschrieben aber mit großem i bei in. Und schriebst ein kleines L
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:@Alfons Mittelmeyer: leider tut Dein Spaziergang bei mir nicht:

Code: Alles auswählen

> ls()
=> \.
   Frame
> Tcl_WaitForEvent: Notifier not initialized
Abort trap: 6
Ich gehe mal davon aus, dass es daran liegt, dass Du versuchst, von einem Thread aus auf die GUI zuzugreifen.
Wäre möglich, dass Windows bei solchen Treads nicht mitspielt. Also unter Linux Ubuntu gibt es keine Probleme die GUI auch von einem Thread aus zu verändern. Man könnte natürlich auch noch ein Entry Feld einbauen und dann von der App aus die Befehle aufrufen statt über einen Thread. Vielleicht mache ich das heute noch irgendwann, damit es auch unter Windows keine Probleme gibt. Bei Dot .Net hat man dasselbe Probleme, kann aber über einen Backgroundworker an die App weiterleiten. Bei Python unter Windows könnte man über Locks, after und Flagabfragung von der App her aus nachfragen, ob etwas da ist und es dann ausführen, am besten im Thread schon compilert und in der App dann nur mehr eval.

Aber die Einfachste Lösung für dieses Beispiel wär wohl noch ein Entry Feld. Und wenn es nicht in der App sein sollte, dann am Besten in einem Toplevel. Das sollte ich machen, um das Prinzip zu verdeutlichen.

Der GuiDesigner - über den Namen bin ich mir nocht nicht schlüssig - benutzt selbstverständlich keine Threads, sondern ist erweiterte Applikation in einem Toplevel Window
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Du bist ein echter fan von 'eval',was? :twisted:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
wuf
User
Beiträge: 1529
Registriert: Sonntag 8. Juni 2003, 09:50

@Alfons Mittelmeyer: Danke! Hat jetzt geklappt.
Gruss wuf :wink:
Take it easy Mates!
Sirius3
User
Beiträge: 17747
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: noch ein Grund, warum man sich an die Namenskonvention halten sollte, bei "go_in" gibt es keine Mißverständnisse.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

jens hat geschrieben:Du bist ein echter fan von 'eval',was? :twisted:
Er ist halt der Rebell des Forums, quasi ein Python Punk, der aus Prinzip alles anders macht, alle Regeln bricht und Ratschläge konsequent ignoriert... :roll:
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Python Punk
:mrgreen:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Sirius3 hat geschrieben:@Alfons Mittelmeyer: noch ein Grund, warum man sich an die Namenskonvention halten sollte, bei "go_in" gibt es keine Mißverständnisse.
Sorry hatte nicht gewußt, dass bei Eurer Normalschriftart groß i genauso wie klein L aussieht. Wenn man eintippt, hat man eine andere Schriftart bei der der Unterschied deutlich ist. Aber was Ihr dann ausgebt unterscheidet sich.
Gesperrt