Kivy take screenshot with clear background - python

I'm working on a Kivy app that lets the user position images and text labels on a template. When they're done, the resulting image is cropped to fit the template.
I need all the empty space in the image to be clear, as I will be printing the image and don't want to waste ink. Kivy, however, fills all the empty space with black. Is there a way for Kivy's export_to_png() function to use a transparent background instead of a black one?

I could be wrong, but it looks like the transparent colour is hardcoded.
Looking at the source code it seems that ClearColor is hard-coded as black.
def export_to_png(self, filename, *args):
'''Saves an image of the widget and its children in png format at the
specified filename. Works by removing the widget canvas from its
parent, rendering to an :class:`~kivy.graphics.fbo.Fbo`, and calling
:meth:`~kivy.graphics.texture.Texture.save`.
.. note::
The image includes only this widget and its children. If you want
to include widgets elsewhere in the tree, you must call
:meth:`~Widget.export_to_png` from their common parent, or use
:meth:`~kivy.core.window.WindowBase.screenshot` to capture the whole
window.
.. note::
The image will be saved in png format, you should include the
extension in your filename.
.. versionadded:: 1.9.0
'''
if self.parent is not None:
canvas_parent_index = self.parent.canvas.indexof(self.canvas)
self.parent.canvas.remove(self.canvas)
fbo = Fbo(size=self.size, with_stencilbuffer=True)
with fbo:
ClearColor(0, 0, 0, 1)
ClearBuffers()
Scale(1, -1, 1)
Translate(-self.x, -self.y - self.height, 0)
I guess you could try updating the Widget module code to accept a parameter to set the ClearColor.

Related

Adjusting opacity and updating the properties of a text object in a canvas in Python

I created a canvas and inside I put an image. I also can change the properties of the watermark text and would like to update the text on the canvas when I make some changes.
I created the text inside of the canvas with create_text and when I initialize the program, I created a variable. text_variable = canvas.create_text(...) However, I couldn't also adjust the opacity of the text.
Problems:
I can't adjust the opacity
I can't update color, font style, font size and position after I put this text on the canvas.
I expect:
Change the text when I change some properties from the edit menu
Add opacity adjustment to the text
self.watermark_display = self.display_canvas.create_text(self.watermark_start_position_x, self.watermark_start_position_y, text="Plese write your watermark!", font=(self.fonttype.get(),self.fontsize.get()),fill=self.color_choice)
def update_watermark_display(self):
self.display_canvas.itemconfig(self.watermark_display, self.watermark_start_position_x, self.watermark_start_position_y, text="Plese write your watermark!", font=(self.fonttype.get(),self.fontsize.get()),fill=self.color_choice)
When I try to do with this way, I got Type Error.
self.display_canvas.itemconfig(self.watermark_display, self.watermark_start_position_x, self.watermark_start_position_y, text="Plese write your watermark!", font=(self.fonttype.get(),self.fontsize.get()),fill=self.color_choice)
TypeError: Canvas.itemconfigure() takes from 2 to 3 positional arguments but 4 were given
You cannot use itemconfig to change the coordinates. Instead, use the coords method for the coordinates, and itemconfig for the item configuration.
self.display_canvas.itemconfig(
self.watermark_display,
text="Plese write your watermark!",
font=(self.fonttype.get(),self.fontsize.get()),
fill=self.color_choice
)
self.display_canvas.coords(
self.watermark_display,
self.watermark_start_position_x,
self.watermark_start_position_y
)

ImageTk and PIL do not display png image correctly

I am currently trying to write some kind of mapping tool in python using both the PIL and Tkinter module. So far almost everything works quite fine. During the setup process of the ui a virtual image is created (based upon several input png files), which also seems to have worked well. However, when trying to display this picture inside a canvas using ImageTk.Photo the display shows something that is definitly not the picture. For debugging reasons I had my picture be output by using the show method on the PIL.Image itself.
However what the show method shows and the canvas displays somehow differ - I could not figure out the solution and would appreciate help.
First of all the code excerts (I only show the initialization of the canvas and the displaying of the picture, since the whole code would be extremly long and not provide any more inside I guess).
This is the code excert of the initialization of the canvas (I display a completly black picture until the user loaded all resources neccessary for displaying the picture):
self.tileset_canvas = tkinter.Canvas(root, width=1024, height=1024)
self.tileset_canvas.create_line(0, 0, 80, 80)
self.tileset_raw_image = ImageTk.PhotoImage(PImage.new("RGB", (1024, 1024), "black"))
self.tileset_canvas_image = self.tileset_canvas.create_image(0, 0, image=self.tileset_raw_image)
self.tileset_canvas.grid(row=4, column=6, sticky=tkinter.W)
Furthermore inside another method I change the display of the image:
merged_img = PImage.new("RGB", (128, 512))
merged_img.paste(tsp_img, (0, 0))
merged_img.paste(tss_img, (0, 320))
merged_img = merged_img.resize((1024, 1024)) #Double the view for a better mapping expierience
merged_img = merged_img.convert(mode="RGB")
self.tileset_raw_image = ImageTk.PhotoImage(merged_img)
merged_img.show()
self.tileset_canvas.itemconfig(self.tileset_canvas_image, image=self.tileset_raw_image)
As you can see I also call the show method to see what the picture actually looks like.
This is what the show method outputs, when called on the picture:
However this is what is shown inside the ui:
For anyone that cares, it seems that the image was not just correctly anchored but instead fixed in the middle of the canvas.

Is it possible to precalculate the height of text to be printed in renpy?

