当鼠标光标在窗口

时间:2018-06-01 06:18:23

标签: python windows kivy frame-rate

我正在为爱好编写一个卡拉OK软件,可下载YouTube视频,保存在数据库中并放入播放列表。代码是用Python编写的,我在Windows 10 64位机器上使用kivy作为用户界面。我搜索并搜索并搜索了互联网,找不到任何有类似问题的人:如果我只是将鼠标光标悬停在程序的kivy窗口上,界面会开始出现口吃,fps会下降很多。

我只会放置Widget类,因为代码太大了:

class InterfaceWidget(BoxLayout):

    #Definitions for properties of the graphic interface.
    FONT_NAME_1 = StringProperty('NotoSansCJKjp-Medium.otf')
    FONT_NAME_2 = StringProperty('NotoSansMonoCJKjp-Regular.otf')
    current_title_prop = ObjectProperty(None)
    current_artist_prop = ObjectProperty(None)
    playlist_list_prop = ObjectProperty(None)
    results_list_prop = ObjectProperty(None)
    search_bar_prop = ObjectProperty(None)
    play_button_prop = ObjectProperty(None)
    stop_button_prop = ObjectProperty(None)
    restart_button_prop = ObjectProperty(None)
    remove_button_prop = ObjectProperty(None)
    search_title_button_prop = ObjectProperty(None)
    search_artist_button_prop = ObjectProperty(None)
    current_time_prop = ObjectProperty(None)
    current_duration_prop = ObjectProperty(None)
    youtube_status_prop = ObjectProperty(None)
    counter_prop = ObjectProperty(None)

    current_title = ''
    current_artist = ''
    current_time = ''
    current_duration = ''
    results_list = ''
    search_bar = ''
    playlist_list = ''
    youtube_status = ''

    current_path = ''
    category_state = None
    processes_started = False
    already_focused = False

    karaoke = KaraokeGuts()
    i = 0
    remaining_time = WAIT_TO_NEXT_SONG

    changed = {
                'title': False, 
                'artist': True,
                'current_time': False,
                'length': False,
                'queue': True,
                'playlist': False,
                'download_status': False,
                'search_bar': False,
                'search_result': False,
                'buttons': True,
              }

    def update(self, dt):
        print(dt)###MAIN LOOP###
        if self.processes_started == False:
            self.configure_threads() 
            self.processes_started = True

        self.next_music()
        self.get_search_results()
        self.get_add_title()

        if self.changed['title'] == True:
            self.current_title_prop.text = self.update_title()
            self.changed['title'] = False

        if self.changed['artist'] == True:
            self.current_artist_prop.text = self.update_artist()
            self.changed['artist'] = False

        self.current_time_prop.text = self.update_time()

        if self.changed['length'] == True:
            self.current_duration_prop.text = self.update_duration()
            self.changed['length'] = False

        if self.changed['queue'] == True:
            self.counter_prop.text = self.update_counter()
            self.changed['queue'] = False    

        if self.changed['playlist'] == True: 
            self.playlist_list_prop.text = self.update_playlist()
            self.changed['playlist'] = False

        self.youtube_status_prop.text = self.update_download_status()

        if self.changed['search_bar'] == True:
            self.search_bar_prop.text = self.update_search_bar()
            self.changed['search_bar'] = False

        if self.changed['search_result'] == True:
            self.results_list_prop.text == self.update_results_list()
            self.changed['search_result'] = False

        if self.changed['buttons'] == True:
            self.update_buttons()
            self.changed['buttons'] = False

         ###

    ###DEFINITION OF SYNCRONOUS UPDATES METHODS###
    def update_title(self):
        if self.karaoke.playing in ('playing', 'paused'):
            return self.current_title
        else:
            return ''



    def update_artist(self):
        if self.karaoke.playing in ('playing', 'paused'):
            return self.current_artist
        else:
            if self.karaoke.counter == 0:
                return 'Fila vazia: adicione uma música para começar'

    def update_duration(self):
        if self.karaoke.playing in ('playing', 'paused'):
            return self.current_duration
        else:
            return ''

    def update_time(self):
        if self.karaoke.playing in ('playing', 'paused'):
            self.q_put.put(['','get_time'])
            ctime = self.q_get.get()
            self.current_time = self.karaoke.format_seconds(float(ctime))
        else:
            self.current_time = ''
        return self.current_time

    def update_counter(self):
        return str(self.karaoke.counter)

    def update_download_status(self):
        download_status = self.karaoke.downloaded_percent
        if download_status == None:
            self.youtube_status = ''
        elif download_status == 'ERROR':
            self.youtube_status = 'Um erro ocorreu ao baixar o vídeo =('
        elif download_status == 'UNKNOWN_FILESIZE':
            self.youtube_status = 'Baixando, mas tamanho de arquivo desconhecido'
        elif download_status == 'FINISHED':
            self.youtube_status = 'Vídeo baixado!'
        else:
            self.youtube_status = 'Baixando: {:2.1f}%'.format(download_status)

        #return self.youtube_status
        self.i += 1
        return str(self.i)

    def update_playlist(self):
        playlist_aux2 = ''
        for i in self.karaoke.playlist:
            playlist_aux = playlist_aux2 + '[size=20][color=#FFFFFF][font=NotoSansCJKjp-Medium.otf]' + escape_markup(i['title']) + '[/color][/size][/font]' + '\n'
            playlist_aux = playlist_aux + '[size=15][color=#c5cacd][font=NotoSansCJKjp-Medium.otf]' + escape_markup(i['artist']) + ' ' +  escape_markup('[') + self.karaoke.format_seconds(i['length']) + escape_markup(']') + '[/color][/size][/font]' + '\n'
            playlist_aux2 = playlist_aux
        self.playlist_list = playlist_aux2
        return self.playlist_list

    def update_search_bar(self):
        return self.search_bar

    def update_results_list(self):
        return self.results_list

    def update_buttons(self):
        if self.karaoke.playing not in ('playing','paused'):
            self.play_button_prop.disabled = True
            self.stop_button_prop.disabled = True
            self.restart_button_prop.disabled = True
        else:
            self.play_button_prop.disabled = False
            self.stop_button_prop.disabled = False
            self.restart_button_prop.disabled = False

        if self.karaoke.counter == 0:
            self.remove_button_prop.disabled = True
        else:
            self.remove_button_prop.disabled = False

    ###DEFINITIONS OF SYNCRONOUS NON-UPDATE METHODS###
    def next_music(self):
        if self.karaoke.counter != 0 and self.karaoke.playing not in ('playing','paused'):
            self.q_put.put([self.karaoke.playlist[0]['path'], 'play'])
            self.current_title = self.karaoke.playlist[0]['title']
            self.current_artist = self.karaoke.playlist[0]['artist']
            self.current_duration = self.karaoke.format_seconds(float(self.karaoke.playlist[0]['length']))
            self.current_time = '00:00'
            self.remove_title()
            self.karaoke.playing = 'playing'
            self.changed.update(title = True, artist = True, current_time = True, length = True, playlist = True, queue = True, buttons = True)

    def get_search_results(self):
        try:
            result = self.q_search_get.get(block = False)
            if result == 'SEARCH_NOT_FOUND':
                self.results_list = 'Busca não encontrada, tente outro termo.'
            else:
                results_aux = self.results_list + '[size=15][color=#FFFFFF][font=NotoSansCJKjp-Medium.otf]' + escape_markup(result['title']) + '[/color][/size][/font]' + '\n'
                results_aux = results_aux + '[size=12][color=#c5cacd][font=NotoSansCJKjp-Medium.otf]' + escape_markup(result['artist']) + '[/color][/size][/font]' + '\n'
                self.results_list = results_aux
            self.changed['search_result'] = True
        except thq.Empty:
            pass

    def get_add_title(self):
        try:
            metadata = self.q_youtube_get.get(block = False)
            if metadata != 'ERROR':
                self.karaoke.playlist.append(metadata)
                self.karaoke.counter += 1
                self.changed.update(queue = True, playlist = True)
            # else:
            #     self.youtube_status = 'Erro ocorreu ao baixar o vídeo.'
            #     changed
        except:
            pass

    ###DEFINITIONS OF ASYNCRONOUS METHODS##
    def search(self):
        if self.search_bar_prop.text.startswith('https://') == False and self.search_bar_prop.text != '':
            self.results_list = ''
            if self.search_artist_button_prop.state == 'normal' and self.search_title_button_prop.state == 'down':
                input_text = {'fieldname': 'title', 'search_term': self.search_bar.text}
                self.q_search_put.put(input_text)
            elif self.search_artist_button_prop.state == 'down' and self.search_title_button_prop.state == 'normal':
                input_text = {'fieldname': 'title', 'search_term': self.search_bar.text}
                self.q_search_put.put(input_text)            
        elif self.search_bar_prop.text.startswith('https://') == True and (self.search_artist_button_prop.state == 'down' or self.search_title_button_prop.state == 'down'):
            self.results_list = '[size=15][color=#FFFFFF][font=NotoSansCJKjp-Medium.otf]Desative as opções de busca antes de adicionar um link.[/color][/size][/font]'
        elif self.search_bar_prop.text == '':
            self.results_list = ''
        self.changed['search_result'] = True

    def search_state(self, category):
        if category == 'title':
            self.search_artist_button_prop.state = 'normal' 

        if category == 'artist':
            self.search_title_button_prop.state = 'normal' 

    def add_title(self):
        self.q_youtube_put.put(self.search_bar_prop.text, block = False)
        self.search_bar_prop.focus = False
        self.search_bar_prop.do_cursor_movement('cursor_home')
        self.already_focused = False
        self.search_bar = 'Digite um termo de busca ou cole um link'
        self.changed.update(search_bar = True, download_status = True)

    def remove_title(self):
        self.karaoke.remove_title()
        self.changed.update(queue = True, playlist = True)

    #The following methods executes on VLC separate process.
    def stop(self):
        self.q_put.put(['','stop'])
        self.q_put.put(['','get_state'])
        state = self.q_get.get()
        self.karaoke.playing = state
        self.changed.update(title = True, artist = True, current_time = True, current_duration = True, playlist = True, buttons = True)

    def play(self):
        self.q_put.put(['','get_state'])
        self.karaoke.playing = self.q_get.get()

        if self.karaoke.playing == 'paused':
            self.q_put.put(['','play'])
            self.play_button_prop.background_normal = "buttons\\pause.png"
            self.play_button_prop.background_down = "buttons\\paused_clicked.png"

            print(1)
        else:
            self.q_put.put(['','pause'])
            self.play_button_prop.background_normal = "buttons\\play.png"
            self.play_button_prop.background_down = "buttons\\play_clicked.png"

            print(2)

    def restart(self):
        self.q_put.put([self.current_path,'play'])

    def search_bar_focused(self, focus):
        if focus == True and self.already_focused == False:
            self.search_bar_prop.text = ''
            self.already_focused = True

    ###EXECUTED ONLY ONCE METHOD###
    def configure_threads(self):
        if self.processes_started == False:
            self.media = Media()
            self.q_get = mp.Queue()
            self.q_put = mp.Queue()
            self.vlc_process = mp.Process(target = self.media.vlc, args = (self.q_put, self.q_get,))
            self.vlc_process.daemon = True
            self.vlc_process.start()

            self.q_youtube_get = thq.Queue()
            self.q_youtube_put = thq.Queue()
            self.th_youtube = th.Thread(target = self.karaoke.add_title, args = (self.q_youtube_put, self.q_youtube_get,))
            self.th_youtube.daemon = False
            self.th_youtube.start()

            self.q_search_get = thq.Queue()
            self.q_search_put = thq.Queue()
            self.th_search = th.Thread(target = self.karaoke.yield_search_to_queue, args = (self.q_search_put, self.q_search_get,))
            self.th_search.daemon = True
            self.th_search.start()

            self.processes_started = True

