Hi, i'm working on simple fullscreen launcher application, to use it with remote on my HTPC media center to launch xbmc, stepmania, nes emulator, etc
I'd like to use png icons with transparency, but there is a problem. In alpha channel of loaded icons i can see the back frame's color instead of PNG image loaded as wallpaper. What's wrong and how to solve that problem?

Here's the code i've wrote so far:

try:
    import Tkinter as tk
except ImportError:
    raise ImportError,"The Tcl/Tk is required to run this program."
try:
    from PIL import Image, ImageTk
except ImportError:
    raise ImportError,"Please install image module from http://www.pythonware.com/products/pil/"

class SimpleLauncher(tk.Tk):
    def __init__(self, parent):
        tk.Tk.__init__(self,parent)
        self.parent = parent
        self.width = self.winfo_screenwidth()
        self.height = self.winfo_screenheight()
        self.initialize()

    def initialize(self):
        backgroundFile = "night.png"
        bckImage = Image.open(backgroundFile)
        bckImage = bckImage.resize((self.width, self.height), resample=3)

        background = ImageTk.PhotoImage(bckImage)
        obrazek = ImageTk.PhotoImage(Image.open("ff.png"))

        bckPanel = tk.Label(self, image=background)
        bckPanel.pack(side='top', fill='both', expand='yes')
        bckPanel.image = background

        ikona = tk.Label(bckPanel, image=obrazek)
        ikona.pack()
        ikona.image = obrazek

        bClose = tk.Button(bckPanel, text = u"EXIT", command = self.buttonClicked)
        bClose.pack(pady=10, ipady=10)

        bClose2 = tk.Button(bckPanel, text = u"EXIT2", command = self.buttonClicked)
        bClose2.pack(pady=10, ipady=10)
        
    def buttonClicked(self):
        self.destroy()

def main():
    app = SimpleLauncher(None)
    app.overrideredirect(1)
    w, h = app.winfo_screenwidth(), app.winfo_screenheight()
    app.geometry("%dx%d+0+0" % (w, h))
    app.mainloop()

if __name__ == "__main__":
    main()

Using Python 2.6.4 (r264:75706, Jan 25 2010, 08:55:26) on Arch Linux
PIL 1.17


and unpleasant effect:

Edited 6 Years Ago by neostead: n/a

Attachments zrzut_ekranu1.png 105.53 KB

I made some modifications to code, but i have another problem, how to add dynamic actions for dynamic buttons?
My app adds buttons from config file, for each button should be separate action. But when i try to call performAction method in that way, i got errors:

Traceback (most recent call last):
  File "/home/bagheera/NetBeansProjects/simpleLauncher/src/simplelauncher.py", line 95, in <module>
    main()
  File "/home/bagheera/NetBeansProjects/simpleLauncher/src/simplelauncher.py", line 88, in main
    app = SimpleLauncher(None)
  File "/home/bagheera/NetBeansProjects/simpleLauncher/src/simplelauncher.py", line 32, in __init__
    self.initialize()
  File "/home/bagheera/NetBeansProjects/simpleLauncher/src/simplelauncher.py", line 78, in initialize
    tk.Button(bckPanel, image=item["icon"], command = self.performAction(item["exe"])).pack(side="left", padx = defPadx, in_ = bckPanel)
  File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 2002, in __init__
    Widget.__init__(self, master, 'button', cnf, kw)
  File "/usr/lib/python2.6/lib-tk/Tkinter.py", line 1932, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: can't invoke "button" command:  application has been destroyed

How to pass item["exe"] parameter to performAction method?
Or mb there's other way to perform actions?

here's the modified code:

# To change this template, choose Tools | Templates
# and open the template in the editor.

__author__="bagheera"
__date__ ="$2010-02-06 13:10:47$"

import sys
try:
    import Tkinter as tk
except ImportError:
    raise ImportError,"The Tcl/Tk is required to run this program."
try:
    from PIL import Image, ImageTk
except ImportError:
    raise ImportError,"Please install image module from http://www.pythonware.com/products/pil/"

class SimpleLauncher(tk.Tk):
    def __init__(self, parent):
        tk.Tk.__init__(self,parent)
        #object's vars
        self.parent = parent
        self.width = self.winfo_screenwidth()
        self.height = self.winfo_screenheight()

        #default config vars
        self.backgroudFile = ""
        self.items = []
        self.defIcoWidth = 0

        #init methods
        self.parseConfig()
        self.initialize()

    def parseConfig(self):
        try:
            configFile = open(".slauncher.cfg", 'r')
        except IOError:
            sys.exit("No config file. Please refer to readme and create .slauncher.cfg file")
        else:
            for line in configFile:

                if line.startswith("wallpaper"):
                    self.backgroudFile = line.split("=")[-1].strip()

                #build index of icons and actions
                elif line.startswith("item"):
                    iconFile = line.split("=")[-1].strip().split(":")[0].strip()
                    iconImage = ImageTk.PhotoImage(Image.open(iconFile))
                    if self.defIcoWidth == 0:
                        self.defIcoWidth = iconImage.width()
                    executedCmd = line.split("=")[-1].strip().split(":")[-1].strip()
                    self.items.append({"icon":iconImage, "exe":executedCmd})

    def initialize(self):

        #setting wallpaper
        if self.backgroudFile != "":
            bckImage = Image.open(self.backgroudFile)
            iw, ih = bckImage.size
            if iw != self.width and ih != self.height:
                bckImage = bckImage.resize((self.width, self.height), resample=3)
            background = ImageTk.PhotoImage(bckImage)

            bckPanel = tk.Label(self, image=background)
            bckPanel.pack(side='top', fill='both', expand='yes')
            bckPanel.image = background
        else:
            bckPanel = tk.Label(self)
            bckPanel.pack(side='top', fill='both', expand='yes')

        #define padx for icons
        icoCount = len(self.items)
        defPadx = (self.width - (icoCount * self.defIcoWidth)) / (icoCount *2) -3
        print(defPadx)

        #placing icons horizontally
        for item in self.items:
            tk.Button(bckPanel, image=item["icon"], command = self.performAction(item["exe"])).pack(side="left", padx = defPadx, in_ = bckPanel)
