I am having alot of issues trying to add an image to Scatter in Kivy. I want the image to first appear the same height as the boxlayout. Then I would like to be able to move and scale it (this does work currently). When I run the code the image shows up very small. I would also like the image to resize itself if the size of the window is changed. I am new to kivy so any help would be great. Thanks!
<MyGridLayout>:
rows: 1
BoxLayout:
id:layout1
orientation: 'vertical'
BoxLayout:
id: box1
size_hint : [1,0.5]
StencilView:
ScatterLayout:
center_x: box1.center_x
center_y: box1.center_y
Image:
source: 'histo_test.png'
size_hint_y: None
size_hint_x: None
width: self.parent.width
height: self.parent.width/self.image_ratio
center: self.parent.center
allow_stretch: True
keep_ratio: True
BoxLayout:
size_hint : [1,0.5]
id:box2
StencilView:
ScatterLayout:
center_x: box2.center_x
center_y: box2.center_y
Image:
source: 'flower.png'
size_hint_y: None
size_hint_x: None
width: self.parent.width
height: self.parent.width/self.image_ratio
center: self.parent.center
allow_stretch: True
keep_ratio: True
The size of the image must be the size of the StencilView, so:
size: stencil.width, stencil.height
or
width: stencil.width
height: stencil.width/self.image_ratio
(stencil is the id of the StencilView)
And the size of the ScatterLayout must be the size of the image:
size: my_image.size
(my_image is the id of the image)
Also you can set the position of the ScatterLayout with the position of the StencilView:
pos: stencil.pos
instead of this:
center_x: box1.center_x
center_y: box1.center_y
Watch this video for more info.
I wrote this code which does almost the same
<MyGridLayout>:
orientation: 'vertical'
StencilView:
id: stencil1
Scatter:
pos: stencil1.pos
size: my_image1.size
Image:
id: my_image1
size: stencil1.width, stencil1.height
source: 'dog.jpg'
allow_stretch: True
keep_ratio: False
StencilView:
id: stencil2
Scatter:
pos: stencil2.pos
size: my_image2.size
Image:
id: my_image2
size: stencil2.width, stencil2.height
source: 'flower.jpg'
allow_stretch: True
keep_ratio: False
Sorry if my english isn't clear
Related
I'm trying to use Squib to generate a map for a boardgame by printing one "card" which is the size of an entire A4 sheet of paper.
There must be some default in Squib that is cropping the resulting images and text, however, so that only a portion of it is visible.
Here is some sample code demonstrating the problem:
require 'squib'
Squib::Deck.new cards: 1, layout: [] do
rect x: 0, y: 0, width: 3457, height: 2438, fill_color: 'BLUE'
circle x: 1728, y: 1218 , radius: 1218, fill_color: 'RED'
save_pdf file: 'maps_1.pdf'
end
At 300 dpi, a landscape A4 piece of paper should be 3457x2438 pixels, so this ought to display a blue box with a red circle, filling the page. Instead it displays a poker-card-sized chunk of that image in the upper left hand corner:
resulting pdf
The result is much the same if I use millimeters, with a sprue:
require 'squib'
Squib::Deck.new cards: 1, layout: [] do
rect x: 0, y: 0, width: '295mm', height: '208mm', fill_color: 'BLUE'
circle x: '147.5mm', y: '104mm' , radius: '104mm', fill_color: 'RED'
save_pdf file: 'maps_1.pdf', sprue: 'layouts/map-sprue.yml'
end
Sprue:
---
sheet_width: 297mm
sheet_height: 210mm
card_width: 295.0mm
card_height: 208.0mm
cards:
- x: 0.0mm
y: 0.0mm
crop_line:
lines:
- type: :vertical
position: 0.0mm
- type: :vertical
position: 295.0mm
- type: :horizontal
position: 0.0mm
- type: :horizontal
position: 208.0mm
Does anyone know what is forcing squib only to address a portion of the A4 page?
thanks
You want width and height as parameters to Squib::Deck.new
To make your "card" the entire size of an A4 page, use something like this:
Squib::Deck.new(width: '210mm', height: '297mm') do
end
HOWEVER If you are planning on printing to an A4 page I recommend making it a tad smaller so that your printer doesn't autoscale or cut things off. My printer does fine with 6mm margin, probably something like 200x290.
You probably don't need sprues in this situation.
Trying to place text within a Rectangle. I even tried solution given here.
I want the text to be within Rectangle. This should holds good even if I change window size please. When I add_widget Actor I still want to continue pos_hint and size_hint format. Any idea please..
from kivy.uix.label import Label
from kivy.uix.relativelayout import RelativeLayout
from kivy.properties import ListProperty
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.scatter import Scatter
from kivy.core.window import Window
Window.clearcolor = (1, 1, 1, 1)
Window.size = (800, 600)
kv = '''
<Actor>:
canvas:
PushMatrix
Color:
rgba: 0,1,0,.8
Rectangle:
id: _rect_
size: self.width, self.height/12
pos: 0, 11 * (self.height / 12)
Line:
points: self.width/2, 11 * self.height/12, self.width/2, 0
width:2
PopMatrix
Label:
id: _actr_lbl
text: 'Hello World'
markup: True
color: 0,0,0,1
pos: 0, 11 * self.height/12
halign: 'center'
'''
Builder.load_string(kv)
class Actor(Scatter):
def __init__(self, **kwargs) :
super(Actor, self).__init__(**kwargs)
class TestApp(App):
def build(self):
layout = RelativeLayout()
layout.add_widget(Actor(pos_hint = {'center_x':0.5, 'top':0.95}, size_hint = (0.2, 1)))
return layout
if __name__ == '__main__':
TestApp().run()
I think you can accomplish what you want by adjusting your kv for the Label slightly:
Label:
id: _actr_lbl
text: 'Hello World'
markup: True
color: 0,0,0,1
size_hint: None, None
size: root.width, root.height/12
pos: 0, 11 * root.height/12
halign: 'center'
Adding size_hint: None, None allows the size to be effective. And referencing root for size and pos info keeps the Label sized and positioned correctly.
I'm having difficulty in positioning a label that has an image added using canvas within a scrollview. The desirable output is to have a label with text content as a paragraph followed by a label with an image and then followed by another label with text content as a paragraph.
The image is displaying in the correct position vertically as in its between the two text labels, but it is not positioning center when I attempt to scale down the image by multiplying the self.parent.width by .9 or whatever the decimal. It's binding it to the left screen and padding in the label is not working whereas it does work in the labels with text content. I have searched for documentation and other examples but could not find a solution to this. If anyone has experience with this or can provide any guidance, I'd greatly appreciate it. Please see my code below:
BoxLayout:
size_hint_y: .7
orientation: 'vertical'
canvas.before:
Color:
rgba: rgba('#FFFFFF')
Rectangle:
pos: self.pos
size: self.size
ScrollView:
id: sv
size_hint_y: None
height: self.parent.height
effect_cls: 'ScrollEffect'
GridLayout:
id: Content
cols: 1
size: self.minimum_size
size_hint: (1, None)
height: labelscroll1.texture_size[1]
Label:
id: labelscroll1
padding: ['20dp', '0dp']
color: rgba('#000000')
font_size: mtx.sp(14)
text_size: self.width, None
size: self.parent.width, self.texture_size[1]
size_hint: (None,None)
text: "Some text"
Label:
id: labelscroll2
padding: ['5dp','0dp']
size_hint: (None, None)
width: max(self.texture_size[0], self.parent.width)
height: 300
halign: 'center'
markup: True
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'Table.png'
Label:
id: labelscroll3
padding: ['20dp', '0dp']
color: rgba('#000000')
font_size: mtx.sp(14)
text_size: self.width, None
size: self.parent.width, self.texture_size[1]
size_hint: (None,None)
text: "Some text"
The indentations are four spaces in actual code but the formatting might be slightly off in here due to pasting.
Without seeing your actual code, I can only guess at what the problem actually is. But a good way to get something centered within a GridLayout cell is to use the AnchorLayout. Try replacing your middle Label in your kv with:
AnchorLayout:
size_hint: (1.0, None)
height: 300
Label:
id: labelscroll2
padding: ['5dp','0dp']
size_hint: (None, None)
width: max(self.texture_size[0], self.parent.width)
height: 300
halign: 'center'
markup: True
canvas.before:
Rectangle:
pos: self.pos
size: self.size
source: 'Table.png'
My Kivy application has a different look under Mac than under Windows or Linux. What could be the reason behind this ? The screen resolution ? The installation process under different OS ? ... ?
Here is the code for the first page:
#:kivy 1.0.9
<MenuButton>:
font_size: 20
size_hint: None, None
height: 75
width: 300
pos_hint: {'center_x': .5, 'center_y': .5}
MyScreenManager:
HomePage:
#### Home Page ##############################################
<HomePage>:
name: 'Home'
BoxLayout:
orientation: 'vertical'
spacing: 50
padding: 20
BoxLayout:
orientation: 'vertical'
size_hint: 1, 0.23
Label:
text: 'V2G-Sim'
font_size: 50
Label:
text: 'Vehicle to Grid Simulator'
font_size: 30
BoxLayout:
orientation: 'vertical'
size_hint: 1, 0.64
spacing: 20
RelativeLayout:
MenuButton:
text: 'Create vehicles'
on_release:
app.root.transition.direction = 'left'
app.root.current = 'Itinerary'
RelativeLayout:
MenuButton:
text: 'Grid initialization'
on_release:
app.root.transition.direction = 'left'
app.root.current = 'Grid'
RelativeLayout:
MenuButton:
text: 'Simulate vehicles'
on_release:
app.root.transition.direction = 'left'
app.root.current = 'SimulationType'
RelativeLayout:
MenuButton:
text: 'Visualizations'
on_press:
root.raise_popup()
on_release:
root.visualization()
BoxLayout:
orientation: 'horizontal'
size_hint: 1, 0.13
spacing: 30
Button:
text: 'Project status'
font_size: 20
size_hint: 0.7, 1
on_release:
app.root.transition.direction = 'left'
app.root.current = 'ProjectStatus'
Button:
text: 'Exit'
font_size: 20
size_hint: 0.7, 1
on_release:
root.exit_app()
Here is the look under a Windows/Linux distribution:
Here is the look under Mac (tested with 2 different Mac book)
The mac probably has a high dpi display, so your fixed size declarations for the buttons and font size are half the actual size since they're given in pixels.
You can use the dp function from kivy.metrics (automatically imported in kv) to avoid this, e.g. font_size: dp(20).
Note that screens are all a bit different and may not have their dpi reported correctly anyway, so you will probably still get some (smaller) differences with different hardware.
I'd like to draw the x,y coordinates of a nested ellipse I have within the ellipse. However, I'm afraid I don't understand the object hierarchy enough for how to do that. I have tried adding a label event to be a child of the Ellipse, and I know it doesn't have a 'text' attribute that I can modify directly (as it's not a Button or a Label). Here's what I have:
MyWidget:
canvas.before:
Color:
rgba: 1,0,0,1
Ellipse:
size: min(self.size)*0.2, min(self.size)*0.2
pos: (self.x), (self.y)
Label:
text: unicode(self.x), unicode(self.y)
Error:
>> 40: Label:
41: text: unicode(self.x), unicode(self.y)
...
You can add only graphics Instruction in canvas.
So, I add it to a child of the Ellipse:
MyWidget:
canvas.before:
Color:
rgba: 1,0,0,1
Ellipse:
size: min(self.size)*0.2, min(self.size)*0.2
pos: (self.x), (self.y)
Label:
text: unicode(self.x), unicode(self.y)
>> 40: Label:
41: text: unicode(self.x), unicode(self.y)
...
You can add only graphics Instruction in canvas.
So, I try to put it in a canvas:
MyWidget:
canvas.before:
Color:
rgba: 1,0,0,1
Ellipse:
size: min(self.size)*0.2, min(self.size)*0.2
pos: (self.x), (self.y)
canvas:
Label:
text: unicode(self.x), unicode(self.y)
That doesn't have an error, but doesn't display any text.
Updating to address excellent answer below
MyWidget:
canvas.before:
Color:
rgba: 1,0,0,1
Ellipse:
size: min(self.size)*0.2, min(self.size)*0.2
pos: (self.x, self.y)
Label:
pos: (self.x,self.y)
size: min(self.size)*0.2, min(self.size)*0.2
text: "{},{}".format(str(self.x),str(self.y))
Gives me the following error:
44: Label:
>> 45: pos: (self.x, self.y)
46: size: min(self.size)*0.2, min(self.size)*0.2
47: text: "{},{}".format(str(self.x),str(self.y))
...
RuntimeError: maximum recursion depth exceeded while calling a Python object
I still can't get the text to appear /inside/ the Ellipse.
Your problem is that you cannot mix the canvas with widgets.
A way to think of it is that each widget has a canvas. You can draw what you like on that canvas, but the keyword there is draw - you can use kivy graphics instructions, like Ellipse or Rectangle or Line (or contextual instructions like Translate and Rotate). However, you can't use widgets. They don't work that way, they aren't things you draw on a canvas, they are widgets. When you add one widget to another with add_widget, one thing that happens is that its canvas is drawn on the canvas of the other, but this is kept to the canvases - it doesn't make sense to try and draw a whole widget on a canvas.
This is the root of all of your errors; Ellipse is not a widget. It doesn't have a canvas, it's only something you draw on a canvas. It can't have children because it isn't a widget. In kv language, the keyword canvas (and canvas.before etc.) doesn't mean there's a child widget called canvas, it's just a special syntax referring to the canvas of the parent widget.
So, to actually fix your problem, you need to take the Label out of the canvas. Something like the following should work:
MyWidget:
canvas.before:
Color:
rgba: 1,0,0,1
Ellipse:
size: min(self.size)*0.2, min(self.size)*0.2
pos: (self.x), (self.y)
Label:
pos: root.pos
size: min(self.size)*0.2, min(self.size)*0.2
text: unicode(self.x), unicode(self.y)
This is of course the normal syntax for making the Label just be a child of MyWidget. The important part is it's been given the same position and size as the ellipse so, since text is centered by default, the text will appear in the middle of the ellipse. If the text is long or something you might want to play with other things like setting text_size to automatically wrap, but that's a different problem.
Also, once you have multiple widgets with the same size description (like the size of both the Label and Ellipse in my example), it's often neater to move that calculation to a different place - for instance a NumericProperty of MyWidget. That way you can avoid code duplication, and also make it so that if you ever change the positioning requirements you can easily update both the Label and Ellipse simultaneously.