I'm writing a PyGtk paint program based on the basic tutorial found here.
Is there any way to add an image to the drawing area so that you can still draw over the image? Like a stamp, or an imported photo for example. I've tried adding a gtk.Image() but gtk.DrawingArea object has no attribute add.
self.window = gtk.Window((gtk.WINDOW_TOPLEVEL))
self.window.set_title ("Canvas")
self.window.set_position(gtk.WIN_POS_CENTER)
hbox = gtk.HBox(False, 0)
self.window.add(hbox)
self.window.set_resizable(False)
# Create the drawing area
drawing_area = gtk.DrawingArea()
drawing_area.set_size_request(screenWidth-350, screenHeight-100)
hbox.pack_start(drawing_area, True, True, 0)
drawing_area.show()
You have to draw the image (as a gtk.gdk.Pixbuf, not gtk.Image) onto the backing pixmap yourself using gtk.gdk.Drawable.draw_pixbuf(). Only container widgets (widgets that can contain other widgets) have an add() method, and gtk.DrawingArea is not one.
pixbuf = gtk.gdk.pixbuf_new_from_file(image_filename) #one way to load a pixbuf
pixmap.draw_pixbuf(None, pixbuf, 0, 0, x, y, -1, -1, gtk.gdk.RGB_DITHER_NONE, 0, 0)
Related
Why is my image corrupt when displayed using simple QPixMap and draw commands. Every once in awhile it will display correctly.
self._pixmap = QtGui.QPixmap(128,128)
painter = QtGui.QPainter(self._pixmap)
brush = QtGui.QBrush(QtCore.Qt.SolidPattern)
brush.setColor(QtGui.QColor(240, 20, 20, 255))
painter.setPen(QtGui.QPen(brush, 1, QtCore.Qt.SolidLine,QtCore.Qt.SquareCap))
painter.drawLine(0, 0, self._pixmap.width(), self._pixmap.height())
painter.drawLine(self._pixmap.width(), 0, 0, self._pixmap.height())
painter.end()
You should call fill before painting using QPainter, look at reference here about QPixmap constructor
This will create a PySide.QtGui.QPixmap with uninitialized data. Call PySide.QtGui.QPixmap.fill() to fill the pixmap with an appropriate color before drawing onto it with PySide.QtGui.QPainter .
I got a problem to set the transparent background of drawing area.
The reason what I want this is that I have a main window where is background
def draw_pixbuf(self,widget, event):
path = 'test.jpg'
pixbuf = gtk.gdk.pixbuf_new_from_file(path)
scaled_buf = pixbuf.scale_simple(800,480,gtk.gdk.INTERP_BILINEAR)
widget.window.draw_pixbuf(widget.style.bg_gc[gtk.STATE_NORMAL], scaled_buf, 0, 0, 0,0)
self.window = gtk.Window()
self.window.connect("delete-event", gtk.main_quit)
self.window.set_decorated(False)
self.window.set_position(gtk.WIN_POS_CENTER_ALWAYS)
self.window.set_size_request(800,480)
hbbox = gtk.HBox()
hbbox.connect('expose-event', self.draw_pixbuf)
so my HBox has this background and I have two Fixed containers in it - one button and one drawing area.
fix = gtk.Fixed()
image = gtk.Image()
image.set_from_file("close.png")
event_box = gtk.EventBox()
event_box.add(image)
event_box.set_size_request(30,30)
event_box.set_visible_window(False)
event_box.connect("button_press_event",gtk.mainquit)
fix.put(event_box,140,0)
self.darea = gtk.DrawingArea()
self.darea.set_size_request(450,300)
self.darea.connect("expose-event", self.expose)
fix2 = gtk.Fixed()
fix2.put(self.darea,175,90)
hbbox.pack_start(fix2, True, False, 10)
hbbox.pack_end(fix, True, False, 10)
#hbbox.pack_start(self.darea,True,False,10)
self.window.add(hbbox)
self.window.show_all()
But the drawing area overrides that HBox's background with its own default background(grey). I am able to change background by modify_bg function, but I want it transparent to write the cairo animated text on the HBox's background.
So the goal is to have background image of the window and draw the caito animated text onto it and not to grey rectangle (drawing area's background).
I am new to GTK so maybe I miss something important how to do it.
I hope you can help. Thank you.
I also have not found solution and swiched to Cairo (Pycairo)
See more there: GTK drawable area transparent background color
I'm trying to get buttons with image and label and didn't succed. I can have button with label OR image but not both.
This is my part of code:
try:
pb = Pixbuf.new_from_file_at_size('myimg.jpg', 100, 100)
except:
pb = None
img = Gtk.Image()
img.set_from_pixbuf(pb)
button1 = Gtk.Button(xalign=0.5, yalign=1)
#button1.set_label(lbl)
button1.set_image(img)
button1.set_image_position(Gtk.PositionType.TOP)
button1.get_style_context().add_class("btn_article")
any idea ?
Thanks
Doc: Gtk.Button.set_image (widget, data): "The image will be displayed if the label text is NULL". The image here usually is an icon, therefore there is a icon-name associate with it and (depends on settings) if necessary showing the label according the icon. Reverse the situation, the label is used to find an icon associate with it and (if necessary) showing the icon.
Use:
button1.set_always_show_image (True)
or, if that doesn't succeed, create a container inside (in your case Gtk.Grid) and pack inside the button, i.e:
grid = Gtk.Grid ()
img = Gtk.Image()
img.set_from_pixbuf(pb)
label = Gtk.Label ('test')
grid.attach (img, 0, 0, 1, 1)
grid.attach (label, 0, 1, 1, 1)
grid.show_all ()
button1.add (grid)
Short question:
I know how to draw text on a wx.Bitmap, but how can I draw text on a wx.Icon in wxpython so that it does not appear transparent?
Long question:
I have a wxpython based GUI application, that has a taskbar icon, which I set using mytaskbaricon.SetIcon("myicon.ico").
Now I would like to dynamically put some text on the icon, so I tried to use the wx .DrawText method as explained here.This works fine if I test this for bitmaps (which I use in menu items).
However, the taskbar requires an wxIcon instead of a wxBitmap. So I figured I'll convert the icon to a bitmap, draw the text, and then convert it back to an icon. This works, except that the text is not shown transparent. Why ? And how can I make the text NOT transparent ?
My code is as roughly follows:
import wx
class MyTaskBarIcon(wx.TaskBarIcon):
...
icon = wx.Icon("myicon.ico", wx.BITMAP_TYPE_ICO)
bmp = wx.Bitmap("myicon.ico", wx.BITMAP_TYPE_ICO)
memDC = wx.MemoryDC()
memDC.SetTextForeground(wx.RED)
memDC.SelectObject(bmp)
memDC.DrawText("A", 0, 0)
icon.CopyFromBitmap(bmp)
self.SetIcon(icon, APP_NAME_WITH_VERSION)
...
So, no errors raised and myicon.ico is shown, but the letter A is transparant (instead of red). If I use a .bmp file to start with (myicon.bmp) the text appears in the correct color (but the borders are jagged). I've played around with masks, foreground and background colors, but that didn't help.
(I am using Windows 7, Python 2.6, wxpython 2.8)
Edit: I've shortened my explanation, and made the code more self-contained
Short answer: It seems to me that there is a bug in this particular piece of wx code. I am going to report it and see what comes out of it.
Long answer: You can hack your way around. Setup a color, which is not used in the image. Then draw using that color and when done, fix alpha values and color of those pixels to match your expectation:
import wx
from wx import ImageFromStream, BitmapFromImage, EmptyIcon
import cStringIO, zlib
# ================================ ICON ======================================
def getData():
return zlib.decompress(
'x\xda\x01\x97\x03h\xfc\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x10\
\x00\x00\x00\x10\x08\x06\x00\x00\x00\x1f\xf3\xffa\x00\x00\x00\x04sBIT\x08\
\x08\x08\x08|\x08d\x88\x00\x00\x03NIDAT8\x8dm\xd2ML\x9bu\x00\xc7\xf1\xef\xf3\
<\xed\xda><\xa3#\xcb\x8a\x0cp\xac8\x15\x87\x89/ \x11\xd1d&:5&#n\xc9\\\xa2\
\xc6\xc3b\xe2\xd1y0Y2\xa3q^\xcc\xb8\x9a\xb9\xf9rQc\xc6\x0es\xa4\xd1\x91\xe98\
\xc8\x96\xb98H\xc3\x8b\xc0\xc6\x00\x91\xd2\xb2\xa7}\xda\xe7\xa5\xcf\xd3\xf6\
\xf9{0\xa2\x07\xbf\xf7_\xf29\xfc$\x00\xf1>\xb2\xd9\xc7\tI0$\xc0\xd5d\x06\xa5\
\x17q\xf9O\xa5\x0b$$\x85KB\xa2\xec\xcb\xbc\x1e}\x81\xdf\x01$q\x9a`>\xce\xc9`\
\xc7\x91#\xa1\xce\xa3;\xed\xdbg\xb3s\x19c\xe1\x9cz\xbe*A\x0f\x80\x80\xf4A\
\xeb\xb0\xfcPG\xa2;\x10\x8aI\xe5\xd9\x93\x8bB\xe6`l\x88U)\xf3-\xc7\xc3\xbb_{\
;r\xef\xe1Vci\xa4\xb0\xbc:\x17\xb8\xdczQ\xd3B5"A\x1f\x00\xa7"\xe39\x16\xfb\
\xd6_\xb1wu\x1f#\xa9\x15-k\xe6\xd4j\xa2D\xbf\xec\x95\x91\xe5PGX_\x18),.\xcei\
W\xdb\xbf\xd3:\xb7{49\x0e\xeem\x1dkAG+Z\xb4l\xdf\xc6o-\xc3\xea\x9fK\xbf\x84\
\xe5\xa6\xfe&\xa1>\xa8\xad)\xec\x96n}\xc6`E\xa8g7\x95d\xdbD\xf2\x82\xda\xae\
\x06\x08\xd95\x1e\xeej\xa2\xa1^F \xa1\x1b5\xae\xcf\xe5\xa8D\x14\xea\xf4\xf3\
\xdco\x9es\xb7\x9933\xe1Z\xe9U\t\xe0\xd8\xe7\x17?\t4\xecz7\x99\xd0hp\x05\x87\
\xf6u\x927\x0c6-\x87\xf6\xd6\x16\x00\xaa\x02\xbeN\xdd\xc2\xd7\x04\x99\xec:9K\
\xf9\xf8\xd37\x07\x8e\xcb\x00\x99\xca=\xbd\xbe\x00\xbf\xe4\xb1wO\x0c\xbb*\
\x08\x06\x83\x8c\xfd\xf8\x03E\xc3\xa0\xe2\xba\\\x1a\xfb\x99\xee=q\x8c\xac\
\x83#7RtC\x03\x00\x01\x80r\xd9\xea\xa9z2\x86\xeb\x13\x8bEpk\x82:U\xe5\x8f\
\x95\x15\xc6~\x1a\'=5\xc9\xb3\xcf\xef\xa7q\x87Jn\xd3A4\x04)\x97\xad\x1e\x00\
\x19\xc0\xb3-,\xbb\x82\xe3\xf9\xb85\xa8\xf8\x905J\xd4i\x1a\xe9\xa9I^:0\xc4#\
\xbd}\xb8U\xa8x>\x96]\xc1\xb3-\xb6\x04^\xd9N\x17K\x91gv\xc6\x03,el\xeek\x8b\
\x82\x1c\xe6\xd1\xc7\xfby\xa0g/j\xb4\x1e\xd3\x85\xd5\x8cE0"\x91+\xd9xe;\xfd\
\xaf\xc0\xb1\xae\x14\r\x03\xbd\xecr\xf5\xe6\x06\xc1\x10\xd4\x85\x83<5\xf8$\
\xf1\xc6zB\x80\x16\x86_of\xf1\xf0(\x1a\x06\x9ec]\xd9\x12\xb8\xb63\xea:\xe6\
\xa1\xd9\x9a\xd2-\xb7U\xf9bD\xf0\\o\x82\xaeD\x1d\x08X\xc9Z\x8c^\xcbP4\xd6\
\x99\xdf\xb00\xf3k3\x08e\x14#\xfa\xe7\xeb}GO\xbd\xf5Xr\xc7\xf0BAS[\xe3\x1a\
\xb1P\x08\xc5\x97\xa9\xf9\x82\x8aT\xc5\xf0\\\xaa\xd5*\xaa\xb8k\xa7\xefl\xbes\
\xfd\xcc\xb1\xd3[\x02\x80\xe17\x9e\x98\x8fF\xa3jv3_;12\xaf\xccJ*\xb2\x12\x06\
\xc0\xaf\x95iV+\xbc\xf7rR\xc8rcD\xa2kv\xe0\xcc\xdf;\x19 \x95J5\x17\n\x85\xef\
\xc3\xe10f\xa9`\x98\xf9;\x1f\xda\xb9\xe9qk\xe3\x86nm\xdc\xd0\xed\xdc\xf4\xf8\
\xf2\xf2\xfc\x07\x85B\xdel\x8e\xc7%]\xd7/\xa7R\xa9\xe4\x96\xc04M\xc7q\x9c\
\xb5\x89\x89\x89N!\xc4\xd3S\xdf|4\xcd\xfftw\xff\x97_]\xd3\xf5I\xc0\xf2}\xdf\
\x02\xf8\x0b\xc1.\x9e\xd8Y.\x85\x85\x00\x00\x00\x00IEND\xaeB`\x822\x86\xba\
\xb3' )
def getBitmap():
return BitmapFromImage(getImage())
def getImage():
stream = cStringIO.StringIO(getData())
return ImageFromStream(stream)
def getIcon():
icon = EmptyIcon()
icon.CopyFromBitmap(getBitmap())
return icon
# ============================================================================
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.number = 0
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.panel = wx.Panel(self)
self.button = wx.Button(self.panel, label="Test")
self.button.Bind(wx.EVT_BUTTON, self.OnButton)
self.tbicon = wx.TaskBarIcon()
self.tbicon.SetIcon(getIcon(), "Test")
self.sizer = wx.BoxSizer()
self.sizer.Add(self.button)
self.panel.SetSizerAndFit(self.sizer)
self.Show()
# --------------------------------------------------------------------------
def OnClose(self, e):
self.tbicon.Destroy()
self.Destroy()
wx.Exit()
# --------------------------------------------------------------------------
def OnButton(self, e):
# HERE WE GO!
self.number += 1
bitmap = getBitmap()
# Find unused color
image = bitmap.ConvertToImage()
my_solid_color = wx.Color(*image.FindFirstUnusedColour(0, 0, 0)[1:])
# Use the unused *unique* color to draw
dc = wx.MemoryDC()
dc.SetTextForeground(my_solid_color)
dc.SelectObject(bitmap)
dc.DrawText(str(self.number), 0, 0)
dc.SelectObject(wx.NullBitmap)
# Convert the bitmap to Image again
# and fix the alpha of pixels with that color
image = bitmap.ConvertToImage()
for x in range(image.GetWidth()):
for y in range(image.GetHeight()):
p = wx.Colour(image.GetRed(x, y),
image.GetGreen(x, y),
image.GetBlue(x, y))
if p == my_solid_color:
image.SetAlpha(x, y, 255) # Clear the alpha
image.SetRGB(x, y, 0, 0, 0) # Set the color that we want
# Convert back to Bitmap and save to Icon
bitmap = image.ConvertToBitmap()
icon = wx.IconFromBitmap(bitmap)
self.tbicon.SetIcon(icon, "Test")
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()
Note: A had to add some icon. You can ignore that part of the code.
Just a guess, but perhaps create your initial icon as an "EmptyIcon", then copy the bmp to it.
import wx
class MyTaskBarIcon(wx.TaskBarIcon):
...
icon = wx.EmptyIcon()
bmp = wx.Bitmap("myicon.ico", wx.BITMAP_TYPE_ICO)
bmp = WriteTextOnBitmap("A", bmp, color=wx.RED) #this function is as in the link above
icon.CopyFromBitmap(bmp)
self.SetIcon(icon, APP_NAME_WITH_VERSION)
...
I've isolated the cause of the problem to be the image, since the code seems to work with other png images with transparency. However, it doesn't seem to work with the one image I need it to. This would be of great help seeing as I'm trying to make a nice shaped window.
The image:
The code:
import wx
class PictureWindow(wx.Frame):
def __init__(self, parent, id, title, pic_location):
# For PNGs. Must be PNG-8 for transparency...
self.bmp = wx.Image(pic_location, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
framesize = (self.bmp.GetWidth(), self.bmp.GetHeight())
# Launch a frame the size of our image. Note the position and style stuff...
# (Set pos to (-1, -1) to let the OS place it.
# This style wx.FRAME_SHAPED is a frameless plain window.
wx.Frame.__init__(self, parent, id, title, size=framesize, pos = (50, 50), style = wx.FRAME_SHAPED)
r = wx.RegionFromBitmap(self.bmp)
self.SetShape(r)
# Define the panel and place the pic
panel = wx.Panel(self, -1)
self.mainPic = wx.StaticBitmap(panel, -1, self.bmp)
# Set an icon for the window if we'd like
#icon1 = wx.Icon("icon.ico", wx.BITMAP_TYPE_ICO)
#self.SetIcon(icon1)
self.Show()
# The paint stuff is only necessary if doing a shaped window
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Main()
def OnPaint(self, event):
dc = wx.PaintDC(self)
dc.DrawBitmap(self.bmp, 0, 0, True)
def Main(self):
sizer = wx.GridBagSizer()
button = wx.Button(self,-1,label="Click me !")
sizer.Add(button, (0,1))
# What pic are we opening?
pic_location = r"C:\Users\user\Pictures\CPUBAR\A4.png" # PNG must be png-8 for transparency...
app = wx.App(redirect=0) # the redirect parameter keeps stdout from opening a wx gui window
PictureWindow(None, -1, 'Picture Viewer', pic_location)
app.MainLoop()
This is in Windows 7, btw.
wx.RegionFromBitmap uses the bitmap's mask to set the shape. If your source image has an alpha channel then it won't have a mask and so wx.RegionFromBitmap will not be able to determine what shape to use. You can convert the source image such that all pixels are either fully opaque or fully transparent, and then wx.Image will load it with a mask instead of an alpha channel. Or you can convert it at runtime using wx.Image's ConvertAlphaToMask method before converting it to a wx.Bitmap.
Your code says that it needs to be in png-8 format in order for transparency to work.
First of all, is the image in png-8 format?
second, why is this a requisite for transparency???
You're converting your image to a bitmap - bitmaps do not support transparency.
As a workaround you could use a .gif (if you can stand the limited color set).
They only support a 1-bit alpha channel.