关闭另一个类的kivy弹出窗口



我正在编写一个简单的词汇应用程序,当用户提交答案时,如果他回答正确与否,应该会显示一个弹出窗口。到目前为止,这是有效的,但当弹出窗口应该被取消/关闭时,应用程序崩溃,告诉AttributeError: 'MyScreenManager' object has no attribute 'close_pop'这是有道理的,因为close_pop方法是在PopupWindow类中定义的(如果可能的话,我想把不同的关注点分开(

我想到了两种可能的解决方案,但不知道如何实现:

1:从MyScreenManager类中调用close_pop方法,但我不知道如何引用应该关闭的弹出对象

2:调整kv部分:

<PopupWindow>:
pLabel: pLabel
Label:
id: pLabel
size_hint: .6, .2
pos_hint:{'x': .2, 'top': 1}
font_name: 'static/NotoSansSC-Regular.otf'
Button:
text: 'Close'
size_hint: .8, .2
pos_hint:{'x': .1, 'y': .1}
on_release: app.root.close_pop()

不调用根类(MyScreenManager(,而是执行类似app.PopupWindow.close_pop()的操作,但这也不起作用。

我能够在没有screenmanager的情况下使其工作(并将所有方法放入一个类"Mainwindow"中,该类当时也是根类(,但为了进一步增强,我想使用screenmanager:(

任何其他好的解决方案也会起作用-非常感谢!

这是我的Python代码:

import random
import pandas as pd
import unidecode
from kivy.app import App
#from kivy.uix.gridlayout import GridLayout
#from kivy.uix.widget import Widget
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.popup import Popup
#from kivy.uix.actionbar import ActionBar
#from kivy.uix.label import Label
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen
class MainWindow(Screen):
userInput = ObjectProperty(None)
vocab = ObjectProperty(None)
def __init__(self, **kwargs):
super(MainWindow, self).__init__(**kwargs)
self.df = pd.read_excel(r"static/HSK1-Vocabulary-List.xlsx")
self.en = self.df['English']
self.zh = self.df['Chinese']
self.pinyin = self.df['Pinyin']
self.rd = None
def btn_submit(self):
if self.rd is None:
pLabel = "Please start before submitting!"
elif not self.userInput.text:
pLabel = "Please enter something!"
else:
pLabel = self.validate(self.userInput.text)
self.btn_next()
PopupWindow(pLabel).open_popup()
def btn_next(self):
self.userInput.text = ""
self.rd = random.randint(0, self.df.shape[0]-1)
self.vocab.text = "What is '{}' in Chinese?".format(self.en[self.rd])
def validate(self, answer):
def replace_tones(orig_voc):
unaccented_voc = unidecode.unidecode(orig_voc)
return(unaccented_voc)
if answer == self.zh[self.rd]:
#correct+=1
return("Well done, even in chinese characters!")
elif answer == self.pinyin[self.rd]:
#correct+=1
return("Well done, you also got the correct tones!")
elif answer == replace_tones(self.pinyin[self.rd]):
#correct+=1
return("Well done! Keep in mind the tones '{}'".format(self.pinyin[self.rd]))
else:
return("Sorry, that was not correct!nThe correct vocab is {}".format(self.pinyin[self.rd]))
#cnt+=1

class PopupWindow(FloatLayout):
def __init__(self, userInput):
super().__init__()
self.pLabel.text = userInput
def open_popup(self):
content = PopupWindow(self.pLabel.text)
self.pop = Popup(title="Result", content=content, size_hint=(None, None), size=(400, 400))
self.pop.open()
def close_pop(self):
self.pop.dismiss()

class DashboardWindow(Screen):
pass    

class MyScreenManager(ScreenManager):
pass
#def close_pop(self):
#    print("This should close the popup...")

KV = Builder.load_file("main.kv")
class VocabularyTrainer(App):
def build(self):
return KV

if __name__ == "__main__":
app = VocabularyTrainer()
app.run()

这里是我的.kv文件:

MyScreenManager:
MainWindow:
DashboardWindow:
<MainWindow>:
name: 'main'
vocab: vocab
userInput: userInput
GridLayout:
size: root.width, root.height
rows: 4
ActionBar:
id: actBar
background_image: ''
background_color: (0.53, 0.808, 0.98, 1)
ActionView:
ActionPrevious:
ActionButton:
text: 'Quiz'
ActionButton:
text: 'Training'
ActionButton:
text: 'Settings'
Label:
id: vocab
text: 'Welcome to the Chinese Learning App!'
TextInput:
id: userInput
hint_text: 'Enter answer'
width: 300
multiline: False
on_text_validate: root.btn_submit()
font_name: 'static/NotoSansSC-Regular.otf'
GridLayout:
cols: 3
Button:
text: 'Submit'
on_press: root.btn_submit()
Button:
text: 'Start/Skip'
on_press: root.btn_next()
Button:
text: 'Dashboard'
on_press: app.root.current = 'dashboard'
<PopupWindow>:
pLabel: pLabel
Label:
id: pLabel
size_hint: .6, .2
pos_hint:{'x': .2, 'top': 1}
font_name: 'static/NotoSansSC-Regular.otf'
Button:
text: 'Close'
size_hint: .8, .2
pos_hint:{'x': .1, 'y': .1}
on_release: app.root.close_pop()
<DashboardWindow>:
name: 'dashboard'
GridLayout:
rows: 2
Label:
text: '<e.g. PieChart Results>'
Button:
text: 'Go back'
on_press: app.root.current = 'main'

问题是每次使用PopupWindow时都会创建两个PopupWindows。更好的方法是只创建一个,如下所示:

class PopupWindow(FloatLayout):
def __init__(self, userInput):
super().__init__()
self.pLabel.text = userInput
self.pop = Popup(title="Result", content=self, size_hint=(None, None), size=(400, 400))
def open_popup(self):
self.pop.open()
def close_pop(self):
self.pop.dismiss()

然后在您的kv中,您可以使用:

<PopupWindow>:
pLabel: pLabel
Label:
id: pLabel
size_hint: .6, .2
pos_hint:{'x': .2, 'top': 1}
font_name: 'static/NotoSansSC-Regular.otf'
Button:
text: 'Close'
size_hint: .8, .2
pos_hint:{'x': .1, 'y': .1}
on_release: root.close_pop()

您应该将其分解为一个简单的问题示例。从我目前所看到的情况来看,你应该尝试将你的btn_submit方法更改为这样的方法,以使弹出窗口易于访问:

def btn_submit(self):
if self.rd is None:
pLabel = "Please start before submitting!"
elif not self.userInput.text:
pLabel = "Please enter something!"
else:
pLabel = self.validate(self.userInput.text)
self.btn_next()
self.mypopup = PopupWindow(pLabel)
self.mypopup.open_popup()

然后你应该可以用你的屏幕管理器访问它,就像这样:

class MyScreenManager(ScreenManager):
def close_pop(self):
print("This should close the popup...")
self.get_screen('main').mypopup.close_pop()

最新更新