【问题标题】:Kivy Popup displays at the end of cycleKivy 弹出窗口显示在周期结束时
【发布时间】:2021-02-12 09:18:28
【问题描述】:

我有一个处理数据的脚本 - 例如 5 个 csv 文件。脚本加载一个 csv 后,它会要求用户通过 Popup 窗口为特定 csv 提供额外的数据输入,因此在这种情况下,将有 5 个 Popup 窗口。

问题在于脚本忽略了在代码的所需部分中对弹出窗口的调用,并将它们显示在代码的最后。然而,它以相反的顺序显示它,因为最新的窗口位于旧窗口的顶部。

下面是代表我的问题的代码。在评论部分,有我的第一次尝试,其中 Popup 在主线程中被简单地调用。已经问过类似的问题,所以我用线程修改了代码,但是它没有解决问题,因为已经问过的问题是进度条,它应该与我假设的 Popup 一起运行代码.

所以我的问题是:有没有办法在调用 Popup 时冻结代码,并且在用户在 Popup 中提供变量后然后继续使用代码来自用户的变量。

test.kv:

<FirstWindow>
    name: "second"

    canvas.before:
        Color:
            rgba: (0.91,0.91,0.91,1)
        Rectangle:
            size: self.size
            pos: self.pos
    BoxLayout:
        orientation: "vertical"
        Label:
            size_hint_y: 0.2
            size_hint_x: 1
        BoxLayout:
            orientation: "horizontal"
            spacing:10
            Button:
                font_size: 30
                text: "Press to get Popup"
                on_release:
                    root.manager.transition.direction = "left"
                    root.Main_code()
        Label:
            size_hint_y: 0.2
            size_hint_x: 1

<MyPopup>:
    size_hint: .5, .5
    auto_dismiss: False
    title: 'Test'
    BoxLayout:
        text_input: text_input
        text_input2: text_input2
        orientation: 'vertical'
        Label:
            id: Datum
            font_size: 25
        BoxLayout:
            Label:
                text: "Test line one"
            TextInput:
                id: text_input
        BoxLayout:
            Label:
                text: "Test line two"
            TextInput:
                id: text_input2
        Button:
            text: 'Confirm'
            on_press: root.dismiss()

.py 文件:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.core.window import Window
from kivy.uix.popup import Popup
from kivy.properties import StringProperty
import threading

Window.size = (1200, 700)

class FirstWindow(Screen):
    popup_text = StringProperty()
    popup_text2 = StringProperty()

    def poptest (self,date):
        p = MyPopup(date)
        p.content.text_input.bind(text=self.setter('popup_text'))
        p.content.text_input2.bind(text=self.setter('popup_text2'))
        p.open()

    def Main_code(self):
        year = " .1.2020 0:00"
        con = 1
        while con<5:
            date = str(con) + year

            mythread = threading.Thread(target=self.poptest(date))
            mythread.start()

            # p = MyPopup(date)
            # p.content.text_input.bind(text=self.setter('popup_text'))
            # p.content.text_input2.bind(text=self.setter('popup_text2'))
            # p.open()

            print(self.popup_text)
            print(self.popup_text2)
            print("Cycle " + str(con) + " finished")
            con +=1

class MyPopup(Popup):
    date = StringProperty()
    def __init__(self, date, **kwargs):
        super(MyPopup, self).__init__(**kwargs)
        self.ids.Datum.text = "Date since: " + str(date)

class WindowManager(ScreenManager):
    pass

with open("test.kv", encoding='utf-8') as f:
    Builder.load_string(f.read())

window = WindowManager()
screens = [FirstWindow(name="second")]
for screen in screens:
    window.add_widget(screen)
window.current = "second"

class MyMainApp(App):
    def build(self):
        return window

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

非常感谢任何帮助。

【问题讨论】:

    标签: python kivy popup kivy-language


    【解决方案1】:

    您可以使用locks 强制一个线程等待另一个线程。这是使用锁的代码的修改版本:

    from functools import partial
    from kivy.app import App
    from kivy.clock import Clock
    from kivy.lang import Builder
    from kivy.uix.screenmanager import ScreenManager, Screen
    from kivy.core.window import Window
    from kivy.uix.popup import Popup
    from kivy.properties import StringProperty
    import threading
    
    Window.size = (1200, 700)
    
    class FirstWindow(Screen):
        popup_text = StringProperty()
        popup_text2 = StringProperty()
    
        def poptest (self, p, dt):
            # the instance of MyPopup is passed as an arg
            p.content.text_input.bind(text=self.setter('popup_text'))
            p.content.text_input2.bind(text=self.setter('popup_text2'))
            p.open()
    
        def Main_code(self):
            # run the loop in another thread (not the main thread)
            mythread = threading.Thread(target=self.old_main_code, daemon=True)
            mythread.start()
    
    
        def old_main_code(self):
            # create a lock to be used in keeping this thread and the MyPopups sychronized
            lock = threading.Lock()
            lock.acquire()
    
            year = " .1.2020 0:00"
            con = 1
            while con<5:
                date = str(con) + year
    
                lock.release()  # release the lock so that the MyPopup can acquire it
                pop = MyPopup(lock, date)  # create Popup here to be sure it acquires lock
                Clock.schedule_once(partial(self.poptest, pop))  # run poptest on main thread
                lock.acquire()  # wait for the Popup to release the lock
    
                print(self.popup_text)
                print(self.popup_text2)
                print("Cycle " + str(con) + " finished")
                con +=1
    
    class MyPopup(Popup):
        date = StringProperty()
        def __init__(self, lock, date, **kwargs):
            lock.acquire()  # acquire the lock to force the other thread to wait
            super(MyPopup, self).__init__(**kwargs)
            self.ids.Datum.text = "Date since: " + str(date)
            self.lock = lock
    
        def myDismiss(self):
            self.dismiss()
            self.lock.release()  # release the lock to allow while loop to continue
    
    class WindowManager(ScreenManager):
        pass
    
    
    with open("test.kv", encoding='utf-8') as f:
        Builder.load_string(f.read())
    
    window = WindowManager()
    screens = [FirstWindow(name="second")]
    for screen in screens:
        window.add_widget(screen)
    window.current = "second"
    
    class MyMainApp(App):
        def build(self):
            return window
    
    if __name__ == "__main__":
        MyMainApp().run()
    

    kv文件的唯一改动是将Confirm按钮设置为调用root.myDismiss()

        Button:
            text: 'Confirm'
            on_press: root.myDismiss()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-10-12
      • 2014-06-27
      • 1970-01-01
      • 2017-02-01
      • 2020-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多