Alfons Mittelmeyer's Wundersame Welt

Fragen zu Tkinter.
BlackJack

@Alfons Mittelmeyer: Du bist masochistisch. Hat Sirius3 doch deutlich geschrieben wer. Wenn Dein Textverständnis so schlecht ist das Du noch nicht einmal das verstehst, dann erklärt das vielleicht so einiges.

Nicht alles was man importieren kann macht Sinn, das heisst man muss nicht alles importieren. Das was man nicht importieren muss weil es keinen Sinn macht muss man aber auch nicht mit `compile()` und `exec` verwursten, eben weil es keinen Sinn macht. Man muss es gar nicht erst schreiben. ;-)

Niemand hat hier etwas für einen solchen Browser gefordert, denn solch einen Browser gibt es nicht. Den führst Du hier doch bloss an weil Dir mittlerweile wohl selber dämmert das Dein `compile()` und `exec` schwachsinn ist und Du verzweifelt nach einem Anwendungsfall suchst der das vielleicht doch noch irgendwie rechtfertigen könnte. So ein Browser wäre aber wieder ein Sonderweg der durch Standardmittel wie HTML bereits abgedeckt ist. HTML ist besser geeignet als Python-Code für Tk-GUI-”Seiten” weil HTML genau für diesen Zweck — Dokumente mit Verlinkungen — entwickelt wurde. HTML direkt ist schon besser und einfacher zu schreiben und zu verwalten, aber es gibt sogar noch Werkzeuge die Dokumentation/Hilfe schreiben nochmal einfacher machen und durch Funktionalität die man dafür brauchen kann erweitern (Suche, Index, verschiedene Formate (HTML, PDF, Textverarbeitungsdokumente, E-Books, …), …).

Wenn in der HTML-Hilfe auf Clientseite Programmierung nötig sein sollte, dann in der Tat mit JavaScript weil das die Sprache ist die Browser kennen. Wie Du auf PHP und Apache kommst ist mir ein Rätsel, denn man kann in Python sogar mit mitteln der Standardbibliothek sehr leicht einen HTTP-Server aufsetzen. Wenn man serverseitig Programmlogik braucht lässt die sich in Python umsetzen. Wenn man ein Microwebrahmenwerk wie Bottle oder Flask verwendet sogar mit wenig Aufwand.

Nicht Python ist in einem Datenformat für GUI-Beschreibungen Teufelswerk sondern generell dort Programmcode unterbringen zu wollen ist es. Der Sinn von so einem Datenformat ist es ja gerade wie bei Qt ein *Sprachunabhängiges* Format zu haben wo man für jede Programmiersprache die das verwenden möchte eine kleine Bibliothek schreibt die solche UI-Beschreibungen in Programme einbindet. Was bei Tk durchaus Sinn macht weil es für eine ganze Reihe von Programmiersprachen eine Anbindung an das Rahmenwerk gibt und sich somit der Wert eines GUI-Editors steigert. Selbst wenn an selbst für diese anderen Programmiersprachen keine Bibliothek zum Einbinden der Datendateien schreibt, gibt es die Möglichkeit das jemand anderes das tut.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

BlackJack hat geschrieben:Niemand hat hier etwas für einen solchen Browser gefordert, denn solch einen Browser gibt es nicht. Den führst Du hier doch bloss an weil Dir mittlerweile wohl selber dämmert das Dein `compile()` und `exec` schwachsinn ist und Du verzweifelt nach einem Anwendungsfall suchst der das vielleicht doch noch irgendwie rechtfertigen könnte.
Natürlich gibt es so einen Browser. Die DynTkInter Widgets LinkLabel und LinkButton erlauben eine nicht beschränkte Verlinkung von Seiten. Zur Zeit allerdings nur auf das lokale Filesystem und das lokale Netzwerk beschränkt. http:// ist noch nicht implementiert, da auch noch kein Webserver hierfür existiert. Aber http request und response zu implementieren, ist ja kein Problem.
BlackJack hat geschrieben:So ein Browser wäre aber wieder ein Sonderweg der durch Standardmittel wie HTML bereits abgedeckt ist. HTML ist besser geeignet als Python-Code für Tk-GUI-”Seiten” weil HTML genau für diesen Zweck — Dokumente mit Verlinkungen — entwickelt wurde. HTML direkt ist schon besser und einfacher zu schreiben und zu verwalten, aber es gibt sogar noch Werkzeuge die Dokumentation/Hilfe schreiben nochmal einfacher machen und durch Funktionalität die man dafür brauchen kann erweitern (Suche, Index, verschiedene Formate (HTML, PDF, Textverarbeitungsdokumente, E-Books, …), …).
Natürlich ist HTML besser geeignet als tkinter GUI), um alles Mögliche darzustellen. Images können in verschiedenen Formaten benutzt werden. Um Images gibt es Textumfluss. Und da gibt es Vieles, was HTML bietet, tkinter aber nicht.