Renpy uses a lot of python and custom made code, in order to show text that is displayed on screen using the say statement.
After running into some troubles with the nvl mode within renpy, I found it necessary to know how many lines are going to be displayed on screen (taking into account the font size, naturally and the size of the text window).
So my question:
As I didn't find anything in the documentation in regards to that, I'm wondering if there is any command or other possibility to precalculate the height of a text that is to be displayed?
get_virtual_layout() is part of class Text in text.py.
I copied this from text.py:
# Find the virtual-resolution layout.
virtual_layout = self.get_virtual_layout()
# The laid-out size of this Text.
vw, vh = virtual_layout.size
This looks promising, I think.
With the virtual text size (width, height) you could possibly calculate the lines of text by using the text window size (width, height).
pseudo code:
lines = int(vw/text_window.width)
#the text height would then be
text_height_needed = int(lines*vh)
# does it fit in completely
complete_text_in_window = text_window.height >= text_height_needed
# visible lines
visible_lines = int(text_window.height/vh)
Also, it is worth to take a deeper look at text.py(e.g. def render(self, width, height, st, at)), in order to get to know the use of virtual_layout.
I hope it helps somehow.
Update:
def render(...) initializes the virtual layouts, so get_virtual_layout() is not None anymore, but represents an instance of Layout() with scaled width and height.

How to make a wxpython Bitmap Button with only image and no extra pixels and border around image

I am trying to use an image as a button in wxpython. What I want is that there should only be a bitmap and no other border or any extra pixel around the button. I would really only want to capture a click on a bitmap, so maybe I do not need an actual button. "Pressing down" the button is hence not required.
One option that I am using a PlateButton with platebutton.PB_STYLE_NOBG which works fine only when it is displaying the image without any mouse hover or clicks. Now when I hover the button, what I want is a shadowed image of same image(only image and no border or anything), but what I get is a square border around my image.
My code :
import wx.lib.platebtn as platebutton
imageButton = platebutton.PlateButton(self._ribbon,wx.ID_NEW, bmp = wx.Bitmap("image.png", wx.BITMAP_TYPE_ANY), pos = (0,0), size = (37,17), style= platebutton.PB_STYLE_DEFAULT | platebutton.PB_STYLE_NOBG)
You can directly use static bitmap and capture the mouse event in this bitmap.
try this:
sBitMap = wx.StaticBitmap(self._ribbon, -1, wx.Bitmap("image.png", wx.BITMAP_TYPE_ANY), (0, 0), (37,17))
sBitMap.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
def OnLeftDown(self, e):
print "OnLeftDown"
Edit:
Fetch the size from the source image and use it to create the static bitmap
sBitMap = wx.StaticBitmap(self._ribbon, -1, wx.Bitmap("image.png", wx.BITMAP_TYPE_ANY), (0, 0), (bmp.GetWidth(), bmp.GetHeight()))
I'm using the GenBitmapButton from wx.lib.buttons
path="path to bitmap"
size=(size of bitmap)
b=GenBitmapButton(Parent,wx.ID_ANY, bitmap=wx.Bitmap(path),
style=wx.NO_BORDER|wx.BU_EXACTFIT,size=size)
This is doing the trick just fine and I have bitmaps lined up with no spacing between them for buttons.

how to create a transparent rectangle responding to click event in Tkinter

I need to draw a rectangle in a tkinter.canvas to respond click event:
click_area = self.canvas.create_rectangle(0,0,pa_width,pa_height,fill='LightBlue',outline='lightBlue',tags=['A','CLICK_AREA'])
self.canvas.tag_bind('CLICK_AREA','<Button>',self.onClickArea)
it works.
at this moment, I have to draw a series of grid on the canvas, and I want them to be covered with the click_area, so that I need to make the click_area transparent.
but, when I wrote like this:
click_area = self.canvas.create_rectangle(0,0,pa_width,pa_height,fill='',outline='lightBlue',tags=['A','CLICK_AREA'])
it did not respond to click any longer.
So, my question is how to make it transparent and keep it responding to click. Or, is there any other way to implement what I want.
Thank you very much.
I came across this same issue trying to use the find_closest Canvas method to modify existing rectangles, but simply binding to the canvas didn't work. The issue is that a Tkinter rectangle without a fill will only respond to clicks on its border.
Then I read about the stipple argument to create_rectangle from here:
stipple: A bitmap indicating how the interior of the rectangle will
be stippled.
Default is stipple="", which means a solid color. A
typical value would be stipple='gray25'. Has no effect unless the fill
has been set to some color. See Section 5.7, “Bitmaps”.
And the section on bitmaps states that only a few stipple options are available by default, but none of them are completely transparent. However, you can specify your own custom bitmap as an X bitmap image (a .xbm file).
XBM files are really just text files with a C-like syntax, so I made my own 2x2 bitmap with all transparent pixels and saved it as transparent.xbm in the same directory as my Tkinter script. Here's the code for the XBM file:
#define trans_width 2
#define trans_height 2
static unsigned char trans_bits[] = {
0x00, 0x00
};
Then, you can specify the custom stipple by prefixing the xbm file name with a # when creating your rectangle:
self.canvas.create_rectangle(
x1,
y1,
x2,
y2,
outline='green',
fill='gray', # still needed or stipple won't work
stipple='#transparent.xbm',
width=2
)
Note, you still need to provided some fill value or the stipple will not be applied. The actual fill value doesn't matter as the stipple will "override" it in the canvas.
I think I got it: Bind the canvas, not the rectangle.
replace
self.canvas.tag_bind('CLICK_AREA','<Button>',self.onClickArea)
with
self.canvas.bind('<Button>',self.onClickArea)
problem solved.

Categories

Resources