python, menu, GUI, tkinter

Akarok csinalni egy kis python programot aminek van GUI-ja... vagyis inkabb csak "GUI", mert nagyon egyszeru. Pythonban kezdo vagyok... de nem ez a gond, hanem, hogy GUI-t meg sosem csinaltam, abban abszolut nem vagyok kepben. (GUI alatt Linux dextopon mukodo grafikus interface-t ertek most)

Nagyon egyszeru dologrol lenne szo. Amikor a program elindul, dobjon fel egy menut amibol valasztani lehet. De nem kell igazi window, meg becsuk gomb es egyebek, csak egy popup menu nehany elemmel (mintha csak jobb gombbal kattintanank), ha valaszt valamit akkor a GUI be is csukodhat, a tobbit megoldom (persze azt tudnom kell mire kattintott a user).

Minek olvassak utana? A python GUI-ra keresve hamar a wxwidget-be botlottam ami szimpatikus, de nagyon komplikalt ahhoz kepest ami nekem kell. Van egyszerubb mod, vagy kenytelen leszek a wx-nek rendesen utanaolvasni? Az tetszik a wxwidget-ben, hogy nincs a pythonhoz drotozva, mashol is jol johet meg ha ezt hasznalom. A wx+python+popup+menu kereses meg csupa olyan lehetoseget ad, ahol van window is es azon belul csinalnak egy menut. De nekem a window nem kell!

A teljes megoldast tartalmazo minta kodokat is szivesen latok a jotanacsok mellett. ;)

--------------------------------------------------------------------------------
Update (2013.08.08.)
A szamomra eppen megfelelo tk-ra epulo megoldas Lajatol:


from Tkinter import *

root = Tk()

def hello():
    print "hello!"
    root.destroy()

# create a popup menu
menu = Menu(root, tearoff=0)
menu.add_command(label="Undo", command=hello)
menu.add_command(label="Redo", command=hello)

menu.post(100, 100)

root.withdraw()
root.mainloop()

--------------------------------------------------------------------------------
Update 2 (2013.08.12.)
Akadt meg egy kis bajom. A fenti szuperul mukodik... csakhogy a menuket dinamikusan generalom a hozza tartozo commandoknak meg parametere van, valami ilyesmi (lenne):


for one in list:
  menu.add_command(label=one, command=hello(one)) # WRONG!

Ez igy persze nem megy... kicsit modositva mar legalabb fut, de meg mindig nem jo:


for one in list:
  menu.add_command(label=one, command=lambda:hello(one))

Aki a lambda-t nalam jobban erti, annak bizos leesett, ami nekem csak sok probalkozas utan.... hogy ez igy annyira dinamikus, hogy a "one" csak a hivas pillanataban helyettesitodik be, akkor meg persze a "list" utolso eleme lesz mar az erteke, szoval az osszes menuelem, ugyanazt a hello(legutolso elem a list-bol) hivast hajtja vegre.

Hogy lehetne ezt normalisan lekezelni? Vagy ha az ennyire dinamikus parameter atadas nem megy, akkor a "hello" fuggvenybol hogyan tudnam lekerdezni, hogy melyik menu elemre kattintott a user?

--------------------------------------------------------------------------------
Update 3 (2013.08.12.)
Laja nagyon porog, erre a problemara is szallitotta a megoldast:


for one in myList:
    menu.add_command(label=one, command=lambda one=one: hello(one))

--------------------------------------------------------------------------------
Update 4 (2013.08.21.)
Koszi meg egyszer mindenkinek. Ez lett belole:
hup.hu: blog/traktor: BrowserSelector
Meg van mit rajta mit csiszolni, de az mar foleg nem a GUI lesz. A GUI-val most mar csak annyi bajom van, hogy nem lesz aktiv a menu amikor felugrik (nem kap fokuszt), igy a billentyuzet nem mukodik raja (le, fel, enter, shortcut-ok), de ez mar aprosag es remelem majd megoldom.

Hozzászólások

wxPythont egyébként sem javasolnám - bár nekem mások a szempontjaim. (valami windows-os kompatibilitási gondom volt vele)

