Seite 1 von 2

Konsole in GUI- Fenster

Verfasst: Donnerstag 17. Januar 2008, 15:15
von mathi
Hi,
ich habe ein Konsolen-Programm geschrieben. Um jetzt nach und nach einzelne Teile Buttons grafisch darzustellen brauche ich z.B. TKInter (ist mir klar). Aber für den Anfang würde ich gerne eine " virtuelle Konsole" in einem Hauptfenster haben, und dann nach und nach einige Auswahlfunktionen über Buttons ersetzen, aber den Hauptteil wie: print und raw_input in der "virtuellen" Konsole laufen lassen.

ist so etwas einfach möglich oder sollte ich umdenken?

Verfasst: Donnerstag 17. Januar 2008, 15:27
von schlangenbeschwörer
Hi mathi,
du kannst einfach mit dem os-modul deine Ein- und Ausgaben umleiten.
Bsp:

Code: Alles auswählen

import Tkinter as tk
import sys
class TkConsole:
    def __init__(self):
        self.console= tk.Text(width=80, height=20)
        self.console.pack()
    def write(self, text):
        self.console.insert("end", text)

c = TkConsole()
sys.stdout = c
print "Ich bin ein Testingteststring"
tk.mainloop()
sys.stdout kanns du ein beliebiges Objekt mit einer "write"-Methode übergeben. Ähnlich gehts mit sys.stdin und sys.stderr.

Verfasst: Donnerstag 17. Januar 2008, 15:42
von mathi
vielen Dank, das war im Grunde was ich suche, mit dem kleinen Problem, das ich keine Interaktion habe:

Code: Alles auswählen

# -*- coding: cp1252 -*-
import Tkinter as tk 
import sys 
class TkConsole: 
    def __init__(self): 
        self.console= tk.Text(width=80, height=20) 
        self.console.pack() 
    def write(self, text): 
        self.console.insert("end", text) 
c = TkConsole() 
sys.stdout = c 
print "Ich bin ein Testingteststring" 

p=eval(raw_input("Eingabewert= "))
a=3
b=5
c=a+b
print 'p=%0.2f' % p
print c 
f=open("foo.txt","w") # öffne upatemodus
f.write ("test2")
f.close()
tk.mainloop()
--- ich hoffe ich habe mich verständlich machen können---
ich möchte halt mit raw_input werte empfangen und weiterverarbeiten.

Verfasst: Donnerstag 17. Januar 2008, 21:34
von Leonidas
Unter PyGTK gibt es dafür VTE.

Verfasst: Freitag 18. Januar 2008, 07:32
von mathi
Wie kann ich das unter Windows schaffen ?? :?:

Wichtig ist mir, dass ich dann mit pyinstaller eine .exe erstellen kann, die auch an Fremdrechnern lauffähig ist.

Verfasst: Freitag 18. Januar 2008, 08:42
von Zap
Hi mathi.

Du kannst dir das raw_input sparen wenn du deine Eingabeaufforderung mit eval() interpretierst, da hast du nichts anderes als ein input().

Code: Alles auswählen

C:\>python
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> p=eval(raw_input("Eingabbewert= "))
Eingabbewert= sys.exit(0)

C:\>

Verfasst: Freitag 18. Januar 2008, 08:49
von mathi
@Zap

eval(raw_input()) bedeutet dass ich einen String einlese mit raw_input und diesen dann als Zahl interpretiere (aus Sicherheitsgründen) - so raten es einige hier im Forum und ich finde das plausibel :D

hilft mir das ´bei meinem Problem? Begreife ich leider nicht :oops:

Verfasst: Freitag 18. Januar 2008, 09:10
von Zap
Sorry das ich dir bei deinem eigentlichen Problem nicht helfen kann, da ich weder ausreichen TK erfahrung hab und auch für andere GUI Frameworks gerade keine Lösung parat hab.

Ich wollte dich nur darauf aufmerksam machen das deine Syntax meiner Meinung nach nicht sicherer ist als ein normales input() weil du auch jeden String als code interpretierst.
Guck dir mal meinen Log oben genauer an, dann weißt du was ich meine.

Verfasst: Freitag 18. Januar 2008, 09:35
von mathi
@Zap
Im Grunde hättest Du recht.
Ich habe es bis jetzt so gemacht:

-wenn eine zahl erwartet wird: eval(raw_input())
-wenn ein String erwartet wird: raw_input()
CM hat geschrieben:Nein, natürlich nicht. Aber input() hat so seine Haken:

Code: Alles auswählen

input(...)
    input([prompt]) -> value
    
    Equivalent to eval(raw_input(prompt)).
D. h. für Dich, wenn Du wirklich nichts Anderes machen willst, ist das ok. Aber sonst kannst Du Dir Sicherheitslücken einbauen.

Gruß,
Christian
BlackJack hat geschrieben:Sicherheit ist immer ein Problem wenn man sich erst einmal an `input()` gewöhnt weil's so schön einfach ist, hat man das früher oder später auch in wichtigem Quelltext oder es gelangt per copy'n'paste aus "unwichtigem" Quelltext in ein wichtiges Programm.

Ab Python 3.0 verhält sich `input()` dann auch wie `raw_input()`, da kann man also jetzt schon den sauberen Weg lernen und verwenden.
@all
Aber back to topic:

Hat keiner eine idee: Ich kann leider mit folgender Lösung nur wenig anfangen, obwohl das doch genau das richtige zu sein scheint:
http://www.python-forum.de/topic-7566.h ... tin+thurau

Verfasst: Freitag 18. Januar 2008, 09:57
von BlackJack
Doch noch einmal zum `eval()`: Damit wandelst Du die Zeichenkette nicht in eine Zahl um ─ sie wird als Python-Quelltext angesehen und ausgeführt. Egal welchen Quelltext man da eingibt; also letztlich genau das gleiche was `input()` macht. Zahlen kommen da nur zufällig heraus, wenn die Eingabe auch wirklich eine Zahl war.