Aber HTML ist völlig ungeeignet als Beispiel für tkinter Code. Und wenn es um Beispiele für tkinter geht, dann müssen die Dateien auch tkinter und Python Code enthalten.
BlackJack hat geschrieben:Nicht Python ist in einem Datenformat für GUI-Beschreibungen Teufelswerk sondern generell dort Programmcode unterbringen zu wollen ist es.
Ein Teufelswerk würde das, wenn man x-beliebige Seiten als Module importieren würde und ihnen gestatten würde alles zu tun. Vielmehr geht es um die Beschränkung von Rechten, so etwa keinen Zugriff auf das Filesystem und vor allem keinen import erlauben. Ein Modul muss sich Zugriffe auf Anderes durch import besorgen. Wenn man das nicht erlaubt, ist es so ziemlich nutzlos.

BlackJack hat geschrieben:Der Sinn von so einem Datenformat ist es ja gerade wie bei Qt ein *Sprachunabhängiges* Format zu haben wo man für jede Programmiersprache die das verwenden möchte eine kleine Bibliothek schreibt die solche UI-Beschreibungen in Programme einbindet. Was bei Tk durchaus Sinn macht weil es für eine ganze Reihe von Programmiersprachen eine Anbindung an das Rahmenwerk gibt und sich somit der Wert eines GUI-Editors steigert. Selbst wenn an selbst für diese anderen Programmiersprachen keine Bibliothek zum Einbinden der Datendateien schreibt, gibt es die Möglichkeit das jemand anderes das tut.
Sorry für tk gibt es kein solches *Sprachunabhängiges* Format. Wenn man so etwas wollte, dann müsste man da ein internationales Gremium ins Leben rufen, welches ein solches Format für tk spezifiziert.

Außerdem müßte es dann auch eine entsprechende tkinter Python Erweiterung geben, welche dieses Format versteht.
BlackJack

@Alfons Mittelmeyer: Ein Sprachunabhängiges Datenformat zur Beschreibung von Tk-GUIs braucht kein internationales Gremium sondern jemanden der es entwirft und eine Bibliothek dafür schreibt.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

@Alfons: Schau Dir doch mal an, wie das bei guten Lösungen wie Qt gemacht wird. Damit meine ich nicht einmal das tief technische, sondern allgemein das Tooling und Vorgehen. Vielleicht wird Dir dann zumindest klar, wie sich das "anfühlt".
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Hyperion Das Qt XML Format ist ein sehr komplexes Format. Ein solch komplexes Format würde viel Arbeit kosten.
Einfacher wäre ein einfacheres Format:

Code: Alles auswählen

# etwa statt
grid(row=2,column=1)

# eventuell
<grid>
    <row>2</row>
    <column>1</column>
</grid>
Also das wäre keine Python Syntax. Doch will das jemand zu irgendeinem Zweck benutzen? Jedenfalls muss man für tkinter die dafür zuständige Interface Funktion aufrufen. Das bedeutet dieses Format erzeugen, nur damit man es wieder zurückverwandeln muss. Das sind doch nur zwei unnötige Schritte, die man sich auch sparen kann.

Und außerdem hatte ich schon einmal ein JSON Format vorgeschlagen. Und dann bekommt man zur Antwort, dass man das nicht haben will. Denn ich hatte auch gezeigt, dass man da aus einem Datensatz für einen Button auch einen Button erzeugen kann. Das wäre ja eine 'Syntax' hatte man da geäußert und eine Syntax will man nicht haben. Es ist einfach so, dass man aus einem Datensatz für einen Button auch einen Button erzeugen kann, ganz egal, welches Format das ist. Und ungerne definiere ich ein Format und implementiere es und am Ende will es keiner.

