ubuntuusers.de

Python und tk-Fenster

Status: Gelöst | Ubuntu-Version: Ubuntu 16.04 (Xenial Xerus)
Antworten |

HP-Fan

Avatar von HP-Fan

Anmeldungsdatum:
2. September 2012

Beiträge: 394

Wohnort: Schweiz (CH)

Morgen Leute

Ich habe ein kleines Testprogramm in Python3 und möchte den Inhalt in einem tk-Fenster ausgeben. Wenn ich im Terminal in den Python3-Modus wechsle und diese Befehle eingebe öffnet sich auch ein tk-Fenster in der linken oberen Ecke:

1
python3
1
import tkinter
1
tkinter.Tk()

Als Prompt-Antwort kommt:

1
<tkinter.Tk object .>

Und das tk-Fenster öffnet sich an besagter Stelle. Starte ich aber nachfolgendes Programm mit...

1
./Test.py

... habe ich die Ausgabe wieder nur im Terminal:

Und das tk-Fenster öffnet sich gar nicht erst. Das Test-Programm sieht so aus:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Kommentar: Mein abgewandeltes Hallo-Welt-Programm fuer Python 3


import os
import sys
import time
import tkinter # Das ist von mir zur Einbindung des tk-Fensters

tkinter.Tk () # Und das ist von mir zum öffnen des tk-Fensters

os.system('clear')

print('Hallo Welt!')
print('Bitte Irgendwas eingeben:')

input = sys.stdin.readline()
input = input.strip() # Newline (\n) am Ende der Eingabe entfernen

i = str(input)

print(i  + 'test') # Test String-Befehle

time.sleep(1)
os.system('clear')
print('5')
time.sleep(1)
os.system('clear')
print('4')
time.sleep(1)
os.system('clear')
print('3')
time.sleep(1)
os.system('clear')
print('2')
time.sleep(1)
os.system('clear')
print('1')
time.sleep(1)
os.system('clear')
print('Ende')
time.sleep(1)

Jetzt stellt sich die Frage, warum die tk-Fensterbefehle manuell im Prompt funktionieren, nicht aber im "Test.py"-Programm?

Gruß HP-Fan

apt-ghetto

Anmeldungsdatum:
3. Juni 2014

Beiträge: 2943

Ich bin kein Python-Programmierer, aber ich kenne es etwas.

In Zeile 11 erzeugst du zwar ein Objekt, aber du machst nichts damit (es überlebt auch nicht lange, da es nirgendwo referenziert wird). Was möchtest du denn damit tun? Welche Elemente soll es anzeigen?

Der Rest von deinem Programm nutzt einfach STDIN und STDOUT, hat also in keiner Weise etwas mit deinem unreferenzierten, ungenutzten Fensterobjekt zu tun.

HP-Fan

(Themenstarter)
Avatar von HP-Fan

Anmeldungsdatum:
2. September 2012

Beiträge: 394

Wohnort: Schweiz (CH)

Hallo apt-ghetto

Ich wollte in einem ersten Schritt mal ein eigenes Fenster kreieren und darin das Programm laufen lassen. Also die Tastatureingaben und Programmausgaben in diesem neuen tk-Fenster.

Gruß HP-Fan

apt-ghetto

Anmeldungsdatum:
3. Juni 2014

Beiträge: 2943

Dann musst du ein Fenster erzeugen und es einer Variable zuweisen, damit du das Fensterobjekt auch weiter nutzen kannst. Dann brauchst du auch Anzeigeelemente (weitere Objekte) wie Labels und/oder Textfelder etc, die dann vom Fensterobjekt dargestellt werden.

Am besten du schaust dir ein paar Tutorials zum Thema an.

Und als Denkanstoss: Wäre auch ein Webframework denkbar?

HP-Fan

(Themenstarter)
Avatar von HP-Fan

Anmeldungsdatum:
2. September 2012

Beiträge: 394

Wohnort: Schweiz (CH)

Hallo apt-ghetto

Ja, mit einem Web-Framework ist das alles kein Problem - ich komme ursprünglich aus der Webdesigner-Ecke. Webserver an, .shtml und cgi und ein serverseitiges Script wie Perl - fertig. Das ist nicht schwierig für mich. In diesem Fall soll aber ein lokales Programm im eigenen Fenster laufen.

Ich habe mir mal ein Tutorial(*) angesehen, das lediglich ein einzeiliges Textfeld erzeugt, und mittels Bottom-Knopf die gemachte Eingabe in das Terminal schreibt. Der Programmcode für "so eine leichte Aufgabe" ist gewaltig - finde ich. Es wird eine Weile dauern, bis ich das alles verstanden habe.

