Wayland and Kivy: how to set window position? - python

Following a previous StackOverflow answer I made additions to one of the basic Kivy tutorial apps to position the window at the top left corner of the screen. This works as expected under Xorg, but not under Wayland/xwayland.
How do you change the Kivy window position when running under xwayland?
Code:
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
class MyPaintWidget(Widget):
pass
class MyPaintApp(App):
def build(self):
# Works under Xorg, not under Wayland
Window.top = 0
Window.left = 0
return MyPaintWidget()
if __name__ == '__main__':
MyPaintApp().run()

Kivy does have Wayland support, but it may not be compiled-in. See setup.py. Also note that this will require SDL2 support to be compiled-in, as well:
# change both to "True"
c_options['use_wayland'] = False
c_options['use_sdl2'] = False

Related

Kivy program: how to change focus in pycharm?

When I run a kivy program in Pycharm, the kivy window doesn't have the default kivy app title, the kivy logo in top-left nor the 3 control buttons in the top-right. It completely occupies my screen and I can't do anything anymore. I'm on Windows 10. Need help, please.
I'm using Python 3.9.0, kivy 2.0.0
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.label import Label
class MainWidget(Widget):
pass
class boxLayoutExample(BoxLayout):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.orientation = "vertical"
item1 = Button(text='a button')
self.add_widget(item1)
item2 = Label(text='a label')
self.add_widget(item2)
item3 = Button(text='a button')
self.add_widget(item3)
class myApp(App):
pass
myApp().run()
the key is the configuration which can either be modified using the config.ini file or the config object.
on my windows system the config file is in C:\users<username>.kivy\config.ini
and you may have to change Windows Explorer to show hidden items if you want to see the .kivy directory.
inside that configuration file, the borderless property being set to 1 could cause this behavior so set this to 0. The curios thing is that by default this should have been 0 so I don't know why it would have changed.
[graphics]
borderless = 0
and you may also be interested in these properties
width = 1200
height = 600
fullscreen = 0
from kivy import Config
Config.set("graphics", "fullscreen", "0")
RTFM -> go here

Get global position of widget in Kivy?

I have an image located relative to the screen size with RelativeLayout. How can I get the global (/window) position of that image, so that I can detect if touch coordinates overlap the image?
this is my current implimentation:
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
from kivy.uix.relativelayout import RelativeLayout
class mainApp(App):
def build(slef):
appRoot = FloatLayout()
relPos = RelativeLayout()
button = Image()
relPos.pos_hint = {"right":1,"top":1.5}
relPos.add_widget(button)
#attempting to print the coordinates of the Image in the window
print(relPos.to_parent(*button.pos))
return relPos
if __name__ == '__main__':
mainApp().run()
As you can see, I'm attempting to use to_parent to get the position relative to the parent. However, I don't think it works pos_hint.
I've also tried using AnchorLayout, and have had similar issues
Note: while I know I can use the window_size, allong with a bit of math, I would like a more robust solution that can handle more complex situations

Removing Kivy's Window border