Der Hinweis, ich solle mir Qt ansehen, nutzt wenig, denn wie gesagt, das Format ist sehr komplex. Wenn Ihr ein bestimmtes Format haben wollt, dann bitte spezifiziert es. Etwas, das für die Katz ist, will ich nicht implementieren.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Dann ist außerdem die Frage, was man mit so einem Format will. Soll es nur zur Widget Erzeugung dienen und ist bei der errsten Änderung nutzlos? Oder will man, dass es immer da ist und aktualisiert wird, dass etwa grid_info() die Daten im XML Format liefert? Das geht doch wohl etwas zu weit oder? Wäre aber machbar, wenn man eine zweite Funktion hätte, die anders heißt, etwa xml_grid_info()

Und wenn man von Programmiersprachenabhängigkeit wegkommen will, wäre wohl ein FORTH Interpreter die richtige Lösung für Callback Funktionen. Denn ein solcher ist ohne großen Aufwand in so ziemlich jeder Programmiersprache implementierbar. Und man hat dann auch keinen Python Code drin.

Aber soll man da Python vervbeten, oder die Wahl lassen durch:

Code: Alles auswählen

<python>
...
</python>
bzw.

Code: Alles auswählen

<forth>
...
</forth>
BlackJack

@Alfons Mittelmeyer: Da gehört gar kein Code rein. :roll: Und warum und bei welcher Änderung so ein Format nutzlos werden soll ist aus dem Beitrag auch nicht ersichtlich.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@BlackJack Bei HTML kann man aber Javascript einbinden und mit php geht es auch. Man kann es natürlich auch anders machen. Jedem, wie es ihm beliebt - ist meine Auffassung.

Und dann handelt es sich nicht um ein Datenformat, sondern nur um ein Datenerzeugungsformat. Und wo die Daten erzeugt werden, hängt ganz davon ab, wo man sie hineinlädt. Man kann sie nach ganz nach Belieben in jedes dafür passende Containerwidget laden. Natürlich keine Buttons in ein Menü.

Und die Datenstruktur, die erzeugt wird, sieht anders aus, als das Erzeugungsformat. Wenn man über Formate spricht, sollte man zuerst einmal über das tatsächliche Datenformat reden, bevor man das Erzeugungsformat auf das Korn nimmt.

Wie sieht etwa das DynTkInter Datenformat aus, für so etwas:

Bild

Das Childrendictionary sieht so aus:

{'RIGHT': [<DynTkInter.Button object at 0x412daa50>], 'LEFT': [<DynTkInter.Button object at 0x412dad50>], 'TOP': [<DynTkInter.Button object at 0x412dad90>], 'PackTitle': [<DynTkInter.Label object at 0x412daa30>], 'BOTTOM': [<DynTkInter.Button object at 0x412da970>]}

Das sind die eigentlichen Daten. Was will man damit tun? Ist das zu gebrauchen?

Was man damit tun kann, ist etwa mit widget('LEFT') sich die Referenz geben lassen. Weitere Daten kann man mit config() bekommen oder auch mit grid_info()

Außerdem kann man mit Layout abfragen, ob es ein GRIDLAYOUT ist. Denn wenn es ein Pack Layout wäre, soll man nicht grid_info() aufrufen.
Gut, das war es nicht ganz. Außerdem gibt es eine Liste mit Referenzen auf Widgets, für die eine bestimme Layout Reihenfolge einzuhalten ist. Das betrifft pack, Panes und Menüeinträge. Diese Liste wird ständig aktualisiert und beim Abspeichern benötigt. Bei Menüeinträgen aber auch benötigt, wenn man Menüeinträge verschiebt.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Also, wenn jemand XML haben möchte für das Layout, dann braucht er auch nicht verschiedene Funktionen anpassen, sondern nur eine einzige Funktion xml_layout_info() schreiben, bei der er meine DynTkInter Methode layout_info() aufruft:

