Game Of Life - Embedding the pygame window in tkinter to add buttons [duplicate] - user-interface

This question already has answers here:
Embedding a Pygame window into a Tkinter or WxPython frame
(3 answers)
Closed last year.
So I'm making a game in pygame, and I want to use tkinter as well. I embedded a pygame window into a tkinter window, but I can't seem to do anything with it.
For context, here is the full code:
import Tkinter as tk
import os
import platform
import pygame
class window(object):
def __init__(self):
self.root = tk.Tk() # Main window
self.root.title("SquareScape")
self.root.iconbitmap(r'C:\Users\17_es\PycharmProjects\square_puzzle\images\icon.ico')
self.root.configure(background='#9b9b9b')
# Large Frame
self.win_frame = tk.Frame(self.root, width=670, height=520, highlightbackground='#595959', highlightthickness=2)
# menu (left side)
self.menu = tk.Frame(self.win_frame, width=150, height=516, highlightbackground='#595959', highlightthickness=2)
self.menu_label = tk.Label(self.menu, text="Settings", bg='#8a8a8a', font=("Courier", "16", "bold roman"))
self.mute = tk.Button(self.menu, text="XXXX", font="Courier", bg='#bcbcbc', activebackground='#cdcdcd')
# pygame
self.pygame_frame = tk.Frame(self.win_frame, width=514, height=514, highlightbackground='#595959', highlightthickness=2)
self.embed = tk.Frame(self.pygame_frame, width=512, height=512,)
# Packing
self.win_frame.pack(expand=True)
self.win_frame.pack_propagate(0)
self.menu.pack(side="left")
self.menu.pack_propagate(0)
self.menu_label.pack(ipadx=60, ipady=2)
self.mute.pack(ipadx=40, ipady=2, pady=5)
self.pygame_frame.pack(side="left")
self.embed.pack()
#This embeds the pygame window
os.environ['SDL_WINDOWID'] = str(self.embed.winfo_id())
if platform.system == "Windows":
os.environ['SDL_VIDEODRIVER'] = 'windib'
#Start pygame
pygame.init()
self.win = pygame.display.set_mode((512, 512))
self.win.fill(pygame.Color(255, 255, 255))
pygame.display.init()
self.root.mainloop()
screen = window()
#Here is sample code that I want to run
pygame.draw.rect(screen.win, (0, 0, 255), (200, 200, 100, 100))
When I use pygame.draw.rect(screen.win, (0, 0, 255), (200, 200, 100, 100)), nothing happens. Using pygame inside the class worked, but in my more complicated game, using self.variable for all my variables seems unnecessary.
How can I run my code in the pygame window outside of the window class?