http://zetcode.com/gui/tkinter/
Ennél egyszerűbbet nem találsz.

Ha meg komolyabb programot akarsz, akkor PyQt4/PySide

Közel egy éve volt, nem emlékszem. Még az sem kizárt (bár ez elég valószínűtlen), hogy egy másik python GUI-val keverem.

Csak az a biztos, hogy rövid idő után félretettem.
Keresgélek a régi szemeteim között, de nem találom a tényleges okot.

Egy halvány emlék: mintha a menükbe nem tudtam volna ikont tenni a menüpontok mellé és ennek volt valami köze a win7-hez (vagy csak a 64 bites win7-hez)

A Tkinter nagy előnye az is, hogy az alap Python rendszer része, így biztos, hogy ahol Python van ott a Tkinter is elérhető.
Egy másik Tkinter doksi, ez talán kevésbé gyakorlatias, de részletekbe menőbb.
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html
--
Tertilla; Tisztelem a botladozó embert és nem rokonszenvezem a tökéletessel! Hagyd már abba!; DropBox

Én eddig egy szállítólevél készítő programot írtam PyQt/PySide használatával. Megy mind a kettővel, bár minimális kódeltérés van azért. Egy globális változóba töltöm, hogy PyQt-t vagy PySid-ot kell használnia és ahol eltérés van ott figyelem, hogy melyik kód ág fusson.
Egyik esetben sem tapasztaltam különösebb hibát.
--
Tertilla; Tisztelem a botladozó embert és nem rokonszenvezem a tökéletessel! Hagyd már abba!; DropBox

Csak azt mond meg, hogy ezt azert irtad, mert egy kerdesben egymashoz kozel meglattad a GUI es a python szavakat es neked ez ugrott be, vagy azert, mert vegegolvastad a problemat, erted, hogy en nem ertek a GUI-hoz es ehhez az apro GUI feladathoz szerinted a legjobb az lenne, ha megismerkednek a QT-vel, pyQT-vel?

Nem akarlak idegesíteni, de az elsőre linkelt oldalon találsz tutorialt a PyQt4-hez is.
Alapjaiban nem bonyolultabb, mint bármely más GUI, csak sokkal több dolgot tudsz vele megcsinálni, sok elemet készen kapsz hozzá. (cserébe a doksija finoman szólva hiányos, sok esetben van szükség a C-hez gyártott Qt leírásokra)

Ennek mar elkezdtem nekifutni, 2 bajom van:
* remelem, hogy az en egyszeri problemamhoz nem kell az egesz tkinter-t megertenem
* ha megertem az egeszet, akkor sem tudom meg, hogy milyen megoldast valaszthatok/valasszak (bar mar biztos tobb otletem lesz)

Most pl 2 fele megoldast latok, azon keves tudas alapjan amim van a GUI-krol:
* csinalok egy dekoralatlan ablakot, amiben fel lesznek sorolva az elemek
* nem csinalok ablakot (vagy csinalok, de nem jelenik meg, nemtom melyiket lehet/erdemes), csak egy menu lesz lathato.

Na, akkor most kb visszajutottunk oda, ahol az egesz kezdodott, csak en meg wx-ben gondolkodtam akkor inkabb: "A wx+python+popup+menu kereses meg csupa olyan lehetoseget ad, ahol van window is es azon belul csinalnak egy menut. De nekem a window nem kell!"

Szoval eddig mar eddig is eljutottam, akkor wx-szel, azota tkinter-rel. Az a baj, hogy nekem egy olyan alkalmazas kell, ami amikor elindul egyetlen menubol all. Ennyi. Nincs keret, nincs fejlec, tehat nem egy klasszikus ablak. Ehhez kell csinalnom egy ablakot ami menunek nez ki? (nincs dekoracio) vagy egy ablakot menuvel, csak az ablak ne latszodjon? Vagy lehet csak magaban menut kesziteni ablak nelkul?

Hali!