Code: Alles auswählen

    def layout_info(self):
        layout = self.Layout
        if layout == PACKLAYOUT: dictionary=self.pack_info()
        elif layout == GRIDLAYOUT: dictionary=self.grid_info()
        elif layout == PLACELAYOUT: dictionary = self.place_info()
        elif layout == PANELAYOUT: dictionary = self.pane_info()
        elif layout == MENUITEMLAYOUT: dictionary = self.menuitem_info()
        else: dictionary = {}
        return dictionary
Hier erhält man ein Dictionary. Die Einträge kann man dann durch XML ersetzen. Wenn jemand das bei config auch so haben möchte, kann er auf meine Methode getconfdict zurückgreifen:

Code: Alles auswählen

    def getconfdict(self):
        dictionary = self.config()
        ConfDictionaryShort(dictionary)
        if 'image' in dictionary:
            del dictionary['image']
            dictionary['photoimage'] = self.photoimage
        return dictionary
Allerdings einen ganzen XML-Baum für die ganze GUI sollte man nicht machen, denn das wäre eine globale Struktur. Und die sollte man nicht haben. Daher nur jeweils für die direkten Children, es sei denn, man fertigt eine Momentaufnahme, etwa für das Abspeichern an.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wieso "Momentaufnahme"? Bei einem GUI Editor geht es primär um das Erzeugen von dauerhaften Strukturen! Man will ja gerade möglichst viel GUI Komponenten fertig designen, und danach mit der Logik verbinden. Dabei spielt es quasi keine Rolle, wie groß oder komplex eine Komponente ist. Daraus wird ja nur *einmal* ein Objekt-Baum erzeugt; nämlich beim Start der Applikation! Die XML-Struktur spiegelt ja lediglich die GUI Komponenten wieder - insofern ergibt sich dessen Komplexität unmittelbar aus der Komplexität der GUI Komponente an sich!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Hyperion Ja, manche mögen gerne dauerhafte Strukturen und ich mag gerne ständig was dazuladen und wieder herauslöschen, also voll dynamisch und fortwährend sich ändernd. Allerdings auch Sachen, die länger erhalten bleiben. Und wenn man dazulädt und wieder löscht, dann wäre ein globaler XML-Baum schwer zu pflegen. Dagegen, wenn man nur ein Children Dictionary hat und löscht das Container Widget, dann ist das einfach von selber mit weg. Da braucht man nicht irgendwelchen Baum zu pflegen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Hyperion Ich will natürlich nicht sagen, dass XML keinen Sinn macht. Wenn man die GUI statisch betrachtet, dann auf XML arbeitet und zum Schluss tkinter erzeugen macht, das sollte schon gehen. Wenn man aber zwei unterschiedliche Strukturen parallel, synchron und dynamisch verwalten wollte, das wäre etwas sehr aufwändig - etwa dass man Änderung in tkinter bei XML nachzieht und umgekehrt und dann alle Funktionen doppelt hätte, nämlich für tkinter und für XML.
Sirius3
User
Beiträge: 18051
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: Du willst alles Dynamisch haben, und das ist bei einem Designer auch sinnvoll (bei einer Anwendung seh ich das jetzt nicht direkt). Aber genau für das dynamische brauchst Du ja eine interne Repräsentation und diese in ein externes Format (wie z.B. XML) umzuwandeln, ist ja nicht kompliziert. XML im Speicher brauchst Du nicht.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@Sirius3 Was man braucht oder nicht braucht, das muss man schreiben und wie man sich das mit XML vorstellt. Soll das nur eine GUI Definition sein, die man im Source File ändern kann und die nach der GUI Erzeugung hinfällig wird? Oder soll es eine XML Struktur im Speicher sein, auf der man dann arbeitet anstatt auf normalem tkinter, also so eine Art von XML tk mit doppelten Referenzen (XML + tkinter - eventuell tkinter verborgen, da XML dann die primäre Struktur ist) und neuen Funktionen.

Also bitte Vorstellungen dazu äußern.

Hyperion hatte geschrieben, dass man mit XML in Qt eine Menge anstellen kann. Wenn man aber XML nur zur Erzeugung benützt, braucht man es eigentlich gar nicht, denn die GUI hat man bereits im GUI Designer definiert und es geht dann nur mehr um die Callbacks dazu (command, events) und den Einbau der widget Referenzen in die eigene Programmstruktur.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Wir könnten ja zum Spezifizieren anfangen. Und zwar geht es um Eigenschaft und Inhalt eines Containerwidgets.