Um eine Zeichenkette in eine Zahl um zu wandeln, und auch *nur* das, muss man `int()` oder `float()` anstelle von `eval()` verwenden, je nach dem was für einen Typ man haben möchte.

Verfasst: Freitag 18. Januar 2008, 10:20
von mathi
ok habe ich begriffen und geändert:

Code: Alles auswählen

 p=float(raw_input("Eingabewert= "))

Mein Problem mit der Konsole bleibt aber :cry:

Verfasst: Montag 21. Januar 2008, 07:54
von mathi
keiner eine Idee bzw. Hilfe??

Verfasst: Montag 21. Januar 2008, 09:15
von BlackJack
Das "einfachste" wäre es wahrscheinlich so eine "Konsole" aus einem `Text`-Widget für die Ausgaben und einem `Entry` für die Eingaben zu programmieren, und das über Sockets mit Deinem ``print``/`raw_input()` verwendenden Quelltext so zu verbinden, dass `sys.stdin` und `sys.stdout` mit dieser Konsole verbunden sind.

Das Hauptproblem ist, dass bei ``print``/`rawinput()` Dein Programm die zeitliche Abfolge bestimmt, GUIs aber ereignisbasiert sind, d.h. der Anwender letztendlich bestimmt wann welcher Code ausgeführt wird. Beides zu mischen verträgt sich nicht so besonders gut.

Oder Du ersetzt `raw_input()` durch eine Funktion die jedesmal ein Fenster mit dem Prompt und einem Entry aufmacht. Das ist zwar einfacher, aber für den Benutzer eine ziemlich lästige GUI.

Im Idealfall hast Du beim bisherigen Quelltext Anwendungslogik und UI voneinander getrennt. Dann kannst Du Deine GUI Stück für Stück aufbauen. Es ist zwar dann erst zum Schluss der ganze Funktionsumfang verfügbar, aber es gibt immer eine funktionierende Teilmenge davon.

Verfasst: Montag 21. Januar 2008, 09:19
von nkoehring
mathi hat geschrieben:ok habe ich begriffen und geändert:

Code: Alles auswählen

 p=float(raw_input("Eingabewert= "))
Ich will dir noch nen Tipp dazu in Form eines kleinen Auszugs geben:

Code: Alles auswählen

In [9]: float("bla")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)

D:\Eigene Dateien\devel\<ipython console> in <module>()

ValueError: invalid literal for float(): bla
Du solltest also nicht einfach so umwandeln. Machs lieber ungefaehr so:

Code: Alles auswählen

while True:
    value = raw_input("Eingabewert? ")
    try:
        value = float(value)
        break
    except ValueError:
        print "Na das ist aber keine Zahl!"
Das wirkt jetzt vielleicht alles total umstaendlich gegenueber der eval- oder input-Variante, aber Programmabstuerze aus Faulheit des Programmierers bringen dem User nicht viel Freude ;)


mathi hat geschrieben:Mein Problem mit der Konsole bleibt aber :cry:
Sorry for that :oops:

Verfasst: Montag 21. Januar 2008, 10:23
von mathi
@nkoehring:

hossa, das bringt bei 50 Eingabeabfragen auch 50 while-Schleifen richtig??

hmmm :shock:

@BlackJack:

das hört sich für mich kompliziert an, da ich erst seit 2 Monaten überhaupt programmiere. Ich glaube ich muß das lassen und auf konsole bleiben.

Verfasst: Montag 21. Januar 2008, 10:34
von BlackJack
Wenn die 50 ``while``-Schleifen alle fast gleich aussehen schreibt man natürlich eine Funktion dafür.

Verfasst: Montag 21. Januar 2008, 11:39
von mathi

Code: Alles auswählen

def floatx(value):
    try:
        value = float(value)
        return value
        break
    except ValueError: 
        print "Na das ist aber keine Zahl!"
    

while True: 
    eingabe = raw_input("Eingabewert? ") 
    ausgabe=floatx(eingabe)

print ausgabe

Warum funktioniert das nicht? --> Fehler: break in Loop??

Verfasst: Montag 21. Januar 2008, 11:51
von BlackJack
Das ``break`` steht nicht in einer Schleife. Es würde allerdings sowieso nie ausgeführt, weil das ``return`` in der Zeile darüber den Ablauf der Funktion ja schon abbricht.

Allerdings hättest Du auf diese Weise immer noch 50 ``while``-Schleifen. Die Schleife sollte man mit in die Funktion stecken. Die 50 Aufrufe sollten dann ungefähr so aussehen:

Code: Alles auswählen

wert = float_input('Eingabewert? ')

Verfasst: Montag 21. Januar 2008, 12:05
von mathi
Das verstehe ich nicht.

jeder Eingabewert hat einen anderen Namen und wird durch einen anderen string hinter raw_input beschrieben.
-> (konntest Du nicht wissen)

Deshalb dachte ich an die obige Lösung, wenn aber die Schleife in der Funktion steckt, müßte auch die Eingabe in der Funktion sein, oder?
Also doch 50 Schleifen? :cry:

Verfasst: Montag 21. Januar 2008, 12:10
von BlackJack
Okay, Aufruf der neuen Funktion für zwei verschiedene Werte:

Code: Alles auswählen

radius = float_input('Bitte den Radius eingeben: ')
hoehe = float_input('Und die Hoehe: ')
Zwei Werte die an verschiedene Namen gebunden werden, mit einer eigenen Zeichenkette als Prompt. In der `float_input()` ist weiterhin nur *eine* Schleife.