Soweit ich das sehe, läuft das tk-Fenster in einer Art "Dauerschleife" oder "Überprogramm" und man muss dem Fenster genau mitteilen, was es machen soll. Also es zeigt Ausgaben nicht von alleine an. Textfelder einzeilig (entry) und mehrzeilig (text) müssen erst erstellt werden. Die Komponenten, die man braucht , oder denen man Informationen mitgibt nennen sich glaub ich, "widgets"...

Das kann auf jeden Fall noch heiter werden...

Hier mal ein Beispiel wie bei (*) beschrieben. Im Gegensatz zu einer html-Ausgabe wirklich Overkill (vor allem Zeile 31-37):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Kommentar: Mein abgewandeltes Hallo-Welt-Programm fuer Python 3


import os
import sys
import time
from tkinter import * # Das ist von mir zur Einbindung des tk-Fensters

master = Tk()

e = Entry(master)
e.pack()

e.focus_set()

def callback():
    print (e.get())

b = Button(master, text="get", width=10, command=callback)
b.pack()

mainloop()

e = Entry(master, width=50)
e.pack()

text = e.get()

def makeentry(parent, caption, width=None, **options):
    Label(parent, text=caption).pack(side=LEFT)
    entry = Entry(parent, **options)
    if width:
        entry.config(width=width)
    entry.pack(side=LEFT)
    return entry

user = makeentry(parent, "User name:", 10)
password = makeentry(parent, "Password:", 10, show="*")

content = StringVar()
entry = Entry(parent, text=caption, textvariable=content)

text = content.get()
content.set(text)

Danke für deinen Einsatz...

Gruß HP-Fan

noisefloor Team-Icon

Anmeldungsdatum:
6. Juni 2006

Beiträge: 29567

Hallo,

shtml und cgi und ein serverseitiges Script wie Perl - fertig

Äh... wir schreiben das Jahr 2017... *SCNR*

Zum eigentlichen Thema:

Ja, GUI-Programmierung braucht relativ viele Code-Zeilen. Weil du für jedes GUI-Element mindestens eine Zeile Code plus ein paar Zeile zum Platzieren plus mögliche Callback-Funktionen plus... das ist halt so.

Unter Python erstellt man normalerweise auch Klassen für die GUI. Bei einem Trivial-Beispiel wie dem deinigen ist das noch nicht nötig, aber bei Fenstern mit ein paar mehr Elementen macht das schon Sinn (bzw. anders macht es keinen Sinn).

Tk ist ja vergleichsweise altbacken. Wenn du das leistungsfähigere Qt oder GTK nimmst, kannst du die GUI-Elemente in eine eigene Datei auslagern.

Aber wenn du dich mit Webdesign auskennst - was spricht dann gegen eine lokale Client-Server-Lösung? Lässt sich mit Python unter Einsatz von z.B. Bottle oder Flask auch umsetzen.

Gruß, noisefloor

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4677

Wohnort: Berlin

@HP-Fan: Alles ab Zeile 25 macht nicht wirklich Sinn weil in Zeile 24 der Aufruf von mainloop() solange blockiert bis das Fenster geschlossen wird. Und nachdem das Fenster geschlossen wurde, kann man da auch keine weiteren Widgets mehr hinzufügen.

Die Zeilen 42 bis zum Ende sind falsch beziehungsweise sinnlos wenn das mainloop() erst danach käme, denn zu dem Zeitpunkt wo content abgefragt wird, hatte der Benutzer noch gar keine Gelegenheit irgend etwas einzugeben. Wobei ich auch gerade sehe das caption in Zeile 43 gar nicht definiert ist.

Sternchen-Importe werden in Tutorials, gerade bei tkinter, recht häufig gezeigt, aber man sollte sie nicht verwenden. Damit importiert man *alles* aus dem Modul in den Namensraum des importierenden Moduls. Bei tkinter sind das so um die 190 Namen, von denen Du sicher nur einen Bruchteil tatsächlich verwendest. Das wird unübersichtlich, kann zu Namenskollisionen führen, und macht das Konzept von Modulen kaputt. Üblicherweise verwendet man import tkinter as tk und referenziert dann die Namen in dem Modul über tk.irgendwas.

Zeig das gleiche doch mal mit Perl-Skript und HTML. Ich bezweifle, dass das wirklich viel kürzer ist.