According to the kivy document, I can remove Window's border by Window.borderless = True
(https://kivy.org/doc/stable/api-kivy.core.window.html)
However, The problem is, it still shows the border when it starts up, then it gets removed in like 0.5 second. And it seems a bit weird to me
Is it possible to remove the border at the very beginning?
The problem is caused by first reading the Config and probably configured to be border and then read your configuration, so the solution in that case is to save it in the config, so a second load of the application will no longer watch that transition.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.config import Config
Config.read("myapp.ini")
if Config.getint('graphics', 'borderless') == 0:
Config.set('graphics', 'borderless', '1')
Config.write()
Window.borderless = True
class MyApp(App):
def build(self):
return Widget()
if __name__ == '__main__':
MyApp().run()

Export_to_png only saves background

I recently learnt about the Python framework kivy and started to follow the simple paint app tutorial. Now I want to save what was drawn as a .png file but instead of the colored dots it only exports the black background.
This is my code example:
import kivy
kivy.require("1.9.1")
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.graphics import Color, Ellipse, Line
class MyPaintWidget(Widget):
def on_touch_down(self,touch):
color=(0,0,1)
with self.canvas:
Color(*color)
d=30.
Ellipse(pos=(touch.x-d/2., touch.y-d/2.), size=(d,d))
class MyPaintApp(App):
def build(self):
parent=Widget()
self.painter=MyPaintWidget()
ssbtn=Button(text='Save')
ssbtn.bind(on_release=self.save_screenshot)
parent.add_widget(self.painter)
parent.add_widget(ssbtn)
return parent
def save_screenshot(self,obj):
self.painter.export_to_png("screenshot.png")
if __name__ == '__main__':
MyPaintApp().run()
What am I doing wrong? Thanks for your help.
You are missing one thing - Widget won't set its size and position automatically to whole Window size, but only to default ones i.e. pos = [0, 0] size = [100, 100] because Window != Layout and even adding it to something that doesn't inherit from a Layout won't make it better (Widget != Layout) which you can easily see if you look a that saved png (is too small).
self.painter=MyPaintWidget(size=[800,600])
will make the job for you if you plan to stay only on pc and only with the default Window size. If not, then use:
from kivy.core.window import Window
self.painter=MyPaintWidget(size=Window.size)
which seems to be more practical, yet you're still not there. An optimal solution would be using a Layout which does these things for you such as BoxLayout, GridLayout or some others.
And a perfect solution for you would be to use a StencilViewin a Layout, which when is placed won't take a screenshot of the whole canvas, but only the part you'd think it'll take i.e. the part sized as the Widget itself placed on its position.
Try drawing outside of the red box. Inspector will provide you with showing widgets in a color and other functions, so definitely try it as it was mentioned in the comments.
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.core.window import Window
from kivy.uix.stencilview import StencilView
from kivy.graphics import Color, Ellipse, Line, Rectangle
class MyPaintWidget(StencilView):
def on_touch_down(self,touch):
color=(0,0,1)
with self.canvas:
Color(*color)
d=30.
Ellipse(pos=(touch.x-d/2., touch.y-d/2.), size=(d,d))
class MyPaintApp(App):
def build(self):
parent=Widget()
self.painter=MyPaintWidget(size=[i/2.0 for i in Window.size])
with self.painter.canvas:
Color(1, 0, 0, 0.3)
Rectangle(pos=self.painter.pos, size=self.painter.size)
ssbtn=Button(text='Save')
ssbtn.bind(on_release=self.save_screenshot)
parent.add_widget(self.painter)
parent.add_widget(ssbtn)
return parent
def save_screenshot(self,obj):
self.painter.export_to_png("screenshot.png")
MyPaintApp().run()

Kivy: Hide mouse cursor on desktop

I have a fullscreen app and I'm trying to hide the mouse cursor. The setup is Kivy 1.9.0 on Python 3.4.1 for Windows, using the prepared packages.
I have tried the following approaches, with no success:
1- Using Config object:
from kivy.config import Config
Config.set("graphics", "show_cursor", 0)
2- Editing .kivy\config.ini:
[graphics]
.
.
.
show_cursor = 0
3- Using pygame:
import pygame
pygame.init()
pygame.mouse.set_visible(False)
4- Moving the mouse off-screen:
def move_mouse_away(etype, motionevent):
# this one doesn't get called at all
Window.mouse_pos = [1400, 1000]
Window.bind(on_motion=move_mouse_away)
5- Using Clock for a similar effect:
Clock.schedule_interval(self._reset_mouse, 0.05)
def _reset_mouse(self, time):
Window.mouse_pos = [1400, 1400]
I'm a little out of ideas now.
You can use Window.show_cursor
It was added in kivy version 1.9.1
from kivy.core.window import Window
Window.show_cursor = False
I just read the documentation, tried it and fixed it (version 1.9.0). To hide the cursor from the application window permanently (even if you are using a touchscreen) :
>>> from kivy.config import Config
>>> Config.set('graphics','show_cursor','0')
>>> Config.write()
>>> quit()
I use a touch screen (LG 19MB15T) which works 'out_of_the_box'.
I'm having the same kind of problem: I need to hide or change my mouse cursor in a kivy app.
I don't have a perfect solution only a partial one:
from kivy.uix.widget import Widget
from kivy.core.window import Window
import win32api
class NoCursorWindow(Widget):
def __init__(self, **kwargs):
super(NoCursorWindow, self).__init__(**kwargs)
Window.bind(mouse_pos=self.on_mouse_pos)
def on_mouse_pos(self, *args):
win32api.SetCursor(None)
if __name__ == '__main__':
from kivy.base import runTouchApp
runTouchApp(NoCursorWindow())
It works only partially:
The problem when you use win32api.SetCursor() is that when the mouse moves, the window gets a WM_SETCURSOR Message which changes the cursor back to default. This is why the win32api.SetCursor() must be triggered for each change of the mouse_pos.
But even like that sometimes we can see the default cursor blinking.
If anyone knows how to hook the WM_SETCURSOR, to prevent the call back of the default cursor, it could solve this...

Categories

Resources