基维:弹出窗口不显示

2024-04-19 12:07:45 发布

您现在位置:Python中文网/ 问答频道 /正文

虽然我的示例代码不是最短的,但这是表示我的应用程序内部工作的最短代码

我的目标是有一个保存弹出对话框来更新进度条(本例中不是这个问题)。 如果您试图运行此代码,您将看到按钮“保存”-点击后弹出显示

然而,我在进度条()中显示更新循环,突然弹出窗口不再显示-为什么

我在互联网上寻找解决方案。起初,我认为这与我在另一个线程中保存文件时用来更新弹出窗口的踩踏有关,但是这个示例没有线程,实际的方法被注释了,所以问题一定在别处

import kivy
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.popup import Popup
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout
from time import sleep

# Main app with save method
class MainApp(App):
  def build(self):
    sm = ScreenManager()
    self.save = save(app=self, name='save')
    sm.add_widget(self.save)
    self.saved_percent = 0.0
    return sm

  def save_file(self,file_path):
    for i in range(0,10):
      sleep(1)
      self.saved_percent = i * 10.0
      print("saved",i)
    self.save_finnished = True
    return 256 # check for written bytes

# one of many screens - this one is for saving
class save(Screen):
  def __init__(self, app, **kwargs):
    super(Screen,self).__init__(**kwargs)
    self.app = app
    lyo = BoxLayout(orientation='vertical')
    btn = Button(text="Save", size=(10,10))
    btn.bind(on_press=self.begin_save)
    lyo.add_widget(btn)
    self.add_widget(lyo) # basic layout to init the save

  def begin_save(self,*args):
    self.app.save_finnished = False
    self.cancel_save = False
    file_path = 'foo.txt' # debug static
    self.progress_bar(file_path) # TODO put in separate thread and continue
    #save_file(self,file_path)

  def progress_bar(self, file_path):
    btn = Button(text="Cancel")
    btn.bind(on_press=self.btn_cancel_save)

    pop = Popup(title="Saving", content=btn, auto_dismiss=False)
    pop.open() # does not open

    # this loop is somehow causing the Popup not to display
    #while (not self.app.save_finnished and not self.cancel_save):
    #    pass # progres bar is being updated here
    #pop.dismiss() # dismiss after exiting the loop

  def btn_cancel_save(self, *args):
    print("Cancel clicked")
    self.cancel_save = True


if __name__ == "__main__":
    top=MainApp()
    top.run()



















#
#import kivy
#from kivy.app import App
#from kivy.uix.screenmanager import ScreenManager, Screen
#from kivy.uix.boxlayout import BoxLayout
#from kivy.uix.progressbar import ProgressBar
#from kivy.uix.popup import Popup
#import threading
#from kivy.uix.label import Label
#from kivy.uix.button import Button
#from kivy.uix.boxlayout import BoxLayout
#from time import sleep
#from kivy.lang import Builder
#import queue
#
## Main app with save method
#class MainApp(App):
#  def build(self):
#    sm = ScreenManager()
#    self.save = save(app=self, name='save')
#    sm.add_widget(self.save)
#    self.saved_percent = 0.0
#    return sm
#
#  def save_file(self,file_path):
#    for i in range(0,10):
#      sleep(1)
#      self.saved_percent = i * 10.0
#      print("saved",i)
#    return 256 # check for written bytes
#
## one of many screens - this one is for saving
#class save(Screen):
#  def __init__(self, app, **kwargs):
#    super(Screen,self).__init__(**kwargs)
#    self.app = app
#    lyo = BoxLayout(orientation='vertical')
#    btn = Button(text="Save", size=(10,10))
#    btn.bind(on_press=self.begin_save)
#    lyo.add_widget(btn)
#    self.add_widget(lyo) # basic layout to init the save
#
#  def begin_save(self,*args):
#    self.save_finnished = False
#    self.cancel_save = False
#    file_path = 'foo.txt' # debug static
#    #written = self.poi.save_file(file_path)
#    #self.progress_bar(file_path)
#
#    # some black magic with threads to get ret value
#    # https://www.edureka.co/community/31966/how-to-get-the-return-value-from-a-thread-using-python
#    #que = queue.Queue()
#    #t = threading.Thread(target=lambda q, arg1: q.put(self.app.save_file(arg1)), args=(que, file_path))
#    #t.start()
#    self.progress_bar(file_path)
#    #progress_bar_thread = threading.Thread(target=self.progress_bar, args=(file_path,))
#    #progress_bar_thread.start()
#    #t.join()
#    #written = que.get()
#
##    self.save_finnished = True
##    size = os.path.getsize(file_path)
##    if(not self.btn_cancel_save):
##      if(written == size):
##        print("OK")
##        self.ok_dialog(True)
##      else:
##        print("Error saving to POI")
##        self.ok_dialog(False)
#
#  def progress_bar(self, file_path):
#    print("progress bar fnc ")
#    #lyo = BoxLayout(orientation='vertical')
#    #pb = ProgressBar(max=100.0)
#    #lbl = Label(text='0 %')
#    btn = Button(text="Cancel")
#    btn.bind(on_press=self.btn_cancel_save)
#    #lyo.add_widget(Label(text=file_path))
#    #lyo.add_widget(pb)
#    #lyo.add_widget(lbl)
#    #lyo.add_widget(btn)
#
#    #pop = Popup(title="Saving", content=lyo, auto_dismiss=False)
#    pop = Popup(title="Saving", content=btn, auto_dismiss=False)
#    pop.open() # does not open
#
##    print("start update loop")
##    print("finished?",self.save_finnished, "cancel?" ,self.cancel_save)
#    while (not self.save_finnished or not self.cancel_save):
#        pass # progres bar is being updated here
##      pb.value = self.app.saved_percent
##      s =  '%.12f' % self.app.saved_percent
##      i, p, d = s.partition('.')
##      str_percent = '.'.join([i, (d+'0'*2)[:2]])
##      lbl.text = str_percent +' %'
##      #print(" # ")
#    print("out of update loop - dismiss pop")
#    pop.dismiss()
#
#  def ok_dialog(self,success):
#    if(success):
#      title = "SUCCESS"
#    else:
#      title = "FAILED"
#    btn = Button(text="OK")
#
#    pop = Popup(title=title, content=btn, auto_dismiss=False)
#    btn.bind(on_press=pop.dismiss)
#    pop.open()
#
#
#  def btn_cancel_save(self, *args):
#    print("Cancel clicked")
#    self.cancel_save = True
#
#
#if __name__ == "__main__":
#    top=MainApp()
#    top.run()