Ich würde bei Python nicht mit GUI-Programmierung anfangen, sondern vorher objektorientierte Programmierung (OOP) separat lernen. Denn die braucht man für so ziemlich jedes nicht-supertriviale GUI-Programm und es ist wahrscheinlich einfacher nicht beides auf einmal zu lernen, sondern nacheinander. Bei GUI-Programmierung kommt dann auch noch das was Du „Dauerschleife“ oder „Überprogramm“ nennst, was man allgemein als ereignisorientierte Programmierung bezeichnet, wo man Code schreibt der auf Ereignisse reagiert. Das ist bei den anderen verbreiteten GUI-Rahmenwerken auch so. Ebenso im Browser bei JavaScript, was ja auch eine Art GUI-Rahmenwerk ist.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4677

Wohnort: Berlin

@HP-Fan: Hier ist das was sinnvoll bis Zeile 24 in Deinem Python-Beispiel läuft, in HTML+JavaScript:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
  <head>
    <title></title>
    <meta charset="utf8">
  </head>
  <body>
    <input id="e" type="text" name="e" autofocus>
    <button id="b">get</button>
    
    <script type="text/javascript">
      var callback = function () {
        console.log(document.getElementById('e').value);
      };
      document.getElementById('b').addEventListener('click', callback);
    </script>
  </body>
</html>

Wenn man aus den ersten 24 Python-Zeilen das Unbenötigte raus wirft, zum Beispiel die Importe die nirgends verwendet werden, dann ist das Python-Programm sogar kürzer.

noisefloor Team-Icon

Anmeldungsdatum:
6. Juni 2006

Beiträge: 29567

Hallo,

@BlackJack: FYI - im dir bekannten deutschen Python-Forum gibt es eine neuere Version des Programms vom gleichen TE, dort aber unter anderem Namen. Die "Fehler" sind die gleiche, die Tipps die wir da so geben, auch. Hat bis dato aber nicht soooo viel genützt... 😉

Gruß, noisefloor

HP-Fan

(Themenstarter)
Avatar von HP-Fan

Anmeldungsdatum:
2. September 2012

Beiträge: 394

Wohnort: Schweiz (CH)

Abend im Vorbeiflug...

@noisefloor

Die "Fehler" sind die gleiche

Dieser Code...

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Kommentar: Mein abgewandeltes Hallo-Welt-Programm fuer Python 3


import os
import sys
import time
from tkinter import * # Das ist von mir zur Einbindung des tk-Fensters

master = Tk()

e = Entry(master)
e.pack()

e.focus_set()

def callback():
    print (e.get())

b = Button(master, text="get", width=10, command=callback)
b.pack()

mainloop()

e = Entry(master, width=50)
e.pack()

text = e.get()

...ist aus einem Python Tutorial. Also nicht von mir. Da gibt es keinen Grund für, persönlich zu werden.

Und mal angenommen ich wäre der, aus dem anderen Forum:

Wenn ich zu einem Ubuntu-Betriebssystem Fragestellungen hier posten würde, und bei Python-Fragestellungen in einem Python-Fachforum um Rat suchen würde,

So wäre das legitim!

Ich finde es immer unmöglich, wenn einer glaubt, eine Verbindung gesehen zu haben, dann meint, er müsste solche Personen wie von der "Polizei verfolgt" öffentlich anprangern. So ein Verhalten fände ich Sch****. Ganz schlechte Kinderstube! Wenn du also glaubst, etwas herausgefunden zu haben, dann behalte das für dich!

Wir sind hier nicht bei der Stasi. Und hier ist auch nicht das Ministerium für Staatssicherheit (MfS).

Des weiteren habe ich diesen Post doch schon als gelöst markiert - da braucht man dann nicht noch in der Vergangenheit herum zu stochern, für ein Problem, welches schon längst gelöst ist! Der ganze Quatsch vom vorherigen post ist Meinungsmache und trägt zur Lösung nichts bei - kann nichts beitragen - da schon gelöst!

Als Moderator würde ich alle posts die Querverweise, oder vermeintliche Querverweise beinhalten, löschen → sowas gibt immer Stress!

Und hiermit bitte ich um Löschung des vorausgegangenen posts und von mir aus auch diesen hier (beide erübrigen sich).

Danke

HP-Fan

noisefloor Team-Icon

Anmeldungsdatum:
6. Juni 2006

Beiträge: 29567

Hallo,

du kannst posten, wo du willst. Genau so wie ich in so vielen Support-Foren aktiv sein kann, wie ich will. Das wir uns dann in zwei von X-tausend verfügbaren Foren auch noch über den Weg laufen ist halt Zufall / Pech für dich / Glück für mich / gut für alle / ... 😉

Immerhin hast du keine Doppelpost, die Supportwillige dann doppelt beschäftigen. Das kann man dir durchaus positiv anrechnen.

...ist aus einem Python Tutorial. Also nicht von mir...

Dann vergiß' am besten, dass es dieses Tutorial gibt, der Code ist stark suboptimal.

Gruß, noisefloor

Antworten |