Soy consciente de que esto es una pregunta que se ha hecho antes en este sitio. Sin embargo, he hecho un intento honesto para implementar las soluciones propuestas en esas respuestas , y todavía estoy corriendo en el mismo problema: Python parece mantenga la basura recogida de mi imagen , y me da un espacio vacío en mi ventana donde la imagen debe ser, como se muestra en la captura de pantalla adjunta.
Esta es la parte de mi código donde intento importar una imagen:
def make_top_title(self):
result = Frame(self.top)
text_lbl = Label(result, text="Proserpine",
font=(main_font, title_pt, "bold"))
arms_image = PhotoImage("icon.png")
arms_lbl = Label(result, image=arms_image, height=200)
arms_lbl.image = arms_image
arms_lbl.pack()
text_lbl.pack()
return result
Se dará cuenta de que ya he intentado usar el truco de preservar la imagen fijándola en una propiedad de un objeto etiqueta. Usted puede también tener aviso, desde la captura de pantalla adjunta, que no tengo ningún problema al importar un icono personalizado - utilizando el mismo archivo de imagen - para esta ventana.
Estoy feliz de compartir cualquier código más de este programa, según sea necesario.
Un par de personas han sugerido que comparto un poco más de mi código. Este es el archivo completo en el que el código anterior se encuentra:
### This code holds a class which allows the user to inspect a the coldstore
### object attached to its parent.
# GUI imports.
from tkinter import *
# Custom imports.
from sibstructures import data_storage
from sibstructures.numerals import index_to_label_column, \
index_to_label_row, \
index_to_label_layer
# Imports
import time
from threading import Thread
# Local constants.
main_font = "Arial"
title_pt = 60
subtitle_pt = 30
big_pt = 20
standard_pt = 15
diddy_pt = 10
standard_pad = 10
inner_pad = 5
tile_width = 15
details_height = 10
details_width = 30
grid_border = 5
spot_stack_width = tile_width+5
##############
# MAIN CLASS #
##############
# The class in question.
class CS_Viewer:
def __init__(self, parent):
self.parent = parent
self.parent_window = self.parent.get_top()
self.code = self.parent.coldstore.code
self.parent.coldstore.reconstruct()
self.max_max_layers = self.parent.coldstore.get_max_max_layers()
self.layer = 0
self.top = Frame(self.parent_window)
self.top_title = self.make_top_title()
self.subtitle = Label(self.top, text="code="+self.code,
font=(main_font, subtitle_pt, "bold"))
self.main_container = Frame(self.top)
self.spot_grid = Spot_Grid(self, self.main_container)
self.box_details = Text(self.main_container,
height=details_height, width=details_width,
state=DISABLED)
self.spot_stack = Spot_Stack(self.main_container, None,
self.box_details)
self.add_headings()
self.arrange()
# Ronseal.
def make_top_title(self):
result = Frame(self.top)
text_lbl = Label(result, text="Proserpine",
font=(main_font, title_pt, "bold"))
arms_image = PhotoImage("icon.png")
arms_lbl = Label(result, image=arms_image, height=200)
arms_lbl.image = arms_image
arms_lbl.pack()
text_lbl.pack()
return result
# Add headings to the holster widgets.
def add_headings(self):
spot_grid_label = Label(self.main_container, text="Coldstore",
font=(main_font, big_pt, "bold"))
spot_stack_label = Label(self.main_container, text="Spot",
font=(main_font, big_pt, "bold"),
width=spot_stack_width)
box_details_label = Label(self.main_container, text="Box",
font=(main_font, big_pt, "bold"))
spot_grid_label.grid(column=0, row=0)
spot_stack_label.grid(column=1, row=0)
box_details_label.grid(column=2, row=0)
# Ronseal.
def place_spot_stack(self):
self.spot_stack.get_top().grid(column=1, row=1,
padx=standard_pad, pady=standard_pad)
# Arrange the object's elements.
def arrange(self):
self.top_title.pack()
self.subtitle.pack()
self.spot_grid.get_top().grid(column=0, row=1, sticky=N,
padx=standard_pad, pady=standard_pad,
ipadx=inner_pad, ipady=inner_pad)
self.place_spot_stack()
self.box_details.grid(column=2, row=1, sticky=N,
padx=standard_pad, pady=standard_pad)
self.main_container.pack()
# Replace the spot stack widget.
def replace_spot_stack(self):
self.spot_stack.get_top().grid_forget()
self.place_spot_stack()
# Ronseal.
def get_top(self):
return self.top
################################
# HELPER CLASSES AND FUNCTIONS #
################################
# A class which holds the grid of spots.
class Spot_Grid:
def __init__(self, parent, parent_window):
self.parent = parent
self.parent_window = parent_window
self.top = Frame(self.parent_window, borderwidth=grid_border,
relief="solid")
Thread(target=self.make_grid).start()
# Fill the grid with boxes.
def make_grid(self):
cs = self.parent.parent.coldstore
for i in range(len(cs.columns)):
column_label = Label(self.top, text=str(index_to_label_column(i)),
font=(main_font, big_pt, "bold"))
column_label.grid(column=(i+1), row=0, padx=standard_pad)
for j in range(len(cs.columns[0].spots)):
if i == 0:
row_label = Label(self.top, text=str(index_to_label_row(j)),
font=(main_font, big_pt, "bold"))
row_label.grid(column=0, row=(j+1), padx=standard_pad)
tile = Spot_Tile(self, self.parent, cs.columns[i].spots[j],
self.parent.box_details)
tile.get_top().grid(column=(i+1), row=(j+1))
# Ronseal.
def get_top(self):
return self.top
# A class which holds a clickable representation of a spot.
class Spot_Tile:
def __init__(self, parent, main_ref, spot_obj, box_details_ref):
self.parent = parent
self.main_ref = main_ref
self.spot_obj = spot_obj
self.box_details_ref = box_details_ref
self.parent_window = self.parent.get_top()
self.top = Frame(self.parent_window)
Thread(target=self.make_filling).start()
# Fill the object with either a tile or a label.
def make_filling(self):
if self.spot_obj.max_layers == 0:
filling = Label(self.top, text="VOID", font=(main_font, diddy_pt),
width=tile_width)
elif self.spot_obj.layers() == 0:
filling = Button(self.top, text="free", command=None,
font=(main_font, diddy_pt, "italic"),
width=tile_width, state=DISABLED)
else:
filling = self.make_filling_button()
filling.pack()
# Make the filling object if it is a button.
def make_filling_button(self):
result = Button(self.top, text=self.make_filling_button_text(),
command=self.inspect,
font=(main_font, diddy_pt), width=tile_width)
return result
# Make the text portion of the filling button.
def make_filling_button_text(self):
growers = set()
varieties = set()
fields = set()
for box in self.spot_obj.boxes:
current_epc = box.epc
current_data = data_storage.fetch_most_recent_crop(current_epc)
growers.add(current_data["grower"])
varieties.add(current_data["variety"])
fields.add(current_data["field"])
result = (set_to_string(growers)+"\n"+set_to_string(varieties)+"\n"+
set_to_string(fields)+"\n"+str(len(self.spot_obj.boxes)))
return result
# Inspect a given spot.
def inspect(self):
self.main_ref.spot_stack = Spot_Stack(self.main_ref.main_container,
self.spot_obj,
self.box_details_ref)
self.main_ref.replace_spot_stack()
# Ronseal.
def get_top(self):
return self.top
# A class which holds a representation of the boxes on a given spot.
class Spot_Stack:
def __init__(self, parent_window, spot_obj, box_details_ref):
self.parent_window = parent_window
self.spot_obj = spot_obj
self.box_details_ref = box_details_ref
self.top = Frame(self.parent_window)
if self.spot_obj is None:
self.fill_empty()
else:
Thread(target=self.add_boxes).start()
# "Fill in" the representation if the spot object is empty.
def fill_empty(self):
label = Label(self.top, text="Select spot",
font=(main_font, standard_pt, "italic"), width=tile_width)
label.pack()
# Add representations of the spot's boxes.
def add_boxes(self):
no_of_boxes = len(self.spot_obj.boxes)
if no_of_boxes == 0:
empty_label = Label(self.top, text="Empty spot",
font=(main_font, standard_pt, "italic"),
width=tile_width)
empty_label.pack()
else:
for i in range(no_of_boxes):
backwards_index = (no_of_boxes-1)-i
box_tile = Box_Tile(self.top, self.spot_obj.boxes[backwards_index],
backwards_index, self.box_details_ref)
box_tile.get_top().pack()
# Ronseal.
def get_top(self):
return self.top
# A class which holds a clickable representation of a box.
class Box_Tile:
def __init__(self, parent_window, box, index, box_details_ref):
self.parent_window = parent_window
self.box = box
self.index = index
self.box_details_ref = box_details_ref
self.top = Frame(self.parent_window)
self.make_filling()
# Fill the object with either a tile or a label.
def make_filling(self):
label = Label(self.top, text=str(index_to_label_layer(self.index)),
font=(main_font, standard_pt))
filling = Button(self.top, text=self.box.epc, command=self.inspect,
font=(main_font, standard_pt), width=tile_width)
label.grid(column=0, row=0, padx=standard_pad)
filling.grid(column=1, row=0)
# Ronseal.
def get_top(self):
return self.top
# Inspect the data for this particular box in more detail.
def inspect(self):
text_to_insert = data_storage.fetch_most_recent_crop(self.box.epc)
self.box_details_ref.config(state=NORMAL)
self.box_details_ref.delete("1.0", END)
self.box_details_ref.insert(END, text_to_insert)
self.box_details_ref.config(state=DISABLED)
# Turns a set into a string, with items thereof separated by commas.
def set_to_string(the_set):
result = ""
the_list = list(the_set)
# Reversal is necessary, since .add() seems to add items to the FRONT of
# the set.
the_list.reverse()
for item in the_list:
if the_list.index(item) == 0:
result = item
else:
result = result+", "+item
return result
Este es el otro archivo, que, con su compañero, lo compensa todo el programa:
### This code holds a class which manages transitions between windows, and
### also oversees their interactions with the Coldstore object.
# Imports.
from pathlib import Path
# GUI imports.
from tkinter import *
# Custom imports.
from sibstructures.coldstore import Coldstore
# Local imports.
from cs_viewer import CS_Viewer
# Constants.
path_to_db = str(Path.home())+"/cseye/source/proserpine/data.db"
##############
# MAIN CLASS #
##############
# The class in question.
class Comptroller:
def __init__(self):
self.coldstore = Coldstore(proserpine_mode=True,
proserpine_path=path_to_db)
self.gui = Tk()
self.top = Frame(self.gui)
self.window = CS_Viewer(self)
self.arrange()
# Return the top-level GUI object.
def get_top(self):
return self.top
# Arrange the widgets.
def arrange(self):
self.window.get_top().pack()
self.top.pack()
# Run the "mainloop" method on the GUI object.
def run_me(self):
self.gui.title("Proserpine")
self.gui.iconphoto(True, PhotoImage(file="icon.png"))
self.gui.mainloop()
###################
# RUN AND WRAP UP #
###################
def run():
comptroller = Comptroller()
comptroller.run_me()
if __name__ == "__main__":
run()
El argumento de PhotoImage("...")
que está mal. Debería ser PhotoImage(file="...")
.