So - besides the obvious missing call to pygame.display.flip - which I suppose is what you intended with the call to pygame.display.init (pygame.init already calls that one) - what I found out is that tkinter needs to initialize its windows and widgets before the packed frame is fully available to be used by Pygame.
I did that by adding a call to self.root.update_idletasks() before calling pygame.init -- that, and explicitly setting the video driver for my platform (which you already does for Windows), made things work.
Anyway, also, in your code you did not show were you wanted to make the calls to Pygamedrawing functions - as it is, it is well possible that everything is correct, but the code after screen.window() is just never run (or rather, just run at program exit) - because you call tkinter.mainloop inside the __init__ method of your application class.
Moving the call to mainloop outside the __init__ is a good practice, so you can initialize other objects and resources as well - and you actualy do have the screen object to operate things on. By making that call inside __init__ is like your whole program was running "inside the initialization".
In short:
call tkinter.update_iddletasks() before initializing pygame
remember to call pygame.display.flip after you draw anything with Pygame
arrange your code so that your drawing calls are actually executed, and not blocked after the call to enter tkinter's loop
You should seriously consider using Python 3.7 or later - (the only "python 2" code there is import Tkinter which becomes import tkinter in Python 3). Python 2 is really at the end of line, and there are no updates for projects like pygame on it.
.
That said, here is your code, modified to run on Linux + Python 3 (should still work on Windows), and to actually perform some actions using the embedded pygame frame.
import tkinter as tk
import os
import platform
import pygame
import time
class window(object):
def __init__(self):
self.root = tk.Tk() # Main window
self.root.title("SquareScape")
# self.root.iconbitmap(r'C:\Users\17_es\PycharmProjects\square_puzzle\images\icon.ico')
self.root.configure(background='#9b9b9b')
# Large Frame
self.win_frame = tk.Frame(self.root, width=670, height=520, highlightbackground='#595959', highlightthickness=2)
# menu (left side)
self.menu = tk.Frame(self.win_frame, width=150, height=516, highlightbackground='#595959', highlightthickness=2)
self.menu_label = tk.Label(self.menu, text="Settings", bg='#8a8a8a', font=("Courier", "16", "bold roman"))
self.mute = tk.Button(self.menu, text="XXXX", font="Courier", bg='#bcbcbc', activebackground='#cdcdcd')
tk.Button(self.menu, text="<->", command=lambda: setattr(self, "direction", (-self.direction[0], self.direction[1]))).pack()
tk.Button(self.menu, text="^", command=lambda: setattr(self, "direction", (self.direction[0], -self.direction[1]))).pack()
# pygame
self.pygame_frame = tk.Frame(self.win_frame, width=514, height=514, highlightbackground='#595959', highlightthickness=2)
self.embed = tk.Frame(self.pygame_frame, width=512, height=512,)
# Packing
self.win_frame.pack(expand=True)
self.win_frame.pack_propagate(0)
self.menu.pack(side="left")
self.menu.pack_propagate(0)
self.menu_label.pack(ipadx=60, ipady=2)
self.mute.pack(ipadx=40, ipady=2, pady=5)
self.pygame_frame.pack(side="left")
self.embed.pack()
#This embeds the pygame window
os.environ['SDL_WINDOWID'] = str(self.embed.winfo_id())
system = platform.system()
if system == "Windows":
os.environ['SDL_VIDEODRIVER'] = 'windib'
elif system == "Linux":
os.environ['SDL_VIDEODRIVER'] = 'x11'
self.root.update_idletasks()
#Start pygame
pygame.init()
self.win = pygame.display.set_mode((512, 512))
self.bg_color = (255, 255, 255)
self.win.fill(self.bg_color)
self.pos = 0, 0
self.direction = 10, 10
self.size = 40
self.color = (0, 255, 0)
self.root.after(30, self.update)
self.root.mainloop()
def update(self):
first_move = True
pygame.draw.rect(self.win, self.bg_color, self.pos + (self.size, self.size))
self.pos = self.pos[0] + self.direction[0], self.pos[1] + self.direction[1]
if self.pos[0] < 0 or self.pos[0] > 512 - self.size:
self.direction = -self.direction[0], self.direction[1]
self.pos = self.pos[0] + 2 * self.direction[0], self.pos[1] + self.direction[1]
if self.pos[1] < 0 or self.pos[1] > 512 - self.size:
self.direction = self.direction[0], -self.direction[1]
self.pos = self.pos[0] + self.direction[0], self.pos[1] + 2 * self.direction[1]
pygame.draw.rect(self.win, self.color, self.pos + (self.size, self.size))
pygame.display.flip()
self.root.after(30, self.update)
screen = window()
tk.mainloop()

Related

pygame does not access sprite functions after putting the dot "."