update方法由Clock.schedule_interval(iw.update, 0)安排。每个属性都是UI中的交互式小部件(属性太多?)。

编辑:这是我的kivy日志:

[INFO   ] [Kivy        ] v1.10.0
[INFO   ] [Python      ] v3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)]
[INFO   ] [Factory     ] 194 symbols loaded
[DEBUG  ] [Cache       ] register <kv.lang> with limit=None, timeout=None
[DEBUG  ] [Cache       ] register <kv.image> with limit=None, timeout=60
[DEBUG  ] [Cache       ] register <kv.atlas> with limit=None, timeout=None
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_pil, img_gif (img_ffpyplayer ignored)
[DEBUG  ] [Cache       ] register <kv.texture> with limit=1000, timeout=60
[DEBUG  ] [Cache       ] register <kv.shader> with limit=1000, timeout=3600
[DEBUG  ] [App         ] Loading kv <.\karaoke.kv>
[DEBUG  ] [App         ] kv <.\karaoke.kv> not found
[INFO   ] [OSC         ] using <thread> for socket
[INFO   ] [Window      ] Provider: sdl2
[INFO   ] [GL          ] Using the "OpenGL" graphics system
[INFO   ] [GL          ] GLEW initialization succeeded
[DEBUG  ] [GL          ] available extensions: b'GL_AMDX_debug_output GL_AMDX_vertex_shader_tessellator GL_AMD_conservative_depth GL_AMD_debug_output GL_AMD_depth_clamp_separate GL_AMD_draw_buffers_blend GL_AMD_multi_draw_indirect GL_AMD_name_gen_delete GL_AMD_performance_monitor GL_AMD_pinned_memory GL_AMD_query_buffer_object GL_AMD_sample_positions GL_AMD_seamless_cubemap_per_texture GL_AMD_shader_stencil_export GL_AMD_shader_trace GL_AMD_texture_cube_map_array GL_AMD_texture_texture4 GL_AMD_transform_feedback3_lines_triangles GL_AMD_vertex_shader_layer GL_AMD_vertex_shader_tessellator GL_AMD_vertex_shader_viewport_index GL_ARB_ES2_compatibility GL_ARB_ES3_1_compatibility GL_ARB_ES3_compatibility GL_ARB_arrays_of_arrays GL_ARB_base_instance GL_ARB_blend_func_extended GL_ARB_buffer_storage GL_ARB_clear_buffer_object GL_ARB_clear_texture GL_ARB_clip_control GL_ARB_color_buffer_float GL_ARB_compatibility GL_ARB_compressed_texture_pixel_storage GL_ARB_compute_shader GL_ARB_conditional_render_inverted GL_ARB_conservative_depth
GL_ARB_copy_buffer GL_ARB_copy_image GL_ARB_cull_distance GL_ARB_debug_output GL_ARB_depth_buffer_float GL_ARB_depth_clamp GL_ARB_depth_texture GL_ARB_derivative_control GL_ARB_direct_state_access GL_ARB_draw_buffers GL_ARB_draw_buffers_blend GL_ARB_draw_elements_base_vertex GL_ARB_draw_indirect GL_ARB_draw_instanced GL_ARB_enhanced_layouts GL_ARB_explicit_attrib_location GL_ARB_explicit_uniform_location GL_ARB_fragment_coord_conventions GL_ARB_fragment_layer_viewport GL_ARB_fragment_program GL_ARB_fragment_program_shadow GL_ARB_fragment_shader GL_ARB_framebuffer_no_attachments GL_ARB_framebuffer_object GL_ARB_framebuffer_sRGB GL_ARB_geometry_shader4 GL_ARB_get_program_binary GL_ARB_get_texture_sub_image GL_ARB_gpu_shader5 GL_ARB_gpu_shader_fp64 GL_ARB_half_float_pixel GL_ARB_half_float_vertex GL_ARB_imaging GL_ARB_instanced_arrays GL_ARB_internalformat_query GL_ARB_internalformat_query2 GL_ARB_invalidate_subdata GL_ARB_map_buffer_alignment GL_ARB_map_buffer_range GL_ARB_multi_bind GL_ARB_multi_draw_indirect GL_ARB_multisample GL_ARB_multitexture GL_ARB_occlusion_query GL_ARB_occlusion_query2 GL_ARB_pipeline_statistics_query GL_ARB_pixel_buffer_object GL_ARB_point_parameters GL_ARB_point_sprite GL_ARB_program_interface_query GL_ARB_provoking_vertex GL_ARB_query_buffer_object GL_ARB_robust_buffer_access_behavior GL_ARB_sample_shading GL_ARB_sampler_objects GL_ARB_seamless_cube_map GL_ARB_seamless_cubemap_per_texture GL_ARB_separate_shader_objects GL_ARB_shader_atomic_counters GL_ARB_shader_bit_encoding GL_ARB_shader_image_load_store GL_ARB_shader_image_size GL_ARB_shader_objects GL_ARB_shader_precision GL_ARB_shader_stencil_export GL_ARB_shader_storage_buffer_object GL_ARB_shader_subroutine GL_ARB_shader_texture_image_samples GL_ARB_shader_texture_lod GL_ARB_shading_language_100 GL_ARB_shading_language_420pack GL_ARB_shading_language_packing GL_ARB_shadow GL_ARB_shadow_ambient GL_ARB_stencil_texturing GL_ARB_sync GL_ARB_tessellation_shader GL_ARB_texture_barrier GL_ARB_texture_border_clamp GL_ARB_texture_buffer_object GL_ARB_texture_buffer_object_rgb32 GL_ARB_texture_buffer_range GL_ARB_texture_compression GL_ARB_texture_compression_bptc GL_ARB_texture_compression_rgtc GL_ARB_texture_cube_map GL_ARB_texture_cube_map_array GL_ARB_texture_env_add GL_ARB_texture_env_combine GL_ARB_texture_env_crossbar GL_ARB_texture_env_dot3 GL_ARB_texture_float GL_ARB_texture_gather GL_ARB_texture_mirror_clamp_to_edge GL_ARB_texture_mirrored_repeat GL_ARB_texture_multisample GL_ARB_texture_non_power_of_two GL_ARB_texture_query_levels GL_ARB_texture_query_lod GL_ARB_texture_rectangle GL_ARB_texture_rg GL_ARB_texture_rgb10_a2ui GL_ARB_texture_snorm GL_ARB_texture_stencil8 GL_ARB_texture_storage GL_ARB_texture_storage_multisample GL_ARB_texture_swizzle GL_ARB_texture_view GL_ARB_timer_query GL_ARB_transform_feedback2 GL_ARB_transform_feedback3 GL_ARB_transform_feedback_instanced GL_ARB_transform_feedback_overflow_query GL_ARB_transpose_matrix GL_ARB_uniform_buffer_object GL_ARB_vertex_array_bgra GL_ARB_vertex_array_object GL_ARB_vertex_attrib_64bit GL_ARB_vertex_attrib_binding GL_ARB_vertex_buffer_object GL_ARB_vertex_program GL_ARB_vertex_shader GL_ARB_vertex_type_10f_11f_11f_rev GL_ARB_vertex_type_2_10_10_10_rev GL_ARB_viewport_array GL_ARB_window_pos GL_ATI_draw_buffers GL_ATI_envmap_bumpmap GL_ATI_fragment_shader GL_ATI_separate_stencil GL_ATI_texture_compression_3dc GL_ATI_texture_env_combine3 GL_ATI_texture_float GL_ATI_texture_mirror_once GL_EXT_abgr GL_EXT_bgra GL_EXT_bindable_uniform GL_EXT_blend_color GL_EXT_blend_equation_separate GL_EXT_blend_func_separate GL_EXT_blend_minmax GL_EXT_blend_subtract GL_EXT_compiled_vertex_array GL_EXT_copy_buffer GL_EXT_copy_texture GL_EXT_direct_state_access GL_EXT_draw_buffers2 GL_EXT_draw_instanced GL_EXT_draw_range_elements GL_EXT_fog_coord GL_EXT_framebuffer_blit GL_EXT_framebuffer_multisample GL_EXT_framebuffer_object GL_EXT_framebuffer_sRGB GL_EXT_geometry_shader4 GL_EXT_gpu_program_parameters GL_EXT_gpu_shader4 GL_EXT_histogram GL_EXT_multi_draw_arrays GL_EXT_packed_depth_stencil GL_EXT_packed_float GL_EXT_packed_pixels GL_EXT_pixel_buffer_object GL_EXT_point_parameters GL_EXT_polygon_offset_clamp GL_EXT_provoking_vertex GL_EXT_rescale_normal GL_EXT_secondary_color GL_EXT_separate_specular_color GL_EXT_shader_image_load_store GL_EXT_shader_integer_mix GL_EXT_shadow_funcs GL_EXT_stencil_wrap GL_EXT_subtexture GL_EXT_texgen_reflection GL_EXT_texture3D GL_EXT_texture_array GL_EXT_texture_buffer_object GL_EXT_texture_compression_bptc GL_EXT_texture_compression_latc GL_EXT_texture_compression_rgtc GL_EXT_texture_compression_s3tc GL_EXT_texture_cube_map GL_EXT_texture_edge_clamp GL_EXT_texture_env_add GL_EXT_texture_env_combine GL_EXT_texture_env_dot3 GL_EXT_texture_filter_anisotropic GL_EXT_texture_integer GL_EXT_texture_lod GL_EXT_texture_lod_bias GL_EXT_texture_mirror_clamp GL_EXT_texture_object GL_EXT_texture_rectangle GL_EXT_texture_sRGB GL_EXT_texture_sRGB_decode GL_EXT_texture_shared_exponent GL_EXT_texture_snorm GL_EXT_texture_storage GL_EXT_texture_swizzle GL_EXT_timer_query GL_EXT_transform_feedback GL_EXT_vertex_array GL_EXT_vertex_array_bgra GL_EXT_vertex_attrib_64bit
GL_IBM_texture_mirrored_repeat GL_KHR_context_flush_control GL_KHR_debug GL_KHR_robust_buffer_access_behavior GL_KHR_robustness GL_KTX_buffer_region GL_NV_blend_square GL_NV_conditional_render GL_NV_copy_depth_to_color GL_NV_copy_image GL_NV_depth_buffer_float GL_NV_explicit_multisample GL_NV_float_buffer GL_NV_half_float GL_NV_primitive_restart GL_NV_texgen_reflection GL_NV_texture_barrier GL_OES_EGL_image GL_SGIS_generate_mipmap GL_SGIS_texture_edge_clamp GL_SGIS_texture_lod GL_SUN_multi_draw_arrays GL_WIN_swap_hint WGL_EXT_swap_control'
[DEBUG  ] [GL          ] glShaderBinary is not available
[INFO   ] [GL          ] Backend used <glew>
[INFO   ] [GL          ] OpenGL version <b'4.5.13399 Compatibility Profile Context 15.201.1151.1008'>
[INFO   ] [GL          ] OpenGL vendor <b'ATI Technologies Inc.'>
[INFO   ] [GL          ] OpenGL renderer <b'AMD Radeon HD 5800 Series'>
[INFO   ] [GL          ] OpenGL parsed version: 4, 5
[INFO   ] [GL          ] Shading version <b'4.40'>
[INFO   ] [GL          ] Texture max size <16384>
[INFO   ] [GL          ] Texture max units <18>
[DEBUG  ] [Shader      ] Fragment compiled successfully
[DEBUG  ] [Shader      ] Vertex compiled successfully
[DEBUG  ] [ImageSDL2   ] Load <E:\Python364\lib\site-packages\kivy\data\glsl\default.png>
[INFO   ] [Window      ] auto add sdl2 input provider
[INFO   ] [Text        ] Provider: sdl2
[DEBUG  ] [Modules     ] Start <monitor> with config {}
[DEBUG  ] [Resource    ] add <C:\WINDOWS\Fonts> in path list
[DEBUG  ] [Resource    ] add <E:\Python364\lib\site-packages\kivy\data\fonts> in path list
[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked
[DEBUG  ] [Cache       ] register <textinput.label> with limit=None, timeout=60.0
[DEBUG  ] [Cache       ] register <textinput.width> with limit=None, timeout=60.0
[DEBUG  ] [Atlas       ] Load <E:\Python364\lib\site-packages\kivy\data\images\defaulttheme.atlas>
[DEBUG  ] [Atlas       ] Need to load 1 images
[DEBUG  ] [Atlas       ] Load <E:\Python364\lib\site-packages\kivy\data\images\defaulttheme-0.png>
[DEBUG  ] [ImageSDL2   ] Load <E:\Python364\lib\site-packages\kivy\data\images\defaulttheme-0.png>
[INFO   ] [GL          ] NPOT texture support is available
[DEBUG  ] [Base        ] Create provider from mouse
[DEBUG  ] [Base        ] Create provider from wm_touch
[DEBUG  ] [Base        ] Create provider from wm_pen
[INFO   ] [Base        ] Start application main loop
[DEBUG  ] [ImageSDL2   ] Load <F:\karaoke\buttons\restart_disabled.png>
[DEBUG  ] [ImageSDL2   ] Load <F:\karaoke\buttons\stop_disabled.png>
[DEBUG  ] [ImageSDL2   ] Load <F:\karaoke\buttons\pause_disabled.png>
[DEBUG  ] [ImageSDL2   ] Load <F:\karaoke\buttons\remove_disabled.png>
[DEBUG  ] [ImageSDL2   ] Load <F:\karaoke\buttons\add.png>
[DEBUG  ] [ImageSDL2   ] Load <F:\karaoke\buttons\search_artist.png>
[DEBUG  ] [ImageSDL2   ] Load <F:\karaoke\buttons\search_music.png>
[INFO   ] [Kivy        ] v1.10.0
[INFO   ] [Python      ] v3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:54:40) [MSC v.1900 64 bit (AMD64)]
[INFO   ] [Factory     ] 194 symbols loaded
[DEBUG  ] [Cache       ] register <kv.lang> with limit=None, timeout=None
[DEBUG  ] [Cache       ] register <kv.image> with limit=None, timeout=60
[DEBUG  ] [Cache       ] register <kv.atlas> with limit=None, timeout=None
[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_pil, img_gif (img_ffpyplayer ignored)
[DEBUG  ] [Cache       ] register <kv.texture> with limit=1000, timeout=60
[DEBUG  ] [Cache       ] register <kv.shader> with limit=1000, timeout=3600

最初我认为update应该受到指责,因为我使用的是线程和队列,但我使用perf_counter()来测量循环开始和结束之间的时间,所有措施都是低于1毫秒。另外,我计算fps计算计数器在1秒循环中递增的次数,并输出到标签小部件(考虑到1个循环= 1帧,为了我的目的,也许它与我们知道的fps不同) )。当鼠标未在窗口上方时,fps> 100;在窗口内,如果我只是让光标停下来,fps保持&gt;但是,如果我在窗口内移动光标,fps会下降,如果我在窗口上有更新,它会断断续续。在最坏的情况下,如果我不断移动鼠标光标,则fps会低于5. kivy的监视器模块的变化几乎与“my fps”相同,在最坏的情况下降至1以下。另一个例子,如果我在我的UI中的TextInput小部件中键入文本,这些字母将看起来像一个“旧的和慢的计算机”,最近显示,虽然键击没有丢失(看起来像缓冲区在内部工作)。

我只能得出结论知道某些东西阻挡了我的循环,可能是一些Kivy隐藏的例程,但我不能确定。我该如何解决这个问题?

感谢。

0 个答案:

没有答案