Kivy AttributeError: 'NoneType' object has no attribute 'ids'
Hallo
Ich mache die Benachrichtigung jezt einfach mit plyer, ich kann ja das mit pyjnius später noch ergänzen.
Ich habe aber gerade ein ganz anderes Problem: wenn man die app aktualisieren will gibt es einen ladebalken. Aber wenn man auf Start drückt dann aktualiesiert er sich nicht sondern wartet bis der Download fertig ist und steht dann auf 100%.
Hier nur ein kleines Beispiel Programm:
Weder der ladebalken noch das Label aktualiesiert sich.
Was kann ich Dagegen tun?
Ich mache die Benachrichtigung jezt einfach mit plyer, ich kann ja das mit pyjnius später noch ergänzen.
Ich habe aber gerade ein ganz anderes Problem: wenn man die app aktualisieren will gibt es einen ladebalken. Aber wenn man auf Start drückt dann aktualiesiert er sich nicht sondern wartet bis der Download fertig ist und steht dann auf 100%.
Hier nur ein kleines Beispiel Programm:
Code: Alles auswählen
from kivy.app import App
from kivy.lang import Builder
import urllib.request
g=Builder.load_string("""
BoxLayout:
Button:
on_press: app.dw()
Label:
id: lb
text:"...%"
ProgressBar:
id: pb
max: 100
""")
class myApp(App):
def __init__(self):
super().__init__()
def build(self):
return g
def dw(self):
urllib.request.urlretrieve("https://www.python.org/ftp/python/3.7.3/python-3.7.3-embed-amd64.zip","py.zip", self)
def __call__(self, bn,bs,cl):
percent=int((bn*bs)/cl*100)
self.root.ids.lb.text=str(percent)+"%"
self.root.ids.pb.value=percent
myApp().run()
Was kann ich Dagegen tun?
Als erstes könntest Du ordentliche Variablennamen vergeben. Auch zweibuchstabige Namen sind nicht aussagekräftig. Ich habe große Probleme den Code zu verstehen, was wie sich den nun bm von bs oder lb von pb unterscheidet. Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht Tabs, denn sonst kann es je Editoreinstellung zu unleserlichem Code kommen. Ein __init__ das nichts macht, als das super-__init__ aufzurufen, kann ganz weg.
Ich denke, wie bei jeder GUI muß man die Ausführung an die Hauptschleife zurückgeben, um eine Aktualisierung zu haben. Das tut aber urlretrieve nicht.
Was Du brauchst ist einen Hintergrundthread für den Download, eine Queue, die den Zustand an die GUI weitergibt, und einen Timer innerhalb der GUI, der die Aktualisierung vornimmt.
Ich denke, wie bei jeder GUI muß man die Ausführung an die Hauptschleife zurückgeben, um eine Aktualisierung zu haben. Das tut aber urlretrieve nicht.
Was Du brauchst ist einen Hintergrundthread für den Download, eine Queue, die den Zustand an die GUI weitergibt, und einen Timer innerhalb der GUI, der die Aktualisierung vornimmt.
- __blackjack__
- User
- Beiträge: 13117
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@MupfSpace: Das darf halt nicht blockieren. Rückruffunktionen bei GUIs dürfen immer nur ganz kurz etwas machen, denn solange sie laufen ist die GUI blockiert. Du könntest das in einen Thread auslagern. Dann wirst Du aber sehr wahrscheinlich nicht einfach einen Callback verwenden können um die Werte in der GUI zu ändern, denn das darf man nur aus dem Thread heraus machen in dem die GUI läuft. Da musst Du dann schauen wie man so etwas in Kivy löst.
Anmerkungen zum Code: Die Namenskonventionen haben sich immer noch nicht geändert – `myApp` sollte mindestens `MyApp` heissen. Auch was Einrückung und Leerzeichensetzung hat sich nichts geändert.
Eine Methode die einfach nur die gleiche Methode auf der Basisklasse mit den gleichen Argumenten aufruft ist überflüssig. Weg mit `__init__()`.
Warum ein Objekt das eine Anwendung repräsentiert aufrufbar sein sollte, und dieser Aufruf dann ausgerechnet einen Ladebalken aktualisiert, ist so gar nicht offensichtlich. Da würde man wirklich besser eine Methode mit einem aussagekräftigen Namen für verwenden. Apropos aussagekräftige Namen: `bn`, `bs`, `cl`, `lb`, `pb` sind das sicher nicht.
Anmerkungen zum Code: Die Namenskonventionen haben sich immer noch nicht geändert – `myApp` sollte mindestens `MyApp` heissen. Auch was Einrückung und Leerzeichensetzung hat sich nichts geändert.
Eine Methode die einfach nur die gleiche Methode auf der Basisklasse mit den gleichen Argumenten aufruft ist überflüssig. Weg mit `__init__()`.
Warum ein Objekt das eine Anwendung repräsentiert aufrufbar sein sollte, und dieser Aufruf dann ausgerechnet einen Ladebalken aktualisiert, ist so gar nicht offensichtlich. Da würde man wirklich besser eine Methode mit einem aussagekräftigen Namen für verwenden. Apropos aussagekräftige Namen: `bn`, `bs`, `cl`, `lb`, `pb` sind das sicher nicht.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Also warum bringt im __init__: super().__init__() nichts allein durch diese Teile wurde der ids Fehler behoben.
Ich habe den Code jezt noch mal besser gemacht:
Okay. Wie genau behebe ich jezt den Fehler mit dem lade Balken.
Ich habe schon verschiedenes versucht und es hat nicht funktioniert. Im Internet habe ich auch nichts gefunden.
Ich habe den Code jezt noch mal besser gemacht:
Code: Alles auswählen
from kivy.app import App
from kivy.lang import Builder
import urllib.request
g=Builder.load_string("""
BoxLayout:
Button:
on_press: app.start_download()
Label:
id: info_label
text:"...%"
ProgressBar:
id: progress_bar
max: 100
""")
class MyApp(App):
def download(self, block_num, block_size, content_length):
percent=int((block_num*block_size)/content_length*100)
self.root.ids.info_label.text=str(percent)+"%"
self.root.ids.progress_bar.value=percent
def build(self):
return g
def start_download(self):
urllib.request.urlretrieve("https://www.python.org/ftp/python/3.7.3/python-3.7.3-embed-amd64.zip","py.zip", self.download)
MyApp().run()
Ich habe schon verschiedenes versucht und es hat nicht funktioniert. Im Internet habe ich auch nichts gefunden.
- __blackjack__
- User
- Beiträge: 13117
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Du suchst den `kivy.clock.mainthread`-Dekorator mit dem man die Ausführung der Rückruffunktion in den Hauptthread verlegen kann.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
so passiert genau das gleiche wie vorher trotz kivy.clock.mainthread:
in der Dokumentation habe ich gelesen das ich mit UrlRequest arbeiten soll, aber da steht nur was von on_succes aber der Ladebanken soll ja nicht wenn es geklappt hat aktualisiert werden sondern während des Downloads.
welcher Fehler befindet sich in meinem Code?
Code: Alles auswählen
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import mainthread
import urllib.request
g=Builder.load_string("""
BoxLayout:
orientation:"vertical"
BoxLayout:
Label:
text:"..%"
id: info_label
ProgressBar:
id: progress_bar
max: 100
Button:
on_press: app.start()
""")
class MyApp(App):
def build(self):
return g
def start(self):
urllib.request.urlretrieve("https://www.python.org/ftp/python/3.7.3/python-3.7.3.exe","download.iregndwas", self.download)
@mainthread
def download(self, block_num,block_size,content_length):
percent=int((block_num*block_size)/content_length*100)
self.root.ids.info_label.text=str(percent)
self.root.ids.progress_bar.value=percent
print(percent)
MyApp().run()
welcher Fehler befindet sich in meinem Code?
- __blackjack__
- User
- Beiträge: 13117
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@MupfSpace: Der Fehler ist immer noch das `urlretrieve()` alles blockiert bis der Download komplett ist. Der Callback ist jetzt thread-sicher, nun müsstest Du halt noch einen Thread für das herunterladen starten.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Jein. Du darfst aus dem Thread keine GUI Objekte manipulieren. Aber ein Thread kann seine Ergebnisse (wie zb den Fortschritt) eben an den mainthread kommunizieren. Kivy kennt dafür wohl diesen decorator, so das du die Methode auch aus einem anderen Thread aufrufen kannst.
So passiert überhaupt gar nichts und ich bekomme noch nicht mal den print...
Warum ist das so und wie kann ich das beheben?
Code: Alles auswählen
from kivy.app import App
from kivy.lang import Builder
from kivy.clock import mainthread
import urllib.request
import threading
g=Builder.load_string("""
BoxLayout:
orientation:"vertical"
BoxLayout:
Label:
text:"..%"
id: info_label
ProgressBar:
id: progress_bar
max: 100
Button:
on_press: app.start()
""")
class MyApp(App):
def build(self):
return g
def start(self):
threading.Thread(target=urllib.request.urlretrieve,args=("https://www.python.org/ftp/python/3.7.3/python-3.7.3.exe","download.iregndwas", self.download))
@mainthread
def download(self, block_num,block_size,content_length):
percent=int((block_num*block_size)/content_length*100)
self.root.ids.info_label.text=str(percent)
self.root.ids.progress_bar.value=percent
print(percent)
MyApp().run()
- __blackjack__
- User
- Beiträge: 13117
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@MupfSpace: Einfach nur in einer Methode die Methode der Basisklasse aufzurufen, mit den gleichen Argumenten, hat keinen Mehrwert. Da passiert vom Effekt her genau das gleiche als wenn es die Methode nicht gäbe, denn dann wird ja beim Aufruf der Methode die aus der Basisklasse genommen. Man hat mit der Methode halt bloss einen Aufruf mehr in der Aufrufhierarchie der aber nichts zusätzliches macht. Also kann man das auch weg lassen. Und sollte man halt auch, denn sonst fragt sich der Leser warum das da steht und ob das Programm an der Stelle fertig ist und nicht noch irgend etwas fehlt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Ich wollte gerade versuchen eine Test-App mit buildozer zu einer apk zu machen.
nach dem ich
eingegebn habe
hat es eine weile gedauert und ich bekam diesen fehler
was kann ich dagegen tun?
nach dem ich
Code: Alles auswählen
buildozer android debug deploy run
hat es eine weile gedauert und ich bekam diesen fehler
Code: Alles auswählen
adrian@adrian-desktop:~$ cd TestApp
adrian@adrian-desktop:~/TestApp$ buildozer android debug deploy run
# Check configuration tokens
# Ensure build layout
# Create directory /home/adrian/.buildozer
# Create directory /home/adrian/.buildozer/cache
# Create directory /home/adrian/TestApp/.buildozer
# Create directory /home/adrian/TestApp/bin
# Create directory /home/adrian/TestApp/.buildozer/applibs
# Create directory /home/adrian/.buildozer/android/platform/android/platform
# Create directory /home/adrian/TestApp/.buildozer/android/platform
# Create directory /home/adrian/TestApp/.buildozer/android/app
# Check configuration tokens
# Read available permissions from api-versions.xml
# Preparing build
# Check requirements for android
# Run 'dpkg --version'
# Cwd None
Debian »dpkg« Paketmanagement-Programm Version 1.19.0.5 (armhf).
Dies ist freie Software; lesen Sie die GNU General Public License in der
Version 2 oder höher für Kopierbedingungen. Es wird KEINE Haftung übernommen.
# Search for Git (git)
# -> found at /usr/bin/git
# Search for Cython (cython)
# -> found at /home/adrian/.local/bin/cython
# Search for Java compiler (javac)
# -> found at /usr/lib/jvm/java-11-openjdk-armhf/bin/javac
# Search for Java keytool (keytool)
# -> found at /usr/lib/jvm/java-11-openjdk-armhf/bin/keytool
# Install platform
# Run 'git clone -b master --single-branch https://github.com/kivy/python-for-android.git python-for-android'
# Cwd /home/adrian/TestApp/.buildozer/android/platform
Cloning into 'python-for-android'...
# Run '/usr/bin/python -m pip install -q --user \'appdirs\' \'colorama>=0.3.3\' \'jinja2\' \'six\' \'enum34; python_version<"3.4"\' \'sh>=1.10; sys_platform!="nt"\' \'pep517\' \'pytoml\' \'virtualenv\''
# Cwd None
# Android ANT is missing, downloading
# Downloading http://archive.apache.org/dist/ant/binaries/apache-ant-1.9.4-bin.tar.gz
# Run 'tar xzf apache-ant-1.9.4-bin.tar.gz'
# Cwd /home/adrian/.buildozer/android/platform/apache-ant-1.9.4
# Apache ANT installation done.
# Android SDK is missing, downloading
# Downloading http://dl.google.com/android/repository/sdk-tools-linux-4333796.zip
# Unpacking Android SDK
# Run 'unzip -q /home/adrian/.buildozer/android/platform/android-sdk/sdk-tools-linux-4333796.zip'
# Cwd /home/adrian/.buildozer/android/platform/android-sdk
# Android SDK tools base installation done.
# Android NDK is missing, downloading
# Downloading https://dl.google.com/android/repository/android-ndk-r17c-linux-x86.zip
# Unpacking Android NDK
# Run 'unzip -q /home/adrian/.buildozer/android/platform/android-ndk-r17c-linux-x86.zip'
# Cwd /home/adrian/.buildozer/android/platform
[/home/adrian/.buildozer/android/platform/android-ndk-r17c-linux-x86.zip]
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of /home/adrian/.buildozer/android/platform/android-ndk-r17c-linux-x86.zip or
/home/adrian/.buildozer/android/platform/android-ndk-r17c-linux-x86.zip.zip, and cannot find /home/adrian/.buildozer/android/platform/android-ndk-r17c-linux-x86.zip.ZIP, period.
# Command failed: unzip -q /home/adrian/.buildozer/android/platform/android-ndk-r17c-linux-x86.zip
# ENVIRONMENT:
# MATE_DESKTOP_SESSION_ID = 'this-is-deprecated'
# XDG_GREETER_DATA_DIR = '/var/lib/lightdm-data/adrian'
# XDG_CURRENT_DESKTOP = 'MATE'
# XDG_SESSION_TYPE = 'x11'
# LOGNAME = 'adrian'
# USER = 'adrian'
# PATH = '/home/adrian/.buildozer/android/platform/apache-ant-1.9.4/bin:/home/adrian/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin'
# XDG_VTNR = '7'
# HOME = '/home/adrian'
# DISPLAY = ':0'
# SSH_AGENT_PID = '1614'
# LANG = 'de_DE.UTF-8'
# MANAGERPID = '1166'
# SHELL = '/bin/bash'
# XDG_SESSION_PATH = '/org/freedesktop/DisplayManager/Session0'
# XAUTHORITY = '/home/adrian/.Xauthority'
# JOURNAL_STREAM = '9:33972'
# SESSION_MANAGER = 'local/adrian-desktop:@/tmp/.ICE-unix/1188,unix/adrian-desktop:/tmp/.ICE-unix/1188'
# XDG_DATA_DIRS = '/usr/share/mate:/usr/local/share:/usr/share:/var/lib/snapd/desktop'
# QT_QPA_PLATFORMTHEME = 'gtk2'
# QT_ACCESSIBILITY = '1'
# WINDOWID = '52428806'
# GTK_OVERLAY_SCROLLING = '0'
# IM_CONFIG_PHASE = '1'
# GPG_AGENT_INFO = '/run/user/1000/gnupg/S.gpg-agent:0:1'
# QT_AUTO_SCREEN_SCALE_FACTOR = '0'
# INVOCATION_ID = '4975065039d84d9f84f6efe8716def4f'
# XDG_SESSION_DESKTOP = 'mate'
# XDG_RUNTIME_DIR = '/run/user/1000'
# QT_SCALE_FACTOR = '1'
# SSH_AUTH_SOCK = '/run/user/1000/keyring/ssh'
# TERM = 'xterm'
# VTE_VERSION = '5202'
# GDMSESSION = 'mate'
# XDG_SEAT_PATH = '/org/freedesktop/DisplayManager/Seat0'
# DBUS_STARTER_BUS_TYPE = 'session'
# LESSOPEN = '| /usr/bin/lesspipe %s'
# XDG_SESSION_ID = 'c2'
# DBUS_SESSION_BUS_ADDRESS = 'unix:path=/run/user/1000/bus,guid=1de859e84ac47caa38b0d51c5cf179cd'
# _ = '/usr/local/bin/buildozer'
# DESKTOP_SESSION = 'mate'
# LESSCLOSE = '/usr/bin/lesspipe %s %s'
# GTK_MODULES = 'appmenu-gtk-module:gail:atk-bridge:canberra-gtk-module'
# UBUNTU_MENUPROXY = '1'
# OLDPWD = '/home/adrian'
# DBUS_STARTER_ADDRESS = 'unix:path=/run/user/1000/bus,guid=1de859e84ac47caa38b0d51c5cf179cd'
# GDM_LANG = 'de_DE'
# LANGUAGE = 'de_DE'
# SHLVL = '1'
# PWD = '/home/adrian/TestApp'
# COLORTERM = 'truecolor'
# XDG_CONFIG_DIRS = '/etc/xdg/xdg-mate:/etc/xdg'
# LS_COLORS = 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'
# XDG_SEAT = 'seat0'
#
# Buildozer failed to execute the last command
# The error might be hidden in the log above this error
# Please read the full log, and search for it before
# raising an issue with buildozer itself.
# In case of a bug report, please add a full log with log_level = 2
adrian@adrian-desktop:~/TestApp$
Hast du schon einmal versucht danach zu googeln?
Es gibt nur 2 Treffer, wenn man nach dem Dateinamen such. Diesen Beitrag im Forum und eine Diskussion in eine Google-Gruppe. Dort stellt sich heraus: Die gesucht Datei existiert nicht, weil buildozer nicht auf 32-bit Systemen bauen kann.
Falls du also ein 32-bit Linux installiert hast, geht es nicht.
Es gibt nur 2 Treffer, wenn man nach dem Dateinamen such. Diesen Beitrag im Forum und eine Diskussion in eine Google-Gruppe. Dort stellt sich heraus: Die gesucht Datei existiert nicht, weil buildozer nicht auf 32-bit Systemen bauen kann.
Falls du also ein 32-bit Linux installiert hast, geht es nicht.