Tags: pathfromimportselfappsavedefbar
2条回答

对于线程,我会使用这样的东西; 您必须退出按钮回调,否则eventloop不会重新绘制小部件

import time
from threading import Thread
from kivy.uix.progressbar import ProgressBar
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.boxlayout import BoxLayout


class TestApp(App):
    def build(self):
        self.thread = None

        parent = Widget()
        btn = Button(text='copy file', on_press=self.start_thread_copy_file)
        parent.add_widget(btn)
        return parent

    def start_thread_copy_file(self, *args):
        if self.thread is None:
            # open progressbar window
            self.progress_bar = ProgressBar(max=5)
            btn = Button(text="Cancel")
            btn.bind(on_press=self.thread_copy_cancel)

            layout = BoxLayout()
            layout.add_widget(self.progress_bar)
            layout.add_widget(btn)

            self.pop = Popup(title="Saving", content=layout)
            self.pop.open()

            self.thread = Thread(target=self.thread_copy_file_func)
            self.thread.start()

    def thread_copy_cancel(self, *args):
        self.thread = None  # can be also done with a flag
        self.pop.dismiss()

    def thread_copy_file_func(self):
        try:
            for i in range(5):
                print('thread_copy_file_func i =', i)
                self.progress_bar.value = i
                time.sleep(1)
                if self.thread is None:  # cancel condition
                    break

        finally:
            self.thread = None
            self.pop.dismiss()


TestApp().run()

如果没有线程,它可能看起来像这样(但是如果迭代时间长,它将非常没有响应)

import time
from kivy.uix.progressbar import ProgressBar
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.uix.button import Button
from kivy.uix.popup import Popup
from kivy.uix.boxlayout import BoxLayout
from kivy.clock import Clock


class TestApp(App):
    def build(self):
        parent = Widget()
        btn = Button(text='copy file', on_press=self.start_copy_file)
        parent.add_widget(btn)
        return parent

    def start_copy_file(self, *args):
        self.copy_cancel_flag = False

        # open progressbar window
        self.progress_bar = ProgressBar(max=50)
        btn = Button(text="Cancel")
        btn.bind(on_press=self.copy_cancel)

        layout = BoxLayout()
        layout.add_widget(self.progress_bar)
        layout.add_widget(btn)

        self.pop = Popup(title="Saving", content=layout)
        self.pop.open()

        self.copy_context_i = 0
        Clock.schedule_once(self.copy_file_func, 1)

    def copy_cancel(self, *args):
        self.copy_cancel_flag = True
        self.pop.dismiss()

    def copy_file_func(self, dt):
        print('thread_copy_file_func i =', self.copy_context_i)
        self.progress_bar.value = self.copy_context_i
        time.sleep(0.1)
        if self.copy_cancel_flag:
            pass  # cancel condition
        elif self.copy_context_i > 50:
            pass  # normal operation end
        else:
            self.copy_context_i += 1
            Clock.schedule_once(self.copy_file_func)  # run again
            return  # exit befor closing popup and cleanup

        # end, close popup
        #   ... other cleanup ...
        self.pop.dismiss()


TestApp().run()

相关问题 更多 >