Code: Alles auswählen

<content> - wird nur verwendet, wenn der Inhalt eines Container widgets gespeichert wird und nicht das Widget selber

    <config> - ist eigentlich kein content sondern enthält Eigenschaften des container widgetws - optional, nur bei Abweichung von Defaultwerten
        ... 
    </config>

   <children> - falls children vorhanden
        ....
   </children>

    <layout_order>  -  nur bei besimmten layouts, etwa pack, pane, menu entry
        ....
    </layout_order>

</content>
Dabei wird config als config des container widgets übernommen in welches dieser content geladen wird.

Dann müßte man die Configeinträge festlegen, etwa so?

<fg value = 'blue' />
<bg value = 'white' />

Problem Texteinträge mehrzeilig auch mit Sonderzeichen, Umlauten, < und > Zeichen, wie umwandeln?
Gibt es da eine Routine, die das macht?
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Alfons:
Du willst also einen "Browser" für Applikationsoberflächen und Logik bauen, welcher alles auch remote nachladen kann. Soso. Nach dem warum frage ich erst gar nicht. Dir ist aber hoffentlich klar, warum HTML-Browser eine Sandbox für Javascript haben und z.T. sogar die Prozesse in einer Art chroot-Umgebung laufen lassen. Wenn Du das verstanden hast, erübrigt sich jede weitere Diskussion um eval/exec & Co.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@jerch Genau das ist der Grund compile und exec zu verwenden. Denn so etwas als Modul zu importieren und zuzulassen, dass ein Modul einen import ausführt, ist sträflicher Leichtsinn. Bei exec dagegen kann ich durch Angabe von globals und locals festlegen, was ausgeführt werden darf und was nicht und bestimmt kein import und auch kein File access.

Ein böses Script könnte dann nartürlich eine Endlosschleife implementieren oder die GUI vollpflastern oder den Bildschirm falls man Toplevel zuläßt. Man könnte es aber auch auf eine bestimmte Fenstergröße beschränken, indem man ihm auch den Zugriff auf das Container Widget sperrt. Dann wäre Endlosschleife noch bös oder Speicher zumüllen, bis Python sich beendet.

Aber anscheinend soll man sowieso den Speicher zumüllen, wenn es nach Euch geht.
Zuletzt geändert von Alfons Mittelmeyer am Dienstag 10. November 2015, 13:10, insgesamt 1-mal geändert.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

@Alfons:
Nein, nein und nochmals nein. Die Sicherheitsprobleme hinterm Laden von Fremdcode sind weder mit import noch mit exec zu lösen. Das ist für sowas schlichtweg der falsche Ansatz. Du reduzierst allzu leicht auf die import vs. exec Sache, meine Anmerkung ist kein Proargument für import - für das was Du vorhast, braucht Du ganz andere Geschütze. Die Diskussion hatten wir schonmal, hier wie damals nochmal der Hinweis, dass die Browserentwickler seit ~15 Jahren an den Sicherheitskonzepten arbeiten. Das baut man nicht mal eben mit frickliger Scriptlösung nach.
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

@Alfons Mittelmeyer: Verständnisfragen, keine Kritik!
Zunächst einmal finde ich es bewundernswert wie Du hier Dein Ding durchziehst.
Die Fragen:
  • Stammt der Thread Titel "Alfons Mittelmeyer's Wundersame Welt" von Dir oder war das ein kleines Machtspielchen von jemadem mit Admin-Rechten?
  • Versuchst Du in Deinem Projekt Funktionalitäten für TK zu schaffen, die es in PyQt schon längst gibt? Wenn ja, macht das Sinn? Wäre es nicht einfacher Du würdest PyQt nehmen?
a fool with a tool is still a fool, www.magben.de, YouTube
Liffi
User
Beiträge: 153
Registriert: Montag 1. Januar 2007, 17:23

MagBen hat geschrieben: Stammt der Thread Titel "Alfons Mittelmeyer's Wundersame Welt" von Dir oder war das ein kleines Machtspielchen von jemadem mit Admin-Rechten?
Der Titel der ersten Antwort ist "Re: tkinter unter eclipse". Würde also auf Abtrennen aus einem Thread durch einen Moderator vermuten.
Antworten