Kivy program: how to change focus in pycharm? - python

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

Related

how to bind an exe to a gui button - kivy

Allright, I just wrote a programme specific for my data analysis purposes and convert it to exe and when i double click on it, it works fine now except showing the console and all the other things it is doing. Instead double clicking on the exe file, i developped a very simple kivy gui which is as follows;
from cProfile import label
from email.mime import image
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.button import Button
from kivy.uix.textinput import TextInput
class Data_Col(App):
def build(self):
self.window = GridLayout()
self.window.cols = 1
self.window.size_hint = (0.5, 0.5)
self.window.pos_hint = {"center_x": 0.5, "center_y" : 0.5}
# add widgets to window
# image widget
self.window.add_widget(Image(source="logo.png"))
# label widget
self.greeting = Label(text="Bonjour!!!", font_size = 18, bold = True)
self.window.add_widget(self.greeting)
# button widget
self.button = Button(text="Run Data-Col", size_hint = (0.3, 0.3), bold = True, background_color = '0175E8', background_normal = "")
self.window.add_widget(self.button)
return self.window
if __name__ == "__main__":
Data_Col().run()
what i want is when the user clicks on the button, it runs the exe file which is in a different folder in my pc. So i need to give a path too to the button to go and tricks the execution of exe file. But don't know how to do it, if anyone knows i would appreciate it. thanks
I don't know much about Kivy, but I can help you run an .EXE file.
This is the code I wrote:
import os
def run_exe(file): # This is the function to run
os.system("start "+file)
run_exe("path/to/file.exe") # Replace "path/to/file.exe" with the path to your file (E.G. "C:/Users/Hipposgrumm/Documents/helloworld.exe").
Hopefully, that works. I'm more of a TKinter user so tell me if this isn't usable.

Kivy Config.read not working properly when using Window.bind from within another class

i just discovered a bug and am trying to find a solution. This is my folder structure:
|- root
|- GUI.py
|- GUI.ini
|- layouts
|- root.kv
|- style.kv
|- lib
|- kivy_utils.py
|- static
|- icon.ico
|- Barlow-Regular.ttf
|- Barlow-Bold.ttf
The GUI.py is my starting point for launching the GUI and looks like this:
# %% standard python library imports
import os
# %% kivy imports
# import kivy
from kivy.app import App
from kivy.core.window import Window
from kivy.config import Config
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
# %% lib imports
from lib.kivy_utils import TTLabel
# read & overrule config
Config.read(os.path.join(os.path.dirname(os.path.abspath(__file__)), "GUI.ini"))
Window.size = Config.getint("graphics", "width"), Config.getint("graphics", "height")
# read kv language files
for kv in ["root.kv", "style.kv"]:
Builder.load_file("layouts" + os.sep + kv)
class Root(BoxLayout):
""" Main Root class for callbacks, UI building etc."""
def __init__(self):
super().__init__()
def test_function(self):
print("K TEST")
class Launcher(App):
"""Supplementary Launcher class"""
def build(self):
return Root()
def on_pause(self):
return True
if __name__ == "__main__":
Launcher().run()
I want to use the kivy_utils.py for custom classes, such as scalable widgets, tooltips etc.:
from kivy.properties import BooleanProperty, ObjectProperty, NumericProperty
from kivy.core.window import Window
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.slider import Slider
from kivy.uix.switch import Switch
from kivy.clock import Clock
class Tooltip(Label):
pass
class HoverBehavior(object):
"""Hover behavior.
:Events:
`on_enter`
Fired when mouse enter the bbox of the widget.
`on_leave`
Fired when the mouse exit the widget
"""
hovered = BooleanProperty(False)
border_point = ObjectProperty(None)
def __init__(self, **kwargs):
self.register_event_type('on_enter')
self.register_event_type('on_leave')
Window.bind(mouse_pos=self.on_mouse_pos) # for recognizing tooltips
super(HoverBehavior, self).__init__(**kwargs)
def on_mouse_pos(self, *args):
if not self.get_root_window():
return
pos = args[1]
inside = self.collide_point(*self.to_widget(*pos)) # compensate for relative layout
if self.hovered == inside:
return
self.border_point = pos
self.hovered = inside
if inside:
self.dispatch('on_enter')
else:
self.dispatch('on_leave')
def on_enter(self):
pass
def on_leave(self):
pass
class TTLabel(HoverBehavior, Label):
"""Resizable Label with Tooltip on top of Label and HoverBehaviour class"""
def __init__(self, **kwargs):
super().__init__()
self.tooltip = None # Attribute set in kv file
self.header = None # Attribute set in kv file
self.tooltip_wdg = Tooltip()
Window.bind(on_resize=self.on_window_resize) # binds font_size rescaling function to on_resize event
Clock.schedule_once(self.on_window_resize, 1.5) # called once at init cuz widget hasnt final size yet
def on_enter(self):
"""Event fires when entering widget"""
if self.tooltip: # only binds event if tooltip variable is set
Window.bind(mouse_pos=lambda w, p: setattr(self.tooltip_wdg, 'pos', p)) # binds position to cursor
self.tooltip_wdg.text = self.tooltip # sets text to tooltip variable
Window.add_widget(self.tooltip_wdg)
def on_leave(self):
"""Event fires when leaving widget"""
if self.tooltip:
Window.remove_widget(self.tooltip_wdg)
def on_window_resize(self, *args):
"""Event fires when window is rescaled"""
fire_refresh = True
# # Fires when horizontal size is too small
if self.size[0] < self._label.size[0]:
fire_refresh = False
self.texture_size[0] = self.size[0] # reduce texture size to widget size
if self.size[1] < self._label.size[1]: # additionally, if vertical size is too small, reduce aswell
self.texture_size[1] = self.size[1]
return
# Fires when vertical size is too small
if self.size[1] < self._label.size[1]:
fire_refresh = False
self.texture_size[1] = self.size[1]
if self.size[0] < self._label.size[0]:
self.texture_size[0] = self.size[0]
return
# Fires when widget size > texture size # TODO: is there another way not to fire all the time?
if fire_refresh:
self.texture_update()
And finally, my root.kv looks like this:
<Root>:
BoxLayout:
orientation: 'horizontal'
Button:
text: "Test button"
on_release: root.test_function()
TTLabel:
text: "Test label with tooltip"
tooltip: "Also WOW!"
So now to my actual problem: The code works, however(!) the Config.read command in my GUI.py file is not "refreshing" the current Config - the load works, i can access the attributes via Config.get, use Config.write etc - the .ini file gets updated, but the changes are not realized. Now i was thinking to manually refresh the parameters from the config (e.g. Window.size = Config.getint("graphics", "width"), Config.getint("graphics", "height")), but i want to use the Options menu (F1) and there must be another way i am sure. The problem occures as soon as i use Window.bind from within my kivy_utils.py. I tried loading the Config there, use self.get_root_window instead of Window, putting the Config.read command in various places in the kivy_utils.py etc. What am i missing?
I figured it out - i just had to import and read the config before the Window import:
from kivy.config import Config
Config.read("GUI.ini")
from kivy.app import App
from kivy.core.window import Window
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
Like this you can use the configurator (F1) and the affected changes are recognized properly (after a restart of the UI, however). Also i figured out a weird behaviour of environmental variables: the kivy documentation states:
If you don't want to map any environment variables, you can disable
the behavior::
os.environ["KIVY_NO_ENV_CONFIG"] = "1"
They probably flipped a bool there, because 0 actually disables environmental variables while 1 enables them. Will report to kivy repository.

