Kivy не отвечает и не может изменить текст в текстовом поле - PullRequest
0 голосов
/ 30 апреля 2020

Так что это часть моего кода, и теоретически он должен работать хорошо, потому что я не мог повторить проблему где-либо еще.

Проблема в том, что хотя print(string) работает очень хорошо и печатает по порядку, когда я пытаюсь создать интерфейс kivy и вместо этого печатаю результаты на textbox, интерфейс работает на мгновение, затем становится все медленнее, после чего Window сообщает мне, что программа не отвечает. Но если я посмотрю на print результаты, они работают просто отлично.

Также, когда я жду, когда программа завершит sh, когда она завершится, она выплевывает весь текст в один большой куча, а затем заканчивается.

Так есть ли способ textbox распечатывать результаты в том же порядке, что и обычный print будет работать?

ex)

обычная печать: print('hello')

печать текстового поля: self.work.text += '\nhello'

PS Если вам необходимо знать функции, которые используются в этом коде, пожалуйста, спросите

Python код

import kivy
from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.textinput import TextInput
from kivy.uix.button import Button
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.core.window import Window
from kivy.uix.togglebutton import ToggleButton
Window.clearcolor = (1, 1, 1, 1)
from kivy.uix.popup import Popup
from datetime import date
import requests
from bs4 import BeautifulSoup
import sys
import urllib.request
import urllib.parse
import re
import os
import time
from pytube import YouTube
from pydub import AudioSegment
AudioSegment.converter = "/FFmpeg/bin/ffmpeg.exe"
import eyed3

############################### functions #########################################

just some functions that work

################################################################################################################
class MyGrid(Widget):
    # url = ObjectProperty(None)
    # mod = ObjectProperty(None)
    # submit = ObjectProperty(None)

    def submit(self):

        self.work.text='starting...'

        if self.mod.state=='down':
            info=get_name_list(self.url.text,'single')
            print(info)
            self.high_audio(info)

        if self.mod.state=='normal':
            info=get_name_list(self.url.text,'playlist')
            print(info)
            self.high_audio(info)



    def high_audio(self,song_album_artist_list):

        for item in song_album_artist_list:
            song = str(item[0])
            artist_name = str(item[1])
            album = str(item[2])

            print(song+" : "+artist_name+" : "+album)
            self.work.text += song+" : "+artist_name+" : "+album
            print('............................')

            youtube_url=get_top_url(song,artist_name)

            # print(youtube_url)

            download_high_audio(youtube_url,song)

            convert(youtube_url,song)


            self.work.text += 'converting finished, applying metadata...'

            song_file = eyed3.load(output_path+"/"+song+".mp3")
            song_file.tag.artist = artist_name
            song_file.tag.album = album

            self.work.text += 'searching music...'

            art=get_music_inf(song,artist_name,album)

            if art=='':
                art=get_album_art_high(song,artist_name,album)

            if art=='':
                art=get_album_art_low(song,artist_name,album)

            if art=='':
                self.work.text += '****************************No artwork availiable****************************'

            self.work.text+=art

            try:
                response = requests.get(art)
                imagedata = response.content
                song_file.tag.images.set(3,imagedata,"image/png",u"None")
                song_file.tag.save()
            except requests.exceptions.MissingSchema:
                pass



            song_file.tag.save()

            self.work.text+='done'




class MyApp(App):
    def build(self):
        return MyGrid()



if __name__ == "__main__":
    MyApp().run()

код Киви


<RoundButton@Button>:
    background_color: 0,0,0,0
    canvas.before:
        Color:
            rgba: (.7,.7,.7,0.7) if self.state=='normal' else (0.82,0.96,0.92,1)
        RoundedRectangle:
            pos: self.pos
            size: self.size
            radius: [10,]

<RoundToggleButton@ToggleButton>:
    background_color: 0,0,0,0
    canvas.before:
        Color:
            rgba: (.7,.7,.7,0.7) if self.state=='normal' else (0.82,0.96,0.92,1)
        RoundedRectangle:
            pos: self.pos
            size: self.size
            radius: [10,]

<MyTextInput@TextInput>:
    background_normal: "textinput.png"
    background_color: (0.82,0.96,0.92,1) if self.focus else (1,1,1,0.5)

<MyGrid>:

    url:url
    mod:mod
    work:work

    FloatLayout:

        size: root.width, root.height


        MyTextInput:
            id: url
            pos_hint: {"x": 0.25, "top":0.85}
            size_hint: 0.5,0.1
            text:"Paste url"

        RoundButton:
            text: "submit"
            on_press: root.submit()
            pos_hint: {"x":0.4, "top":0.7}
            size_hint: 0.2,0.1

        RoundToggleButton:
            id: mod
            text: 'Playlist' if self.state=='normal' else 'Single'
            pos_hint: {"x":0.4, "top":0.45}
            size_hint: 0.2,0.1

        MyTextInput:
            id:work
            text:''
            pos_hint: {"x": 0.25,"top":0.3}
            size_hint: 0.5,0.25

Может кто-нибудь сказать мне, в чем проблема? Я потратил почти день, пытаясь понять это: (

1 Ответ

1 голос
/ 30 апреля 2020

Когда вы запускаете print(), на самом деле происходит вывод текста программой в виде потока байтов, и затем какая-то другая программа (например, ваш терминал) может проверить этот поток и отобразить его в виде символов. Неважно, что еще делает программа Python, потому что этот поток байтов является внешним по отношению к остальной части его потока управления.

Когда вы рисуете текст с помощью gui, модель отличается - установка текста TextInput говорит ему, что делать, но фактическая отрисовка текста также является частью потока программы.

Когда вы запускаете много кода одновременно, вы блокируете этот поток, поэтому нет Код Kivy для обновления gui выполняется между запуском вашей функции и завершением всего кода, поэтому функция возвращает.

Решение состоит в том, чтобы не блокировать gui. Либо разделите вашу функцию на куски, каждый из которых вызывает следующий, используя Clock.schedule_once, или запустите ваш продолжительный вызов функции в потоке.

...