#            ikona.pack()
#            ikona.image = obrazek

        
    def performAction(self, command):
        if command == "quit()":
            self.destroy()

def main():
    app = SimpleLauncher(None)
    app.overrideredirect(1)
    w, h = app.winfo_screenwidth(), app.winfo_screenheight()
    app.geometry("%dx%d+0+0" % (w, h))
    app.mainloop()

if __name__ == "__main__":
    main()

Well, i managed to solve second problem, i used dicts with labels references as keys. I don't know what to do with transparency issue :(

Here's updated code:

#!/usr/bin/env python
#-*- coding: utf-8 -*-
# To change this template, choose Tools | Templates
# and open the template in the editor.

__author__="bagheera"
__date__ ="$2010-02-06 13:10:47$"

import sys
import os
try:
    import Tkinter as tk
except ImportError:
    raise ImportError,"The Tcl/Tk is required to run this program."
try:
    from PIL import Image, ImageTk
except ImportError:
    raise ImportError,"Please install image module from http://www.pythonware.com/products/pil/"

class SimpleLauncher(tk.Tk):
    def __init__(self, parent):
        tk.Tk.__init__(self,parent)
        #object's vars
        self.parent = parent
        self.width = self.winfo_screenwidth()
        self.height = self.winfo_screenheight()

        #default config vars
        self.backgroudFile = ""
        self.items = []
        self.createdItems = {}
        self.createdIconsNormal = {}
        self.createdIconsBig = {}
        self.defIcoWidth = 0
        self.mouse = "on"

        #init methods
        self.parseConfig()
        self.initialize()

    #load and parse config file
    def parseConfig(self):
        try:
            configFile = open(".slauncher.cfg", 'r')
        except IOError:
            sys.exit("No config file. Please refer to readme and create .slauncher.cfg file")
        else:
            for line in configFile:

                if line.startswith("wallpaper"):
                    self.backgroudFile = line.split("=")[-1].strip()

                #build index of icons and actions
                elif line.startswith("item"):
                    iconFile = line.split("=")[-1].strip().split(":")[0].strip()
                    iconImage = Image.open(iconFile)
                    w, h = iconImage.size
                    ws, wh = 30 * w / 100, 30 * h / 100
                    iconImageBig = iconImage.resize((w + ws, h + wh), resample = 3)
                    #convert images to Tk objects
                    iconNormal = ImageTk.PhotoImage(iconImage)
                    iconBig = ImageTk.PhotoImage(iconImageBig)

                    if self.defIcoWidth == 0:
                        self.defIcoWidth = iconNormal.width()
                    executedCmd = line.split("=")[-1].strip().split(":")[-1].strip()
                    self.items.append({"iconNormal":iconNormal, "iconBig":iconBig, "exe":executedCmd})
                elif line.startswith("mouse"):
                    param = line.split("=")[-1].strip()
                    if param == "off":
                        self.mouse = "off"

    #execute command binded to clicked icon
    def executeCmd(self, event):
        command = self.createdItems[event.widget]
        if command == "quit()":
            self.destroy()
        else:
            self.withdraw()
            os.system(command)
            self.deiconify()

    #change image size if mouse pointer is over the icon
    def makeActive(self, event):
        curButton = event.widget
        curButton.configure(image = self.createdIconsBig[curButton])

    def makeUnActive(self, event):
        curButton = event.widget
        curButton.configure(image = self.createdIconsNormal[curButton])

    def initialize(self):
        self.overrideredirect(1)
        self.geometry("%dx%d+0+0" % (self.width, self.height))
        #setting wallpaper
        if self.backgroudFile != "":
            bckImage = Image.open(self.backgroudFile)
            iw, ih = bckImage.size
            if iw != self.width and ih != self.height:
                bckImage = bckImage.resize((self.width, self.height), resample=3)
            background = ImageTk.PhotoImage(bckImage)

            bckPanel = tk.Label(self, image=background)
            bckPanel.pack(side='top', fill='both', expand='yes')
            bckPanel.image = background
        else:
            bckPanel = tk.Label(self)
            bckPanel.pack(side='top', fill='both', expand='yes')

        #define padx for icons
        icoCount = len(self.items)
        defPadx = (self.width - (icoCount * self.defIcoWidth)) / (icoCount *2) -3

        #placing icons horizontally
        #mouse controlled actions
        if self.mouse == "on":
            for item in self.items:
                button = tk.Label(bckPanel, image=item["iconNormal"])
                button.bind("<Button-1>", self.executeCmd)
                button.bind("<Enter>", self.makeActive)
                button.bind("<Leave>", self.makeUnActive)
                button.pack(side="left", padx = defPadx, in_ = bckPanel)
                button.image = item["iconNormal"]
                self.createdItems[button] = item["exe"]
                self.createdIconsNormal[button] = item["iconNormal"]
                self.createdIconsBig[button] = item["iconBig"]


def main():
    root = SimpleLauncher(None)
    root.mainloop()

if __name__ == "__main__":
    main()
This article has been dead for over six months. Start a new discussion instead.