Szerintem mindegy, hogy melyik grafikus toolkitet választod, mert egy ilyen kicsi méretű problémánál nem fogsz beletanulni úgysem az adott toolkit mélységeibe.

Ez egy elég fura dolog, amit meg akarsz valósítani; így aztán trükközni kell. Itt van egy lehetséges megoldás, első tkinter programom :)


from Tkinter import *

root = Tk()

def hello():
    print "hello!"
    root.destroy()

# create a popup menu
menu = Menu(root, tearoff=0)
menu.add_command(label="Undo", command=hello)
menu.add_command(label="Redo", command=hello)

menu.post(100, 100)

root.withdraw()
root.mainloop()

Nem igazán értem ezt a ne legyen ablak problémát.
Ha GUI akkor minimum egy ablak már van. Aztán azon lehet a menü is, meg a "program" is.
Én is mutatok egy példát: Egy ablak menüvel, és van hely rajta bőven annak amit akarsz.


from Tkinter import *
def donothing():
   filewin = Toplevel(root)
   button = Button(filewin, text="Do nothing button")
   button.pack()
   
root = Tk()
menubar = Menu(root)
filemenu = Menu(menubar, tearoff=0)
filemenu.add_command(label="New", command=donothing)
filemenu.add_command(label="Open", command=donothing)
filemenu.add_command(label="Save", command=donothing)
filemenu.add_command(label="Save as...", command=donothing)
filemenu.add_command(label="Close", command=donothing)

filemenu.add_separator()

filemenu.add_command(label="Exit", command=root.quit)
menubar.add_cascade(label="File", menu=filemenu)
editmenu = Menu(menubar, tearoff=0)
editmenu.add_command(label="Undo", command=donothing)

editmenu.add_separator()

editmenu.add_command(label="Cut", command=donothing)
editmenu.add_command(label="Copy", command=donothing)
editmenu.add_command(label="Paste", command=donothing)
editmenu.add_command(label="Delete", command=donothing)
editmenu.add_command(label="Select All", command=donothing)

menubar.add_cascade(label="Edit", menu=editmenu)
helpmenu = Menu(menubar, tearoff=0)
helpmenu.add_command(label="Help Index", command=donothing)
helpmenu.add_command(label="About...", command=donothing)
menubar.add_cascade(label="Help", menu=helpmenu)

root.config(menu=menubar)
root.mainloop()

Igaz itt az egyes menüpontok a példában új ablakot nyitnak de dolgozhatnának az alap formra is.
--
Tertilla; Tisztelem a botladozó embert és nem rokonszenvezem a tökéletessel! Hagyd már abba!; DropBox

Laja ertette es mar be is irta a (szamomra) jo megoldast, nekem tenyleg csak annyi kell.

A "ne legyen ablak" dolgon azert lovagoltam (amellett, hogy tenyleg nem kell ablak :) ), mert nem tudtam, hogy lehet-e ablak nelkuli alkalmazast irni (most mar latom, hogy lehet, es igy utolag: persze, hogy lehet :) ). GUI-s tutorialok mind ugy kezdodnek, hogy "itt egy ablakm nezzuk meg mit lehet bele rakni"...

Igen... meg nem. Szoval igen, _ilyesmit_ de nem pont ilyet. Amig nem tudtam, hogy onmagaban allo menut is lehet csinalni, addig ilyen frame nelkuli ablakkal is beertem volna, de az a helyzet, hogy az en alkalmazasom GUI-ja tenyleg egy menu lesz, amibol valasztani lehet. A tk-ra epulo megoldast Laja megadta kicsit feljebb.

Akkor már említsük meg a PyGtk-t is

sub
--
>'The time has come,' the Walrus said<

"Nagyon egyszeru dologrol lenne szo."

Nem tudom, ez most mennyire lesz hasznos, de ha tényleg annyira egyszerűek az elvárások, nem lehet, hogy neked nem is a Python kell, hanem shell + yad (korábban zenity)?

Én ezekkel, meg némi XML-lel egyszer egy komplett fényképes katalogizálórendszert hoztam össze.

---
Science for fun...