So I'm able to use the video library to play video on my GUI, but I realized the video was always placed at the middle with the default size, as there are no attribute like pos or size in video class. I would like to know if there are any way I can size and place the video like other widgets/buttons/labels.
The following example illustrates sizing and placing a video.
Example
In the following demo, we are using AnchorLayout. You can replace it with any Layouts (BoxLyout, FloatLayout, etc.), Widget, etc. and use pos or pos_hint.
main.py
from kivy.base import runTouchApp
from kivy.lang import Builder
runTouchApp(Builder.load_string("""
AnchorLayout:
anchor_x: 'center'
anchor_y: 'top'
Video:
source: 'rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov'
state: 'play'
keep_ratio: True
allow_stretch: True
size_hint: 0.8, 0.8
"""))
Related
I'm trying to get the size of the rectangle from the canvas called Canvas_Widget class, but no matter what I do, it keeps on giving an error
the code that I wrote and the description of the error are given in the code as a comment.
source file:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
from kivy.metrics import dp
Window.size= dp(500),dp(500)
class Canvas_Widget(Widget):
def __init__(self,**kwargs):
super().__init__(**kwargs)
class MainWidget(BoxLayout):
def __init__(self,**kwargs):
super(MainWidget, self).__init__(**kwargs)
def minimizer(self,button):
button.background_color=(1,0,0,1)
#here i want to try and print the size of that rect id that i created
# i tried "print(self.ids.Canvas.ids.rect.size)"
"""the error says: (((File "f:\canvas\1\main.py", line 16, in minimizer
print(canvas.ids.rect.size)
File "kivy\properties.pyx", line 964, in kivy.properties.ObservableDict.__getattr__
AttributeError: 'super' object has no attribute '__getattr__')))"""
def minimizer_release(self,button):
button.background_color=(.3,.3,1,1)
class mynewApp(App):
pass
mynewApp().run()
here is the kivy file:
MainWidget:
<Canvas_Widget>:
canvas:
Color:
rgb:.4,.4,.4,1
Rectangle:
id:rect #this is the id that Im trying to share with the MainWidget
pos:dp(100),dp(100)
size:self.width - dp(200),self.height - dp(200)
Color:
rgb:0,1,0,1
Line:
points:(dp(100),self.height - dp(100),self.width - dp(100),dp(100))
Line:
points:(dp(100),dp(100),self.width - dp(100),self.height - dp(100))
<MainWidget>:
Button:
text:'press'
on_press:root.minimizer(self)
background_color:(.3,.3,1,1)
on_release: root.minimizer_release(self)
Canvas_Widget:
id:Canvas
here is also the problem with the placement of the canvas on the screen. its suppose to be on the right side, but it's on the left side, on the button:
image 1
image 2
by the way, I'm sorry to ask for too much. it's just that I really want to know how to fix this problem.
thanks
First thing to notice that in kvlang binding happens by Builder automatically (at least from developer's side). That's why it's convenient to use this language for design purpose. From kivy doc.,
As your application grows more complex, it’s common that the construction of widget trees and explicit declaration of bindings becomes verbose and hard to maintain. The KV Language is an attempt to overcome these shortcomings. The KV language, sometimes called kvlang or the kivy language, allows you to create your widget tree in a declarative way and to bind widget properties to each other or to callbacks in a natural manner.
Now in kvlang when you do something like this :
Rectangle:
pos:dp(100),dp(100)
in the canvas instructions, you are basically instructing to draw a rectangle at (100, 100) in the window. But what you want (as it seems) is to draw that rectangle where the widget is and shifted by (100, 100) from its position.
Now as you used BoxLayout as container, each of its child's position, size are managed by itself (if not provided explicitly). So to reflect that changes you need to change the above lines of code by the following,
Rectangle:
pos: self.x+dp(100), self.y+dp(100)
This will reposition the rectangle (automatically) whenever the position of widget (x, y) changes.
Thus the changes you need in your kvlang are,
<Canvas_Widget>:
canvas:
Color:
rgb:.4,.4,.4,1
Rectangle:
# id:rect # Will not work here.
# pos:dp(100),dp(100)
pos: self.x+dp(100), self.y+dp(100)
size: self.width - dp(200), self.height - dp(200)
Color:
rgb:0,1,0,1
Line:
# points:(dp(100),self.height - dp(100),self.width - dp(100),dp(100))
points: (self.x+dp(100), self.y+self.height-dp(100), self.x+self.width-dp(100),self.y+dp(100))
Line:
# points:(dp(100),dp(100),self.width - dp(100),self.height - dp(100))
points: (self.x+dp(100), self.y+dp(100),self.x+self.width-dp(100), self.y+self.height-dp(100
I'm brand new to Kivy, and am working on the UI to get a fairly complex set of widgets to display properly. My root widget is a boxlayout(horiz), and I'm trying to get 2 floatlayouts to appear side by side. But the second floatlayout displays on the left side of the boxlayout over the first floatlayout. I've tried with and without pos_hints and size_hints at the floatlayout level, to no avail. Some base code:
<BoxLayout>:
id: rootwid
orientation: 'horizontal'
FloatLayout:
id: leftside
pos_hint: {'x':0, 'y':0} (Also tried 'right' and 'top' and commenting out the line)
#size_hint: (.5, 1)
(Buttons & Labels here, which lay out properly within the floatlayout)
FloatLayout:
id: rightside
pos_hint: {'x': .5, 'y':0} (Also tried 'right' and 'top' and commenting out the line)
#size_hint: (.5, 1)
(Buttons & Labels here, which lay out properly within the floatlayout)
What am I missing? Thanks!
unless you have a future use for the FloatLayouts, I advise that you replace them with other types of layouts bcoz since they are float, they tend to be independent of the parent.
Try using GridLayout to house the buttons and labels and other widgets
like this;
BoxLayout:
orientation: 'horizontal'
GridLayout:
cols: any
rows: any
# Left widgets added here
GridLayout:
cols: any
rows: any
# Right widgets added here
You can also nest them accordingly, for extensize insight on these run KivyCatalog , an inbuilt python file in kivy-examples,
usually at ~/.local/share/kivy-examples/demo/kivycatalog/main.py for Ubuntu
for windows i think check AppData then local then share, AppData is by default hidden , dont forget that.
KivyCatalog is interative as it shows you changes in your kv code as you write it,try it.
How do I get the fixed window size at one point in time? (s.t. this value will not change later)
I would like to add an image:
Image:
width: self.parent.width
height: self.parent.height
size_hint: None, None
which should keep its initial size when rescaling the window.
I can do this like
Image:
width: 800
height: 800
size_hint: None, None
But I can't get the windows current dimensions in a way that they stay constant when rescaling the window later.
Thanks for your help.
The only way I can think of is to do it outside of your .kv file. Precisely, you can set the values on any event triggered, such as on button press or when starting your app, just like that:
from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
class Main(App):
def build(self):
base = Builder.load_file("main.kv")
base.ids.img.width = Window.width
base.ids.img.height = Window.height
return base
In the example provided the width and height are set only once, when building the app. Alternatively you could achieve the same behaviour by moving the code to the __init__ of your class and access the image whenever you'd like to by calling self.base.ids.img (under the assumption you provide self.base).
I am in a bit of a predicament. While working with Kivy's ScrollView Layout and (Current Experimental) reStructuredText renderer module, I ran into a slight problem. Whenever I run my code, my terminal spams me with:
[CRITICAL] [Clock] Warning, too much iteration done before the next frame. Check your code, or increase the Clock.max_iteration attribute
Now, the application seems to run perfectly fine, until you get to the page with the rST Document inside a ScrollView Layout. That page does all kinds of odd things. The Main scroll view will slowly scroll down, forever, trailing off the page into whiteness, and the rST document is placed oddly, shifted slightly to the left.
When I remove the document though, the screen and application behave perfectly normal, running smoothly. Does anyone have any idea as to how I could fix this, to make the page work correctly? (Did I mention the rST Document was originally in a Carousel, but I took out the carousel to see if that was the problem.)
Here is the Kivy Language Code:
<Page>:
orientation: 'vertical'
ScrollView:
size_hint: (.99, .99)
StackLayout:
size_hint_y: None
id: content_layout
height: self.minimum_height
WrappedLabel:
text: "Test"
font_size: min(root.height, root.width)
RstDocument:
underline_color: 'blue'
text:("Some Text")
Could the problem be that rST Documents are based off of the ScrollView Layout by any chance?
Sometimes height: self.minimum_height and similar stuff are like shooting yourself in a foot. Definitely try to comment out these things first, because if you don't do something fancy, the sizing is the issue.
Now, why is it an issue? StackLayout has its minimum_height set from minimum_size, which is set I think somewhere here and has some initial value that is not zero.
Don't be confused though, minimum_height really defaults to zero at the beginning, but then it's recalculated probably on each added widget or so. If you add on_height: print(self.height) after your height: self.minimum_height, you'll see what I mean.
Why does it do it like that? Simple! You didn't set absolute size for those children (each child has size_hint == [1, 1]).
Also, ScrollView expects size bigger that the ScrollView if I remember correctly (so that it would scroll).
from kivy.lang import Builder
from kivy.base import runTouchApp
from kivy.uix.boxlayout import BoxLayout
Builder.load_string('''
<Test>:
orientation: 'vertical'
ScrollView:
size_hint: (.99, .99)
StackLayout:
size_hint_y: None
id: content_layout
height: self.minimum_height
on_height: print(self.height)
Label:
size_hint: None, None
size: 100, 30
text: "Test"
font_size: min(root.height, root.width)
RstDocument:
size_hint: None, None
size: 100, 1000
underline_color: 'blue'
text:("Some Text")
''')
class Test(BoxLayout): pass
runTouchApp(Test())
Remove size_hint and size from children and you have your too much iteration there.
I would like to create an app in kivy with widgets in a grid and I want to be able to set some widgets to be larger - to occupy more than one cell in a grid.
GridLayout seems the most appropriate, but it seems to not support placing widgets in more than one cell.
To be more specific I want behavour similar to the grid geometry manager from Tkinter, when setting columnspan or rowspan to more than 1.
Like this:
(widget)(widget)(widget)
( bigger widget )(widget)
...
I would prefer to be able to do this using existing kivy layouts instead of having to write my own layout class to handle this, but if no other option is possible, this is also ok.
Another option here is to have a GridLayout with 1 column and populate each row with a BoxLayout with orientation="horizontal". You can then format each BoxLayout (row) as you want.
For more info on the BoxLayout: http://kivy.org/docs/api-kivy.uix.boxlayout.html
I don't think a GridLayout is really suitable, it just isn't designed for quite that usage.
If I personally had to do this, I'd probably make my own Layout class, it wouldn't need a very complicated do_layout method.
One possible start point would be the SparseGridLayout I made a while ago. You could very easily add column and row span properties to it...actually, I'll probably add them myself now that you've given me the idea!
That might not be ideal if you have a big grid full of widgets, in which case something similar to a gridlayout might be better, or possibly a combination of multiple layouts if the spanning widgets are in a particular pattern.
Lets assume you have a GridLayout with two columns and you want to span the first row.You can add Two FloatLayout whereby the first FloatLayout will contain the widget you would like to span while the second Layout will have row and height values to zero.This would archive a span effect
here is an example of .kv span effect
GridLayout:
cols:2
FloatLayout: # The first FloatLayout in the first column in the gridLayout
size_hint:None,None
size: 0,50
BoxLayout:
size_hint: None,None
size: root.width-40,50
pos_hint: {'x':.5,'center_y':.5}
BoxLayout:
padding:0,0,5,0
Label:
id:lbl_unknown
text:'Accession number :'
TextInput:
text:''
FloatLayout: # The second FloatLayout in the second column of the gridLayout
size_hint:None,None
size:0,0
Label:
text:'Label 1:'
TextInput:
Label:
text:'Label 2:'
TextInput:
An easy work around is to pack BoxLayout objects into any type of parent layout you want using your better judgement to decide the orientation of each subsequent BoxLayout
(decided to use box layouts for almost all of my own project over any gridlayout)
This is my class:
class AuthPage(BoxLayout):
def __init__(self, **kwargs):
super(AuthPage, self).__init__(**kwargs)
self.orientation = 'vertical'
self.add_widget(Label(text='Authenticate'))
unameRow = BoxLayout(orientation='horizontal')
unameRow.add_widget(Label(text='User Name'))
unameRow.username = TextInput(multiline=False)
unameRow.add_widget(unameRow.username)
self.add_widget(unameRow)
pwordRow = BoxLayout(orientation='horizontal')
pwordRow.add_widget(Label(text='password'))
pwordRow.password = TextInput(password=True, multiline=False)
pwordRow.add_widget(pwordRow.password)
self.add_widget(pwordRow)
self.add_widget(Button(text='authenticate'))