Seite 1 von 1

Bildgröße anpassen und im Frame anzeigen

Verfasst: Freitag 16. Februar 2018, 22:06
von suk
Hallo,

ich habe mir schon diverse Beiträge zum Thema angesehen, jedoch immer noch nicht verstanden, wo mein Problem liegt.

Ich möchte einen Dialog für eine Bildauswahl zur Verfügung stellen. Das ausgewählte Bild soll auf eine bestimmte Größe angepasst und in einem Frame dargestellt werden.
Ich bekomme jedoch das Bild nicht angezeigt?! Es wird immer nur der graue Hintergrund darstellt.
Hinweis: Den Auswahldialog habe ich mal weggelassen und nur versucht, den Code auf die Bildumwandlung und -darstellung zu reduzieren.

Könnt Ihr mal bitte den Fehler erklären und auf ein Lösungsbeispiel anpassen.
Danke.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

### Import der erforderlichen Module ###
try:
# Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
    import tkinter as tk
    
from functools import partial
import tkinter.font as tkf
from PIL import ImageTk, Image

### Fensterdefinition ###
APP_TITLE = "Template"
APP_WIDTH = 600
APP_HEIGHT = 300

### Inhalt Canvas-Applikation ###
class App_Canvas():
    def __init__(self, canvasmaster):
        self.mycanvas = canvasmaster


### Inhalt Frame-Applikation ###
class App_Frame():
    def __init__(self, framemaster):
        self.myframe = framemaster
        self.myframe.pack()
        self.obj_image = Image.open("/home/pi/python_scripts/python-GUI/Images/person1.gif")
        self.obj_image = self.obj_image.resize((200, 200), Image.ANTIALIAS)
        self.myimage = ImageTk.PhotoImage(self.obj_image)
        self.mylabel = tk.Label(self.myframe, image=self.myimage, width=200, height=200, relief="groove")
        self.mylabel.pack()


### Applikationsstart ###
def main():
    win_master = tk.Tk()
    win_master.title(APP_TITLE)
    app_canvas = tk.Canvas(win_master, width=APP_WIDTH, height=APP_HEIGHT, relief="groove", bg="white", bd=5)
#    app_canvas.pack()
    app_frame = tk.Frame(win_master, width=APP_WIDTH, height=APP_HEIGHT, relief="sunken", bg="gray", bd=3)
    app_frame.pack()
    button1 = tk.Button(win_master, text="close", command=win_master.destroy)
    button1.pack()
#    App_Canvas(app_canvas)
    App_Frame(app_frame)
    win_master.mainloop()

if __name__ == '__main__':
    main()

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Samstag 17. Februar 2018, 12:24
von wuf
Hi suk

Kannst du das folgende Skript einmal ausprobieren?:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
### Import der erforderlichen Module ###
try:
# Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
    import tkinter as tk
   
from functools import partial
import tkinter.font as tkf
from PIL import ImageTk, Image
 
### Fensterdefinition ###
APP_TITLE = "Template"
APP_WIDTH = 600
APP_HEIGHT = 300
 
### Inhalt Canvas-Applikation ###
class App_Canvas():
    def __init__(self, canvasmaster):
        self.mycanvas = canvasmaster
 
 
### Inhalt Frame-Applikation ###
class App_Frame():
    def __init__(self, framemaster):
        self.myframe = framemaster
        self.myframe.pack()
        self.obj_image = Image.open("/home/pi/python_scripts/python-GUI/Images/person1.gif")
        #self.obj_image = Image.open("person1.gif")
        self.obj_image = self.obj_image.resize((200, 200), Image.ANTIALIAS)
        self.myimage = ImageTk.PhotoImage(self.obj_image)
        self.mylabel = tk.Label(self.myframe, image=self.myimage, width=200, height=200, relief="groove")
        self.mylabel.pack()
 
 
### Applikationsstart ###
def main():
    win_master = tk.Tk()
    win_master.title(APP_TITLE)
    app_canvas = tk.Canvas(win_master, width=APP_WIDTH, height=APP_HEIGHT, relief="groove", bg="white", bd=5)
#    app_canvas.pack()
    app_frame = tk.Frame(win_master, width=APP_WIDTH, height=APP_HEIGHT, relief="sunken", bg="gray", bd=3)
    app_frame.pack()
    button1 = tk.Button(win_master, text="close", command=win_master.destroy)
    button1.pack()
