In kv-File auf Zustand eines Objekts abfragen?
Verfasst: Sonntag 21. März 2021, 19:48
Guten Abend zusammen,
ich muss mich wieder an euch wenden. Ich habe ein GUI in Kivy erstellt, allerdings kann das nur arbeiten, wenn meine Cloud gemountet ist. Das GUI läuft auf einem Raspberry Pi und dieser ist über eine W-lan Verbindung im Netz. Das GUI startet automatisch beim hochfahren, zu dieser Zeit ist das Netzwerk wohl noch nicht so weit, so dass die 'fstab' abgearbeitet wird ohne die Cloud einzubinden.
Ich dachte mir, mit dem Problem kann ich was neues in Python lernen. Also habe ich mir gedacht, ich starte eine Animation und im Hintergrund wird für eine bestimmte Zeit 'mount -a' abgearbeitet. Wenn das eine gewisse Zeit fehlschlägt soll der Pi wieder herunterfahren. (Da habe ich aber viel "gedacht"
)
Ich habe einen ersten Ansatz, den ich auch am Ende meines Textes poste. Mein Problem ist gerade, dass ich bei erfolgreicher mount-Operation die Animation verlassen will und der eigentliche 'main'-Screen soll angezeigt werden.
Ich will also in der kv-Datei abfragen ob 'mounted' True ist und dann den Bildschirm wechseln. Aber ich weis nicht wie ich in diesem Fall die Kommunikation zwischen .py und .kv Datei aufbaue.
Kann mir hier bitte jemand weiter helfen? Ich vermute dass das 'return' so nicht den Zustand an die kv-Datei übermittelt. Das ist auch meine erste Berührung mit Threading, da fehlt mir vermutlich noch etwas Basiswissen.
Ob die Funktionen, wie sie im folgenden Code geschrieben sind funktionieren weis ich noch nicht. Ich weis aber, dass die Abfrage in der kv-Datei nicht funktioniert. Und erst wenn ich das raus habe, kann ich den Rest mener Meinung nach sinnvoll testen.
Hier poste ich euch mal beide vollständigen Dateien:
Vielen Dank schon mal und Grüße
Dennis
ich muss mich wieder an euch wenden. Ich habe ein GUI in Kivy erstellt, allerdings kann das nur arbeiten, wenn meine Cloud gemountet ist. Das GUI läuft auf einem Raspberry Pi und dieser ist über eine W-lan Verbindung im Netz. Das GUI startet automatisch beim hochfahren, zu dieser Zeit ist das Netzwerk wohl noch nicht so weit, so dass die 'fstab' abgearbeitet wird ohne die Cloud einzubinden.
Ich dachte mir, mit dem Problem kann ich was neues in Python lernen. Also habe ich mir gedacht, ich starte eine Animation und im Hintergrund wird für eine bestimmte Zeit 'mount -a' abgearbeitet. Wenn das eine gewisse Zeit fehlschlägt soll der Pi wieder herunterfahren. (Da habe ich aber viel "gedacht"

Ich habe einen ersten Ansatz, den ich auch am Ende meines Textes poste. Mein Problem ist gerade, dass ich bei erfolgreicher mount-Operation die Animation verlassen will und der eigentliche 'main'-Screen soll angezeigt werden.
Ich will also in der kv-Datei abfragen ob 'mounted' True ist und dann den Bildschirm wechseln. Aber ich weis nicht wie ich in diesem Fall die Kommunikation zwischen .py und .kv Datei aufbaue.
Kann mir hier bitte jemand weiter helfen? Ich vermute dass das 'return' so nicht den Zustand an die kv-Datei übermittelt. Das ist auch meine erste Berührung mit Threading, da fehlt mir vermutlich noch etwas Basiswissen.
Ob die Funktionen, wie sie im folgenden Code geschrieben sind funktionieren weis ich noch nicht. Ich weis aber, dass die Abfrage in der kv-Datei nicht funktioniert. Und erst wenn ich das raus habe, kann ich den Rest mener Meinung nach sinnvoll testen.
Hier poste ich euch mal beide vollständigen Dateien:
Code: Alles auswählen
#!/usr/bin/env python3
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.dropdown import DropDown
from kivy.uix.slider import Slider
from kivy.uix.button import Button
from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.factory import Factory
from kivy.animation import Animation
from kivy.clock import Clock
from InternetRadio import Radio
from MusicPlayer import PlaylistPlayer
from pathlib import Path
from subprocess import run
import threading
from time import sleep
RADIOSENDER_PATH = Path('/media/MusicBox/Senderliste.csv')
PLAYLIST_PATH = Path('/media/MusicBox/Playlist/')
class WaitForWlan(Screen):
def start_second_thread(self):
threading.Thread(target=self.check_wlan).start()
def check_wlan(self):
Clock.schedule_once(self.waiting_animation, 0)
sleep(0.5)
mounted = False
for _ in range(20):
if not mounted:
mounted = run(['sudo', 'mount', '-a'], check=True)
return mounted
sleep(1)
if not mounted:
run(['sudo', 'systemctl', '-h', '0'], check=True)
def waiting_animation(self, *args):
anim_bar = Factory.AnimWidget()
self.anim_box.add_widget(anim_bar)
anim = Animation(opacity=0.3, width=50, duration=0.6)
anim += Animation(opacity=1, width=400, duration=0.8)
anim.repeat = True
anim.start(anim_bar)
class MainScreen(Screen):
pass
class StartScreen(Screen):
pass
class RadioScreen(Screen):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.radiostation = Radio()
def create_radioplayer(self):
try:
for sender in self.radiostation.read_station(RADIOSENDER_PATH):
sender_button = Button(text=sender, size_hint_y=None, height=44)
sender_button.bind(on_release=lambda sender_button: self.ids.DropDownMenu.select(sender_button.text))
#
# Check to add only once the radiostation to DropDownMenu.
#
if self.ids.sender_button.text not in self.radiostation.read_station(RADIOSENDER_PATH):
self.ids.DropDownMenu.add_widget(sender_button)
else:
break
except:
pass
def set_sender(self, sendername):
self.radiostation.switch_station(sendername)
def radio_play(self):
self.radiostation.play_music()
def radio_stop(self):
self.radiostation.radio_stop()
def set_volume(self, volume):
self.radiostation.set_volume(volume)
class PlaylistScreen(Screen):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.player = PlaylistPlayer()
def load_playlist(self):
#
# Check to add only once the playlistobjects to DropDownMenu.
#
try:
check_new_folder = Path(f"{PLAYLIST_PATH}/{self.ids.playlist_button.text}")
if check_new_folder.is_dir():
pass
else:
for playlist in PLAYLIST_PATH.iterdir():
playlist_button = Button(text=playlist.name, size_hint_y=None, height=44)
playlist_button.bind(
on_release=lambda playlist_button:
self.ids.DropDownPlaylist.select(playlist_button.text)
)
self.ids.DropDownPlaylist.add_widget(playlist_button)
except:
pass
def playlist_player(self, music_folder):
music_path = Path(f"{PLAYLIST_PATH}/{music_folder}/")
self.player.addPlaylist(music_path)
def player_play(self):
self.player.play()
def player_next(self):
self.player.next()
def player_pause(self):
self.player.pause()
def player_previous(self):
self.player.previous()
def player_stop(self):
self.player.stop()
def player_volume(self, volume):
self.player.set_volume(volume)
class BluetoothScreen(Screen):
def bluetooth_on(self):
try:
run(["rfkill unblock bluetooth"], shell=True, check=True)
except:
pass
def bluetooth_off(self):
try:
run(["rfkill block bluetooth"], shell=True, check=True)
except:
pass
class ShutdownScreen(Screen):
def musicbox_off(self):
run(["sudo shutdown -h 0"], shell=True, check=True)
class AnimWidget(Widget):
pass
class ImageButton(ButtonBehavior, Image):
pass
class VolumeSlider(Slider):
pass
class DropDownMenu(DropDown):
pass
class DropDownPlaylist(DropDown):
pass
kv = Builder.load_file("musicbox.kv")
class MusicBox(App):
def build(self):
screenmanager = ScreenManager()
screenmanager.add_widget(WaitForWlan(name='wlan'))
screenmanager.add_widget(MainScreen(name='main'))
screenmanager.add_widget(RadioScreen(name='internetradio'))
screenmanager.add_widget(PlaylistScreen(name='playlist'))
screenmanager.add_widget(BluetoothScreen(name='bluetooth'))
screenmanager.add_widget(ShutdownScreen(name='shutdown'))
return screenmanager
if __name__ == '__main__':
run(["rfkill block bluetooth"], shell=True, check=True)
# Window.fullscreen = 'auto'
MusicBox().run()
Code: Alles auswählen
# Filename: musicbox.kv
<AnimWidget@Widget>:
canvas:
Color:
rgba: 0.7, 0.3, 0.9, 1
Rectangle:
size: self.size
pos: self.pos
size_hint: None, None
size: 400, 30
<WaitforWlan>:
name: "wlan"
anim_box: anim_box
GridLayout:
cols: 1
Image:
source: 'hugo.png'
size: self.size
AnchorLayout:
id: anim_box
returns: root.start_second_thread()
if mounted:
app.root.current = "main"
root.manager.transition.direction = "up"
<MainScreen>:
name: "main"
GridLayout:
cols: 2
ImageButton:
id: button_radio
source: 'icon/radio.png'
pos_hint: {"x":0, "top":1}
on_press:
app.root.current = "internetradio"
root.manager.transition.direction = "up"
ImageButton:
id: button_playlist
source: 'icon/playlist.png'
pos_hint: {"x":0, "top":1}
on_press:
app.root.current = "playlist"
root.manager.transition.direction = "up"
ImageButton:
id: button_bluetooth
source: 'icon/bluetooth.png'
pos_hint: {"x":0, "top":1}
on_press:
app.root.current = "bluetooth"
root.manager.transition.direction = "up"
ImageButton:
id: button_shutdown
source: 'icon/shutdown.png'
pos_hint: {"x":0, "top":1}
on_press:
app.root.current = "shutdown"
root.manager.transition.direction = "up"
<RadioScreen>:
name: "internetradio"
GridLayout:
rows: 2
GridLayout:
cols: 2
Image:
size_hint_x: 0.1
source: 'icon/volume+.png'
allow_stretch: True
Slider:
id: slider
value_track: True
value_track_color: (1,0.2,0.7,1)
min:0
max:100
value: 30
step: 1
on_value:
root.set_volume(int(self.value))
GridLayout:
cols: 4
ImageButton:
id: button_back_main
size_hint_x: 1
allow_stretch: True
source: 'icon/home_radio.png'
on_press:
app.root.current = "main"
root.radio_stop()
root.manager.transition.direction = "down"
ImageButton:
id: button_play
source: 'icon/play_radio.png'
on_press:
root.radio_play()
ImageButton:
id: button_pause
source: 'icon/break_radio.png'
on_press:
root.radio_stop()
ImageButton:
id: sender_button
text: ''
source: 'icon/liste_radio.png'
on_parent: DropDownMenu.dismiss()
on_release:
root.create_radioplayer()
DropDownMenu.open(self)
DropDownMenu:
id: DropDownMenu
on_select:
sender_button.text = '{}'.format(args[1])
root.set_sender(sender_button.text)
<PlaylistScreen>:
name: "playlist"
GridLayout:
rows: 3
GridLayout:
cols: 2
Image:
size_hint_x: 0.1
source: 'icon/volume+.png'
allow_stretch: True
Slider:
id: volume_slider
value_track: True
value_track_color: (0,245,255,1)
min:0
max:100
value: 30
step: 1
on_value: root.player_volume(int(self.value))
GridLayout:
cols: 5
ImageButton:
id: button_previous
source: 'icon/backward.png'
on_press:
root.player_previous()
ImageButton:
id: button_play
source: 'icon/play_playlist.png'
on_press:
root.player_play()
ImageButton:
id: button_pause
source: 'icon/break_playlist.png'
on_press:
root.player_pause()
ImageButton:
id: button_stop
source: 'icon/stop_playlist.png'
on_press:
root.player_stop()
ImageButton:
id: button_next
source: 'icon/forward.png'
on_press:
root.player_next()
GridLayout:
cols: 3
ImageButton:
id: button_back_main
source: 'icon/home_playlist.png'
on_press:
root.player_stop()
app.root.current = "main"
root.manager.transition.direction = "down"
ImageButton:
id: playlist_button
text: ' '
source: 'icon/liste_playlist.png'
on_parent: DropDownPlaylist.dismiss()
on_release:
root.load_playlist()
DropDownPlaylist.open(self)
DropDownPlaylist:
id: DropDownPlaylist
on_select:
playlist_button.text = '{}'.format(args[1])
root.playlist_player(playlist_button.text)
root.player_stop()
<BluetoothScreen>:
name: "bluetooth"
GridLayout:
cols: 2
ImageButton:
id: button_on
source: 'icon/bluetooth.png'
on_press:
root.bluetooth_on()
ImageButton:
id: button_back_main
source: 'icon/home_bluetooth.png'
on_press:
app.root.current = "main"
root.manager.transition.direction = "down"
root.bluetooth_off()
<ShutdownScreen>:
name: "shutdown"
GridLayout:
cols: 2
ImageButton:
id: button_back_main
source: 'icon/home_shutdown.png'
on_press:
app.root.current = "main"
root.manager.transition.direction = "down"
ImageButton:
id: button_shutdown
source: 'icon/shutdown.png'
on_press: root.musicbox_off()
Dennis