0

This is the first program I'm writing utilizing Tkinter, so I apologize in advance if my questions are a bit naive.

I have the following:

class Example(Frame):
def __init__(self, master=None):
    Frame.__init__(self,master)

    menubar = Menu(self)
    master.config(menu=menubar)
    self.centerWindow(master)
    self.Top_Bar(menubar,master)
    self.pack(fill = BOTH, expand = 1)

def Top_Bar(self,menubar,master):
    fileMenu = Menu(menubar,tearoff=False)
    menubar.add_cascade(label="File",menu=fileMenu)
    fileMenu.add_command(label="Open",command = self.open_file)
    fileMenu.add_command(label="Exit",command = self.quit)

    fileMenu = Menu(menubar,tearoff=False)
    menubar.add_cascade(label="Edit",menu=fileMenu)

    fileMenu = Menu(menubar,tearoff=False)
    menubar.add_cascade(label="Shortcuts",menu=fileMenu)

    fileMenu = Menu(menubar,tearoff=False)
    menubar.add_command(label="About",command = Message_About)

Notice that I have self.open_file as a command, which is itself a function:

def open_file(self):
    """ A function that opens the file dialog and allows a user to select a single file, displaying it on the page """
    global filename
    filename = []
    filename.append(str(unicodedata.normalize("NFKD",tkFileDialog.askopenfilename(filetypes=[("Astronomical Data","*.fit;*fits")])).encode("ascii","ignore")))

    for i in filename:
        stretch_type = "linear"
        image_manipulation_pyfits.create_png(i,stretch_type)
        x = Image.open("file.png")
        Label(image = x).pack()

I'm certain there's a shorter, more efficient way of writing this function, but that isn't my primary goal at this point -- it's just to get everything to work. My goal is to take this image x and display it in the Tkinter window. It gives me the error

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\python27\lib\lib-tk\Tkinter.py", line 1486, in __call__
    return self.func(*args)
  File "tkinter1.py", line 125, in open_file
    Label(image = x).pack()
  File "C:\python27\lib\lib-tk\ttk.py", line 766, in __init__
    Widget.__init__(self, master, "ttk::label", kw)
  File "C:\python27\lib\lib-tk\ttk.py", line 564, in __init__
    Tkinter.Widget.__init__(self, master, widgetname, kw=kw)
  File "C:\python27\lib\lib-tk\Tkinter.py", line 2055, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
TclError: image specification must contain an odd number of elements

For clarity, the prior function simply takes an input .fits image (selected from the dialog box that pops up) and applies the linear stretch, then saves it as a .png image to the same directory under the name "file.png".

I've Googled for the past day or so and haven't been able to find any threads on this error.

bjd2385
  • 2,013
  • 4
  • 26
  • 47
  • Are you sure the `image` attribute of `Label` accepts arguments of the type returned by `Image.open`? Don't you need a special `PhotoImage` instance or something? – Kevin Jun 25 '15 at 15:34
  • @Kevin You know, I recall seeing something about PhotoImage in my Google searches. Let me try that, it might just work (I thought it didn't handle this type of file, i.e. .png). – bjd2385 Jun 25 '15 at 15:35
  • @Kevin I believe this is relevant: http://stackoverflow.com/questions/27599311/tkinter-photoimage-doesnt-not-support-png-image I will have to output a .gif instead of .png. – bjd2385 Jun 25 '15 at 15:37
  • General advices: 1) always put the complete error message 2) put your code in a single block and indent it (such that a copy-and-paste will work...) – Eric Levieil Jun 25 '15 at 16:43
  • @EricLevieil I have edited accordingly. – bjd2385 Jun 25 '15 at 17:31

2 Answers2

0

One solution I have found:

        x = Image.open("file.gif")
        x = ImageTk.PhotoImage(x)
        label = Label(image = x)
        label.image = x
        label.pack()
  • Save the image as a .gif and open
  • Need to use PhotoImage from ImageTk.
bjd2385
  • 2,013
  • 4
  • 26
  • 47
0

I would comment if I could, but just a note about @bjd2385's answer. In his case, label.image = x saves a reference of the image, however if this line of code is omitted, then you would need to save a reference by using self, if using classes in your design pattern. Instead of im = ImageTk.PhotoImage("...") it would then be self.im = ImageTk.PhotoImage("...") otherwise it can get garbage collected and still display an outline of where the image would be, but not actually have an image present.

Also, you can directly open an image from the PhotoImage call. I'm not sure of the complete limitations of image files possible to be used, but I know you can use .gif and .png. Here's his answer reworked for Python3.4:

    import tkinter

    self.img = ImageTk.PhotoImage(file = "./images/file.png")
    label = Label(image = self.img)
    label.image = self.img # this line can be omitted if using the 'self' method to save a reference
    label.pack()
Cameron Gagnon
  • 1,532
  • 17
  • 18