I am following a tutorial for a game of ships, and when creating the Player class in the init function I have a strange problem when wanting to access the functions of the Sprite module: when I write the name of the variable and put the point to access its functions remain in white, instead of being colored yellow indicating that it is a reserved word (I am using visual studio)
(Sorry if I do not express myself correctly I am using google translator.)
so the strange is this:
code screenshot
what is indicated in the red boxes should be in yellow (like what I underlined in yellow), since theoretically it would be accessing the functions of a Sprite object therefore it should be highlighted in yellow ...
the problem is that it appears white, as if it did not recognize the variable as a Sprite object
Here is where i create the image directory.
import pygame, random, os, sys
from os import path
img_dir = path.join(path.dirname(__file__), 'img')
And here is the Meteor class:
class Meteor(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image_orig = random.choice(meteor_images)
self.image_orig.set_colorkey("black")
self.image_orig.set_clip()
self.image = self.image_orig.copy()
self.rect = self.image.get_rect()
self.radius = int(self.rect.width*0.85/2) # *0.85 <- se leeria como (el 85% del width) / 2
pygame.draw.circle(self.image, "red", self.rect.center, self.radius)
self.rect.x = random.randrange(0, width)
self.rect.bottom = random.randrange(-100, -50)
self.speedx = random.randrange(-4, 4)
self.speedy = random.randrange(2, 8)
self.rot = 0
self.rot_speed = random.randrange(-8, 8)
self.last_update = pygame.time.get_ticks()
and then here is where create the meteors list:
meteor_images = []
meteor_list = ['meteorBrown_big1.png',
'meteorBrown_big2.png',
'meteorBrown_big3.png',
'meteorBrown_big4.png']
for img in meteor_list:
meteor_images.append(pygame.image.load(path.join(img_dir, img)).convert())
I am not very expert on the subject, what could be the problem??

Images Flickering on Pygame [duplicate]

This question already has an answer here:
Why is the PyGame animation is flickering
(1 answer)
Closed 2 years ago.
I am trying to add some buttons to my program and I have managed to put them on there. However, they keep flickering and I'm not sure how to stop that problem. The sizes and positioning are going to be changed later I just used random positions for now so ignore that. I put pygame.display.flip() everywhere hoping that would fix it. However, it did not. Thank you
import pygame
import pygame.freetype
from pygame.sprite import Sprite
from pygame.rect import Rect
PINK = (250, 100, 100)
WHITE = (255, 255, 255)
BLACK = (0,0,0)
#initialize pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
#images
loginBut = pygame.image.load('loginBut.png').convert_alpha()
signupBut = pygame.image.load('signupBut.png').convert_alpha()
pygame.display.flip()
#variables
xbut = 300
ybut1 = 350
ybut2 = 450
def create_surface_with_text(text, font_size, text_rgb, bg_rgb):
font = pygame.freetype.SysFont("Arial", font_size, bold=True)
surface, _ = font.render(text=text, fgcolor=text_rgb, bgcolor=bg_rgb)
return surface.convert_alpha()
def loginButton(xbut,ybut1):
screen.blit(loginBut,(xbut,ybut1))
pygame.display.update()
def signupButton(xbut,ybut2):
screen.blit(signupBut,(xbut,ybut2))
pygame.display.update()
pygame.display.flip()
class UIElement(Sprite):
def __init__(self, center_position, text, font_size, bg_rgb, text_rgb):
self.mouse_over = False
# what happens when the mouse is not over the element
default_image = create_surface_with_text(
text=text, font_size=font_size, text_rgb=text_rgb, bg_rgb=bg_rgb
)
# what happens when the mouse is over the element
highlighted_image = create_surface_with_text(
text=text, font_size=font_size * 1.1, text_rgb=text_rgb, bg_rgb=bg_rgb
)
self.images = [default_image, highlighted_image]
self.rects = [
default_image.get_rect(center=center_position),
highlighted_image.get_rect(center=center_position),
]
super().__init__()
#property
def image(self):
return self.images[1] if self.mouse_over else self.images[0]
#property
def rect(self):
return self.rects[1] if self.mouse_over else self.rects[0]
def update(self, mouse_pos):
if self.rect.collidepoint(mouse_pos):
self.mouse_over = True
else:
self.mouse_over = False
def draw(self, surface):
surface.blit(self.image, self.rect)
pygame.display.flip()
def main():
pygame.init()
screen = pygame.display.set_mode((800, 600))
uielement = UIElement(
center_position=(400, 100),
font_size=40,
bg_rgb=PINK,
text_rgb=BLACK,
text="Welcome to the Automated Timetable Program",
)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill(PINK)
uielement.update(pygame.mouse.get_pos())
uielement.draw(screen)
pygame.display.flip()
loginButton(xbut,ybut1)
signupButton(xbut,ybut2)
pygame.display.flip()
if __name__ == "__main__":
main()
The issue is caused by the multiple calles of pygame.display.flip(). Multiple calls to pygame.display.update() or pygame.display.flip() cause flickering. Remove all the calls of pygame.display.flip() from the code, but call it once at the end of the application loop.

PIL problem, but only when called from within another object( Image doesn't exist)

I am trying to develop a python app for a RaspberryPi on a PC. In order to test one aspect, I have written an object class to emulate an OLED display device (hardware) that the PC cannot use (no I2C). The Wdisp class is simply loaded in place of the hardware driver when using the PC.
I have another class that wraps up the few OLED functions I need ( write text , draw progressbar etc. )
# OLED display object
import os
Win = False
if os.name == 'nt':
Win=True
from WindowsOLED import Wdisp
else:
import Adafruit_GPIO.SPI as SPI
import Adafruit_SSD1306
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
class OLEDDisplay(object):
def __init__(self):
# Raspberry Pi pin configuration:
RST = 24
if Win:
self.disp = Wdisp()
else:
self.disp = Adafruit_SSD1306.SSD1306_128_64(rst=RST)
# Initialize library.
self.disp.begin()
# Create blank image for drawing.
self.width = 128 #self.disp.width
self.height = 64 #self.disp.height
self._image = Image.new('1', (self.width, self.height))
self.draw = ImageDraw.Draw(self._image)
# Load default font.
self.font = ImageFont.load_default()
self.clear()
def __del__(self):
self.clear()
def __repr__(self):
return 'OLED display object for SSD1306 I2C'
def clear(self):
# Clear display
self.disp.clear()
self.disp.display()
def write(self, text):
self.draw.text((0, 2), text, font=self.font, fill=255)
self._show()
def progressbar(self, percent):
#draw a progress bar on top half of screen
shape_width = self.width * (percent/100)
padding =2
top = padding
bottom = (self.height/2) - padding
x = padding
self.draw.rectangle((x, top, self.width-padding, bottom), outline=255, fill=0)
self.draw.rectangle((x, top, x+shape_width, bottom), outline=255, fill=255)
self._show()
def loadimage(self, imagefile):
#open, convert and display an image
self._image = Image.open(imagefile).resize((self.disp.width,
self.disp.height),
Image.ANTIALIAS).convert('1')
self._show()
def _show(self):
# Display image.
self.disp.image(self._image)
self.disp.display()
If I test this class at the command line
Example:
>>> from OLEDDisplay import*
>>> OD = OLEDDisplay()
>>> OD.progressbar(50)
Its works fine - the OLEDDisplay object draws on a PIL image object, passes the image to the Wdisp object and the Wdisp object converts the image to a BitMapImage and displays in on a Tkinter Label ( self.L ).
#Windows subsitute OLED display class
#displays a label image for testing
from tkinter import *
from PIL import Image, ImageTk
from tkinter import filedialog, messagebox
from tkinter.constants import *
class Wdisp(object):
i=None
width = 128
height =64
_image = None
def __init__(self):
self.master = Tk()
self._image = Image.new('1', (self.width, self.height))
self.i = ImageTk.PhotoImage(self._image)
self.L= Label(self.master, text="label place holder", image=self.i)
self.L.pack(expand=YES, fill=BOTH)
def begin(self):
pass
def image(self, newimage):
self._image = newimage
def display(self):
#display the image
self.i = ImageTk.BitmapImage(self._image)
self.L.config(image=self.i)
However, if I use this in my app or test it in a small app:
from tkinter import *
from PIL import Image, ImageTk
from tkinter import filedialog, messagebox
from tkinter.constants import *
from OLEDDisplay import*
def updateOLED():
text = E.get
print(text)
OD.write(text)
master = Tk()
OD = OLEDDisplay()
E = Entry(master)
B = Button(master, text="update OLED", command = updateOLED)
E.pack()
B.pack()
It fails with a tkinter.TclError: image "pyimage4" doesn't exist:
Traceback (most recent call last):
File "D:\My Documents\PI Projects\Pyprojects\PTPIC\OLEDDisplay test.py", line 19, in <module>
OD = OLEDDisplay()
File "D:\My Documents\PI Projects\Pyprojects\PTPIC\OLEDDisplay.py", line 42, in __init__
self.clear()
File "D:\My Documents\PI Projects\Pyprojects\PTPIC\OLEDDisplay.py", line 52, in clear
self.disp.clear()
File "D:\My Documents\PI Projects\Pyprojects\PTPIC\WindowsOLED.py", line 45, in clear
self.display()
File "D:\My Documents\PI Projects\Pyprojects\PTPIC\WindowsOLED.py", line 36, in display
self.L.config(image=self.i)
File "C:\Python34\lib\tkinter\__init__.py", line 1324, in configure
return self._configure('configure', cnf, kw)
File "C:\Python34\lib\tkinter\__init__.py", line 1315, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: image "pyimage4" doesn't exist
I have no idea why : perhaps variable scope? perhaps something weird with PIL , so any suggestions welcome.
Cheers Bill

Matplotlib embedded in wxPython: TextCtrl in Navigation toolbar not working on macos

I'm doing a simple embedded graph with Matplotlib APIs (2.2.2) in wxPython (Phoenix 4.0.1) and Python 3.6.4. I have subclassed the WXAgg Navigation toolbar so I can remove the "configure subplots" tool and this is working fine.
In addition, I have added a read-only TextCtrl into my subclassed toolbar to show mouse coordinates (just like it appears in the pyplot state-based version of matplotlib). I've implemented a simple handler for the mouse move events per the Matplotlib docs and this is all working fine on Windows 10.
However, this code does not fully work on macOS (10.13.4 High Sierra). The graph displays just fine, the toolbar displays fine, the toolbar buttons work fine, but I don't get any display of my TextCtrl with the mouse coordinates in the toolbar (or even the initial value as set when I create the TextCtrl).
Can anyone shed light on why the TextCtrl in the Matplotlib toolbar doesn't work on the mac? Is there a way to do this on the mac? And if this is simply not possible, what are my alternatives for showing the mouse coordinates elsewhere in my Matplotlib canvas?
Here's my sample code:
import wx
from matplotlib.figure import Figure
from matplotlib import gridspec
import numpy as np
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx as NavigationToolbar
class MyToolbar(NavigationToolbar):
def __init__(self, plotCanvas):
# create the default toolbar
NavigationToolbar.__init__(self, plotCanvas)
# Add a control to display mouse coordinates
self.info = wx.TextCtrl(self, -1, value = 'Coordinates', size = (100,-1),
style = wx.TE_READONLY | wx.BORDER_NONE)
self.AddStretchableSpace()
self.AddControl(self.info)
# Remove configure subplots
SubplotsPosition = 6
self.DeleteToolByPos(SubplotsPosition)
self.Realize()
class Graph(wx.Frame):
def __init__(self, parent, title='Coordinates Test'):
super().__init__(parent, title=title)
self.SetSize((900, 500))
# A simple embedded matplotlib graph
self.fig = Figure(figsize = (8.2,4.2), facecolor = 'gainsboro')
self.canvas = FigureCanvas(self, -1, self.fig)
gs = gridspec.GridSpec(2, 1, left = .12, right = .9, bottom = 0.05, top = .9, height_ratios = [10, 1], hspace = 0.35)
ax = self.fig.add_subplot(gs[0])
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
ax.plot(t, s)
ax.set(xlabel='time (s)', ylabel='voltage (mV)',
title='About as simple as it gets, folks')
ax.grid()
ax.set_navigate(True)
# Get a toolbar instance
self.toolbar = MyToolbar(self.canvas)
self.toolbar.Realize()
# Connect to matplotlib for mouse movement events
self.canvas.mpl_connect('motion_notify_event', self.onMotion)
self.toolbar.update()
# Layout the frame
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.EXPAND)
self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
self.SetSizer(self.sizer)
def onMotion(self, event):
if event.inaxes:
xdata = event.xdata
ydata = event.ydata
self.toolbar.info.ChangeValue(f'x = {xdata:.1f}, y = {ydata:.1f}')
else:
self.toolbar.info.ChangeValue('')
class MyFrame(wx.Frame):
def __init__(self, parent, title=""):
super().__init__(parent, title=title)
self.SetSize((800, 480))
self.graph = Graph(self)
self.graph.Show()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, title='Main Frame')
self.frame.Show()
return True
if __name__ == "__main__":
app = MyApp(False)
app.MainLoop()
I realize this is late, but I think that the simplest solution is to not subclass NavigationToolbar at all, but just to add a TextCtrl of your own.
That is, getting rid of your MyToolbar altogether and modifying your code to be
# Get a toolbar instance
self.toolbar = NavigationToolbar(self.canvas)
self.info = wx.TextCtrl(self, -1, value = 'Coordinates', size = (100,-1),
style = wx.TE_READONLY | wx.BORDER_NONE)
self.canvas.mpl_connect('motion_notify_event', self.onMotion)
self.toolbar.update()
# Layout the frame
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.EXPAND)
bottom_sizer = wx.BoxSizer(wx.HORIZONTAL)
bottom_sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
bottom_sizer.Add(self.info, 1, wx.LEFT | wx.EXPAND)
self.sizer.Add(bottom_sizer, 0, wx.LEFT | wx.EXPAND)
self.SetSizer(self.sizer)
def onMotion(self, event):
if event.inaxes is not None:
xdata = event.xdata
ydata = event.ydata
self.info.ChangeValue(f'x = {xdata:.1f}, y = {ydata:.1f}')
else:
self.info.ChangeValue('')
will give TextCtrl that does display the motion events.