Wayland and Kivy: how to set window position?

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

How to dynamically change Kivy window dimensions based on platform

So I am just starting out with Kivy, and want to know how to
A: get the dimensions of the window (based on the platform)
The end goal is to launch the app on iOS, and there are multiple sized iPhones out there. How would I get the size of the screen of the device?
and B: somehow be able to refer to it
If I want to create a button that is centered on the screen, I need some way of getting the width_of_the_window and the length_of_the_window (these are obviously just made up variables).
Here is the code I am working on, although it is really basic so it probably won't provide much insight.
# Importing os
import os
# Importing Kivy, making sure its up to date, and importing App
import kivy
kivy.require('1.10.1')
from kivy.app import App
# Importing widgets, like buttons, drop down menus, etc
from kivy.uix.widget import Widget
from kivy.uix.dropdown import DropDown
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.boxlayout import BoxLayout
button_one = Button(text='Test', font_size = 20, pos = (root.width-100, 100), size_hint = (.06, .06))
class calculator_app(App):
def build(self):
return button_one
calculator_object = calculator_app()
calculator_object.run()
Actually, you don't need the size of the window in order to do centering. Change your button creation line to :
button_one = Button(text='Test', font_size = 20, pos_hint={'center_x': 0.5, 'center_y': 0.5}, size_hint = (.06, .06))
Using pos_hint will position the button regardless of the window size. Have a look at the documentation for pos_hint

Issues with changing color of basic Kivy app

I created a simple text-to-speech app with Kivy, using the FloatLayout option but am having trouble changing the color of the GUI without actually creating a .kv file (which I do not wish to do). The code of my app is here:
import kivy
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.image import Image
import requests
from threading import Thread
import os
class ButtonApp(App):
def talk(self):
self.info.text = self.text.text
command = "say %s" % (self.text.text)
os.system(command)
def say(self,instance):
t = Thread(target=self.talk)
t.start()
def build(self):
self.b = FloatLayout()
self.info = Label(text="Hello!", pos=(20,400) ,size_hint=(1,0.5), font_size="40sp")
self.text = TextInput(text='Hello!', pos=(20,200), size_hint=(1,0.5))
self.submit = Button(on_press=self.say,text='Submit',pos=(20,100), size_hint=(1,0.5))
self.b.add_widget(self.info)
self.b.add_widget(self.text)
self.b.add_widget(self.submit)
self.b.bind()
return self.b
if __name__ == "__main__":
ButtonApp().run()
Like I mentioned beforehand, all the suggestions I found doing prior research involved either Canvas (which I am not using), or creating a .kv file. Is there a pure python-kivy method of changing the color of a GUI?
You can do anything in pure python, though the reason you see so many kv examples is because it's easier and more concise due to being a more domain specific language, so I don't recommend avoiding it.
What kind of change do you actually want to make? For instance, you can change the background image of the Button with the background_normal or background_down properties (which take a filepath to an image), or tint its colour by setting its background_color to e.g. (1, 0, 0, 1) for red.

Categories

Resources