2

OS: Windows 10

Python 3.8

I am trying to display PNG images with transparency with no titlebar, or any other indication of window info (imagine sticking a sticker on your screen). I've already done this once in another language by putting an image in a window and removing all the elements of the window, including titlebar and background, but I cannot achieve it in python.

I have already tried Tkinter, but seems like it's not designed to work with PNG transparency and it cannot have separate transparency for parent and child windows.

Now I am trying wxPython. My idea is that it might be possible to make the parent window transparent and the child window (which holds the image) opaque, but cannot figure out if that's even possible.

Here is the simplified version of my attempt:

app = wx.App()

path = 'Images/02.png'

bitmap = wx.Bitmap(path, wx.BITMAP_TYPE_PNG)  # Create bitmap

frame = wx.Frame(None,-1,'Transparent Window',size=(1000,1000)) # Create frame (top level window)
frame.SetTransparent(100)                 # Change transparency of the frame 
panel = wx.Panel(frame, -1)               # Create panel (to hold the image)
wx.StaticBitmap(panel, -1, bitmap)        # Put the image in the panel
panel.SetTransparent(255)                 # Change transparency of the panel (the image)

frame.Show()
app.MainLoop()

But unfortunately ".SetTransparent()" only works on top level window, so I can't set the transparency of the panel to anything else.

But basically, the question is, is it possible to display image with transparency on its own with Python? I am not looking for any specific method of achieving this, the one I provided was just the only one I know. So please help me if you can :)

Edit 1: Tried to use wx.lib.agw.advancedsplash:

import wx
import wx.lib.agw.advancedsplash as AS

app = wx.App()

frame = wx.Frame(None, -1, "AdvancedSplash Test")

imagePath = "Images/05.png"
bitmap = wx.Bitmap(imagePath)

splash = AS.AdvancedSplash(frame, bitmap=bitmap)

app.MainLoop()

But it still fills in transparent areas

3 Answers3

0

You may want to look into the implementation of AdvancedSplash in wx.lib.agw.advancedsplash. It’s sort of a splash screen that adapts itself to the picture you use, and if you have transparencies they will be taken into account.

Infinity77
  • 1,317
  • 10
  • 17
  • Thank you for the idea I checked out the documentation for wx.lib.agw.advancedsplash. It clearly says that it will only draw take transparency of the bitmap into account. But it still doesn't work. Here is the simplest code: `import wx import wx.lib.agw.advancedsplash as AS app = wx.App() frame = wx.Frame(None, -1, "AdvancedSplash Test") imagePath = "test.png" bitmap = wx.Bitmap(imagePath) splash = AS.AdvancedSplash(frame, bitmap=bitmap) app.MainLoop()` But the splash still draws the transparent area: https://imgur.com/bzAFSJs I wonder if I am missing something – Yamiko Hikari Apr 12 '21 at 21:28
0

Transparency is be applied to the frame, so don't worry about the panel, the whole thing becomes transparent.

enter image description here

Be careful how you run this code, as it needs to be killed or Ctrl-C'd.

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, pos=(200,200), style=wx.FRAME_NO_TASKBAR)
        panel1 = wx.Panel(self)
        bitmap = wx.Bitmap('ace2.png', wx.BITMAP_TYPE_PNG)
        image = wx.StaticBitmap(panel1, -1, bitmap)
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(panel1)
        self.SetSizerAndFit(sizer)
        self.Show()
        self.OnTransparent(None)

    def OnTransparent(self, event):        
        self.SetTransparent(180)
        self.Update()
        
app = wx.App()
frame = MyFrame(None, -1)
app.MainLoop()
Rolf of Saxony
  • 21,661
  • 5
  • 39
  • 60
  • I think I might have accidentally described my intentions not clearly enough, sorry. PNG format has alpha channel, which denotes transparent areas in the image. I want that transparency (of the pixels in the image) to be taken into account when the image is displayed on the screen. Setting the transparency of the whole image is something I am actually trying to avoid :) Despite that your example is quite helpful, since it taught me to use styles to remove the titlebar, and BoxSizer also looks interesting, so thank you :) – Yamiko Hikari Apr 12 '21 at 21:41
0

Try something like this:

import tkinter as tk


root = tk.Tk()
root.overrideredirect(True)
root.config(bg="blue", bd=0, highlightthickness=0)
root.attributes("-transparentcolor", "blue")

canvas = tk.Canvas(root, bg="blue", bd=0, highlightthickness=0)
canvas.pack()

tk_img = tk.PhotoImage(file="cards.png")
canvas.create_image(0, 0, image=tk_img, anchor="nw")

root.mainloop()

It creates an image on the screen like this:

enter image description here

It changes the transparent colour of the window to "blue" (because there isn't any thing blue in the picture that I am using) and sets the background colour to "blue". That makes the window transparent. To show the image I used a tk.Canvas but it might work with tk.Label (haven't tested it).

Please note that this will most likely work only on Windows.

TheLizzard
  • 7,248
  • 2
  • 11
  • 31