PyGTK Transparent Window

I want the window transparent, but the label to be 100% in opacity. How can I achieve this? BTW: I noticed when I upgraded to Ubuntu 12.04's unity interface that window.set_opacity wasn't working like it did on GNOME, but even if it did all the content inside the window would become transparent as well.
This is the code I started out with...
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
import pango
import time
class Clock:
def __init__(self):
me = gtk.Window(gtk.WINDOW_TOPLEVEL)
me.connect("destroy", lambda w: gtk.main_quit())
me.set_decorated(False)
me.set_has_frame(False)
me.set_resizable(False)
me.set_property('skip-taskbar-hint', True)
self.label = gtk.Label()
self.label.modify_font(pango.FontDescription("FreeSerif Bold 50"))
attr = pango.AttrList()
fg_color = pango.AttrForeground(65535, 0, 0, 0, 65535)
attr.insert(fg_color)
self.label.set_attributes(attr)
me.add(self.label)
me.show_all()
def update(self):
self.label.set_text(time.strftime('%H:%M:%S'))
return True
clock = Clock()
gtk.timeout_add(200, clock.update)
gtk.main()
I found this topic on askubuntu and It's exactly what I was looking for however now I'm having problems having the digital clock show. Any help would be greatly appreciated.
Here's my code.
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk
import pango
import time
import cairo
class Clock (gtk.Window):
def __init__(self):
super(Clock, self).__init__()
self.connect("destroy", lambda w: gtk.main_quit())
self.set_decorated(False)
self.set_has_frame(False)
self.set_resizable(False)
self.set_property('skip-taskbar-hint', True)
self.label = gtk.Label()
self.label.modify_font(pango.FontDescription("FreeSerif Bold 50"))
attr = pango.AttrList()
fg_color = pango.AttrForeground(65535, 0, 0, 0, 65535)
attr.insert(fg_color)
self.label.set_attributes(attr)
self.screen = self.get_screen()
self.visual = self.screen.get_rgba_visual()
self.set_visual(self.visual)
self.set_app_paintable(True)
self.connect("draw", self.area_draw)
self.add(self.label)
self.show_all()
def update(self):
self.label.set_text(time.strftime('%H:%M:%S'))
return True
def area_draw(self, widget, cr):
cr.set_source_rgba(.2, .2, .2, 0.5)
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.paint()
cr.set_operator(cairo.OPERATOR_OVER)
clock = Clock()
gtk.timeout_add(200, clock.update)
gtk.main()
Well, you have to hack a lot to make a label like this.
The best is to reinvent the wheel: make a round one.
Draw your own label.
Get window context ( mywin.window.cairo_create())) and keep track of x, y.
def draw(*args):
ctx = win.window.cairo_create()
ctx.set_source_rgba(0, 0, 0, 0)
ctx.set_operator(0) # OPERATOR_CLEAR
ctx.paint()
ctx.set_source_rgba(0, .6, 1, .3)
ctx.arc(w/2, h/2, w/2, 0, 2*3.1415)
ctx.fill()
ctx.set_source_rgba(1, .8, 0, 1)
ctx.show_text('29-May-1234') #you have some work for font, style and so on
google gives you an hack that use ctypes for loading ttf font from file; it works very well on Linux( I have no idea on win).
NOTE: Above asume that you have an composit manager, or ... rgba for widget is None.
Also put an
colormap = self.win.get_screen().get_rgba_colormap()
if colormap == None: colormap = self.win.get_screen().get_rgb_colormap()
gtk.widget_set_default_colormap(colormap)
to set rgba if posible, and also it worth a check:
if self.win.is_composited():print ('OK!')
else:self.bg = self.capt_screen()
...........
def capt_screen(self):
x, y = self.win.get_position()
win = gtk.gdk.get_default_root_window()
w, h = win.get_size()
pb = gtk.gdk.Pixbuf(0 , False, 8, w, h)
self.win.hide()
pb = pb.get_from_drawable(win, win.get_colormap(), 0, 0, 0, 0, w, h)
self.win.show_all()
if (pb != None):
im = Image.fromstring('RGB', (w, h), pb.get_pixels())
im = im.crop((x, y, x + self._w, y + self._h))
im = im.convert('RGBA')
return im #or pb
The above is „xp” transparent efect: copy the bg and bledit with your win. Only if it is not a composit manager runing. Is ok for widget - stay on desk, but flickr for something else: at every refresh window has to hide itself, capture the gb, drawing and reveal.
PS: I have an working clock example, but I use png. If you like, i could send you an tar.gz on mail

Resources