#    App_Canvas(app_canvas)
    app = App_Frame(app_frame)
    win_master.mainloop()
 
if __name__ == '__main__':
    main()
Gruss wuf :wink:

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Samstag 17. Februar 2018, 12:45
von wuf
Hi suk

Dein Applikationsskript würde ich wie folgt gestalten:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
### Import der erforderlichen Module ###
from functools import partial

try:
# Tkinter for Python 2.xx
    import Tkinter as tk
    import tkFont as tkf
except ImportError:
# Tkinter for Python 3.xx
    import tkinter as tk
    import tkinter.font as tkf
       
from PIL import ImageTk, Image
 
### Fensterdefinition ###
APP_TITLE = "Personal Images"
APP_WIDTH = 600
APP_HEIGHT = 300
 
 
### Inhalt Canvas-Applikation ###
class App_Canvas(tk.Canvas):
    def __init__(self, canvas_master, **kwargs):
        self.canvas_master = canvas_master
        
        tk.Canvas.__init__(self, canvas_master, **kwargs)
 
 
### Inhalt Frame-Applikation ###
class App_Frame(tk.Frame):
    def __init__(self, frame_master, **kwargs):
        self.frame_master = frame_master
        tk.Frame.__init__(self, frame_master, **kwargs)
        
        self.obj_image = Image.open("/home/pi/python_scripts/python-GUI/Images/person1.gif")
        #self.obj_image = Image.open("person1.gif")
        self.obj_image = self.obj_image.resize((200, 200), Image.ANTIALIAS)
        self.myimage = ImageTk.PhotoImage(self.obj_image)
        self.mylabel = tk.Label(self, image=self.myimage, width=200,
            height=200, relief="groove")
        self.mylabel.pack()
 
 
### Applikationsstart ###
def main():
    win_master = tk.Tk()
    win_master.title(APP_TITLE)
    
    app_canvas = App_Canvas(win_master, width=APP_WIDTH, height=APP_HEIGHT,
        relief="groove", bg="white", bd=5)
    app_canvas.pack()
    
    app_frame = App_Frame(win_master, width=APP_WIDTH, height=APP_HEIGHT,
        relief="sunken", bg="gray", bd=3)
    app_frame.pack()
    
    button1 = tk.Button(win_master, text="close", command=win_master.destroy)
    button1.pack()

    win_master.mainloop()
 
if __name__ == '__main__':
    main()
Gruss wuf :wink:

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Samstag 17. Februar 2018, 18:58
von suk
@Wuf: Danke für die Antwort.
Ich habe Deine erste Version übernommen und geht. Jetzt ist die Frage, warum. Entweder bin ich blind oder ich konnte den Unterschied nicht finden. Oder beides ;)
Hilf mir mal bitte auf die Sprünge, wo Dein erstes Script abweicht.

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Samstag 17. Februar 2018, 20:01
von wuf
Hi suk

Du glaubst es nicht aber ich habe einzig die Zeile 50 in deinem Skript:

Code: Alles auswählen

App_Frame(app_frame)
abgeändert auf (in meinem Skript ist es übrigens die Zeile 51:

Code: Alles auswählen

app = App_Frame(app_frame)
Wenn du dich mit Tkinter beschäftigt wirst du mit der Zeit ein Zauberer.

Gruss wuf :wink:

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Samstag 17. Februar 2018, 22:18
von suk
gute Show :o :K :D
Kannst Du mir den "Trick" auch erklären?

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Sonntag 18. Februar 2018, 10:54
von wuf
Hi suk
Kannst Du mir den "Trick" auch erklären?
Kann ich dir leider nicht. Ich möchte mich nicht als Experten bezeichnen. Komme selber eher aus der Sparte der Tüftler. Weicht man von einer gängigen Skriptgestaltung ab offenbaren sich manchmal Dinge die jemand so nicht erwartet. Da brauche ich auch die Hilfe von unseren Forumexperten. Habe dein Skript auf das wesentliche reduziert. So entstanden die drei folgenden Varianten. Die ersten zwei davon funktionieren bei mir nicht.

Variante-1:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
try:
# Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
    import tkinter as tk
 
APP_TITLE = "Template"
APP_WIDTH = 600
APP_HEIGHT = 300
 
 
class App_Frame(object):
    
    def __init__(self, frame):
        self.myimage = tk.PhotoImage(file="person1.gif")
        self.mylabel = tk.Label(frame, image=self.myimage, width=200, bg='red',
            height=200, relief="groove")
        self.mylabel.pack()
 

def main():
    win_master = tk.Tk()
    win_master.title(APP_TITLE)

    app_frame = tk.Frame(win_master)
    app_frame.pack()
    
    App_Frame(app_frame)

    button1 = tk.Button(win_master, text="close", command=win_master.destroy)
    button1.pack()

    win_master.mainloop()
 
if __name__ == '__main__':
    main()
Variante-2:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
try:
# Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
    import tkinter as tk
 
APP_TITLE = "Template"
APP_WIDTH = 600
APP_HEIGHT = 300
 
 
class App_Frame(object):
    
    def __init__(self, master):
        frame = tk.Frame(master)
        frame.pack()

        self.myimage = tk.PhotoImage(file="person1.gif")
        self.mylabel = tk.Label(frame, image=self.myimage, width=200, bg='red',
            height=200, relief="groove")
        self.mylabel.pack()
 

def main():
    win_master = tk.Tk()
    win_master.title(APP_TITLE)
    
    App_Frame(win_master)

    button1 = tk.Button(win_master, text="close", command=win_master.destroy)
    button1.pack()

    win_master.mainloop()
 
if __name__ == '__main__':
    main()
Variante-3:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
try:
# Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
    import tkinter as tk
 
APP_TITLE = "Template"
APP_WIDTH = 600
APP_HEIGHT = 300
 
 
class App_Frame(tk.Frame):
    
    def __init__(self, master):
        
        tk.Frame.__init__(self, master)

        self.myimage = tk.PhotoImage(file="person1.gif")
        self.mylabel = tk.Label(self, image=self.myimage, width=200, bg='red',
            height=200, relief="groove")
        self.mylabel.pack()
 

def main():
    win_master = tk.Tk()
    win_master.title(APP_TITLE)
    
    App_Frame(win_master).pack()

    button1 = tk.Button(win_master, text="close", command=win_master.destroy)
    button1.pack()

    win_master.mainloop()
 
if __name__ == '__main__':
    main()
Kannst du diese drei Varianten auch bei dir ausprobieren. Wie gesagt bei mir läuft nur die Variante-3 korrekt.

Gruss wuf :wink:

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Sonntag 18. Februar 2018, 11:41
von Sirius3
@wuf: Deine Klassen in den ersten beiden Varianten sind eigentlich keine. Eine einfache Funktion hätte den selben Effekt:

Code: Alles auswählen

def App_Frame(frame):
    myimage = tk.PhotoImage(file="person1.gif")
    mylabel = tk.Label(frame, image=myimage, width=200, bg='red',
            height=200, relief="groove")
    mylabel.pack()
Dadurch, dass Du keine Referenz auf die Instanz der Klasse speicherst, wird sie sofort wieder vom Speichermanagement abgeräumt, und damit auch die Referenz auf das Bild.

Im letzten Fall hast Du einen Frame, der durch ›pack‹ eine Referenz in den internen Strukturen behält.

Am einfachsten zu Verstehen ist immer noch, die Imagereferenz direkt im Label zu speichern:

Code: Alles auswählen

def label_with_image(frame, filename):
    image = tk.PhotoImage(file=filename)
    label = tk.Label(frame, image=image, width=200, bg='red',
            height=200, relief="groove")
    label.image = image
    return label

def main():
    win_master = tk.Tk()
    label_with_image(win_master, "person1.gif").pack()
    tk.Button(win_master, text="close", command=win_master.destroy).pack()
    win_master.mainloop()

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Sonntag 18. Februar 2018, 12:08
von wuf
Hi Sirius3

Besten Dank für deine klärenden Worte. Habe mein Variante-2 Skript noch weiter reduziert auf:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
try:
# Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
    import tkinter as tk
 
APP_TITLE = "Template"
APP_WIDTH = 600
APP_HEIGHT = 300
 
 
class App_Frame(object):
    
    def __init__(self, master):

        self.myimage = tk.PhotoImage(file="person1.gif")
        self.mylabel = tk.Label(master, image=self.myimage, width=200, bg='red',
            height=200, relief="groove")
        self.mylabel.pack()
 

def main():
    win_master = tk.Tk()
    win_master.title(APP_TITLE)
    
    App_Frame(win_master)

    button1 = tk.Button(win_master, text="close", command=win_master.destroy)
    button1.pack()

    win_master.mainloop()
 
if __name__ == '__main__':
    main()
Welche immer noch nicht funktioniert. Erst wenn von der Klasse App_Frame eine Instanz app wie folgt erzeugt wird klapp es:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
try:
# Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
    import tkinter as tk
 
APP_TITLE = "Template"
APP_WIDTH = 600
APP_HEIGHT = 300
 
 
class App_Frame(object):
    
    def __init__(self, master):

        self.myimage = tk.PhotoImage(file="person1.gif")
        self.mylabel = tk.Label(master, image=self.myimage, width=200, bg='red',
            height=200, relief="groove")
        self.mylabel.pack()
 

def main():
    win_master = tk.Tk()
    win_master.title(APP_TITLE)
    
    app = App_Frame(win_master)

    button1 = tk.Button(win_master, text="close", command=win_master.destroy)
    button1.pack()

    win_master.mainloop()
 
if __name__ == '__main__':
    main()
Gruss wuf :wink:

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Sonntag 18. Februar 2018, 12:20
von wuf
Ergänzend noch das folgende Skript, welches auch funktioniert:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
try:
# Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
    import tkinter as tk
 
APP_TITLE = "Template"
APP_WIDTH = 600
APP_HEIGHT = 300
 
 
class App_Frame(tk.Tk):
    
    def __init__(self):

        tk.Tk.__init__(self)
        self.title(APP_TITLE)
        
        self.myimage = tk.PhotoImage(file="person1.gif")
        self.mylabel = tk.Label(self, image=self.myimage, width=200, bg='red',
            height=200, relief="groove")
        self.mylabel.pack()

        button1 = tk.Button(self, text="close", command=self.destroy)
        button1.pack()
        
        self.mainloop()
 

App_Frame()
Gruss wuf :wink:

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Sonntag 18. Februar 2018, 12:48
von Sirius3
@wuf: wenn man eine Instanz erzeugt, dann aber nichts damit macht, deutet das immer auf einen Fehler hin, zumindest in der Logik. ›__init__‹ ist zum Initialisieren da und nicht, dass sie unbegrenzt läuft.

Das Programm sollte also zumindest so aussehen:

Code: Alles auswählen

class App_Frame(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.title(APP_TITLE)
       
        self.myimage = tk.PhotoImage(file="person1.gif")
        self.mylabel = tk.Label(self, image=self.myimage, width=200, bg='red',
            height=200, relief="groove")
        self.mylabel.pack()
 
        tk.Button(self, text="close", command=self.destroy).pack()

app = App_Frame()
app.mainloop()

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Sonntag 18. Februar 2018, 13:20
von wuf
Hi Sirius3

OK. Währe das folgende Skript dann besser?:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
try:
# Tkinter for Python 2.xx
    import Tkinter as tk
except ImportError:
# Tkinter for Python 3.xx
    import tkinter as tk
 
APP_TITLE = "Template"
APP_WIDTH = 600
APP_HEIGHT = 300
 
 
class App_Frame(tk.Tk):
    
    def __init__(self):

        tk.Tk.__init__(self)
        self.title(APP_TITLE)
        
        self.build()
        
    def build(self):
        self.myimage = tk.PhotoImage(file="person1.gif")
        self.mylabel = tk.Label(self, image=self.myimage, width=200, bg='red',
            height=200, relief="groove")
        self.mylabel.pack()

        button1 = tk.Button(self, text="close", command=self.destroy)
        button1.pack()
        
        self.mainloop()
 

App_Frame()
Gruss wuf :wink:

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Sonntag 18. Februar 2018, 13:48
von __deets__
Nein, denn du rufst doch einfach nur eine Methode auf, immer noch aus dem __init__.

Das haben wir doch aber neulich schon alles mal durchdekliniert: viewtopic.php?f=18&t=41785&start=30#p319571

Re: Bildgröße anpassen und im Frame anzeigen

Verfasst: Sonntag 18. Februar 2018, 16:11
von wuf
Das haben wir doch aber neulich schon alles mal durchdekliniert: viewtopic.php?f=18&t=41785&start=30#p319571
Danke für deinen Hinweis.