[英]Random Screens from ScreenManager python kivy
我的应用程序中有一些图像,每个图像都属于一个屏幕,当我按下一个按钮时,我尝试获取另一个屏幕,但随机屏幕。 我想我已经很接近做我想做的事了,但是在这个阶段我被困了 2 天。当我在控制台中运行我的代码时,我遇到了这个错误“AttributeError:'ScreenManager' object 没有属性'random_screen' "
而且我真的不知道把那个属性放在哪里......请heeeelppp::((
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
from random import choice
class MyScreens(Screen):
screens = ["Q1", "Q2", "Q3"] # ........
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.random_screen()
def random_screen(self, *_):
self.source = choice(self.screens)
class Q1(Screen):
pass
class Q2(Screen):
pass
class Q3(Screen):
pass
class TestApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(Q1(name='Q1'))
sm.add_widget(Q2(name='Q2'))
sm.add_widget(Q2(name='Q3'))
return sm
if __name__ == '__main__':
TestApp().run()
<Q1>:
Image:
source: 'Q1.png'
FloatLayout:
size: root.width, root.height/2
Button:
size_hint: 0.3, 0.25
pos_hint: {"x":0.09, "top":1.16}
background_color: 1, 1, 1, 0.2
on_release: app.root.random_screen()
<Q2>:
Image:
source: 'Q2.png'
FloatLayout:
size: root.width, root.height/2
Button:
size_hint: 0.3, 0.25
pos_hint: {"x":0.09, "top":1.16}
background_color: 1, 1, 1, 0.2
on_press: app.root.random_screen()
<Q3>:
Image:
source: 'Q3.png'
FloatLayout:
size: root.width, root.height/2
Button:
size_hint: 0.3, 0.25
pos_hint: {"x":0.09, "top":1.16}
background_color: 1, 1, 1, 0.2
on_press: app.root.random_screen()
你那里有很多错误...
Myscreen class 根本没有连接到您的其他类或 kv 文件,因此根本找不到 function。
您的第三个 add.widget 调用添加了“Q2”屏幕而不是 Q3
Screen 没有 self.source 参数。 您需要使用屏幕管理器来更改屏幕。 root.manager.current = 'Q#' 将是正确的方法。
这对我有用...
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
import random
class Q1(Screen):
def random_screen(self):
screens = ['Q1', 'Q2', 'Q3']
return random.choice(screens)
class Q2(Screen):
def random_screen(self):
screens = ['Q1', 'Q2', 'Q3']
return random.choice(screens)
class Q3(Screen):
def random_screen(self):
screens = ['Q1', 'Q2', 'Q3']
return random.choice(screens)
class TestApp(App):
def build(self):
sm = ScreenManager()
sm.add_widget(Q1(name='Q1'))
sm.add_widget(Q2(name='Q2'))
sm.add_widget(Q3(name='Q3'))
return sm
if __name__ == '__main__':
TestApp().run()
.kv文件
<Q1>:
Image:
source: 'Q1.png'
FloatLayout:
size: root.width, root.height/2
Button:
size_hint: 0.3, 0.25
pos_hint: {"x":0.09, "top":1.16}
background_color: 1, 1, 1, 0.2
on_release: root.manager.current = root.random_screen()
<Q2>:
Image:
source: 'Q2.png'
FloatLayout:
size: root.width, root.height/2
Button:
size_hint: 0.3, 0.25
pos_hint: {"x":0.09, "top":1.16}
background_color: 1, 1, 1, 0.2
on_release: root.manager.current = root.random_screen()
<Q3>:
Image:
source: 'Q3.png'
FloatLayout:
size: root.width, root.height/2
Button:
size_hint: 0.3, 0.25
pos_hint: {"x":0.09, "top":1.16}
background_color: 1, 1, 1, 0.2
on_release: root.manager.current = root.random_screen()
您还可以将该方法放入应用程序 class 并在 kv 文件中使用
app.random_screen()
只是意味着您不必在每个屏幕 class 中重复相同的方法。
from kivy.app import App
from kivy.uix.screenmanager import ScreenManager, Screen
import random
class Q1(Screen):
Pass
class Q2(Screen):
Pass
class Q3(Screen):
Pass
class TestApp(App):
def random_screen(self):
screens = ['Q1', 'Q2', 'Q3']
return random.choice(screens)
def build(self):
sm = ScreenManager()
sm.add_widget(Q1(name='Q1'))
sm.add_widget(Q2(name='Q2'))
sm.add_widget(Q3(name='Q3'))
return sm
if __name__ == '__main__':
TestApp().run()
千伏:
<Q1>:
Image:
source: 'Q1.png'
FloatLayout:
size: root.width, root.height/2
Button:
size_hint: 0.3, 0.25
pos_hint: {"x":0.09, "top":1.16}
background_color: 1, 1, 1, 0.2
on_release: root.manager.current = app.random_screen()
<Q2>:
Image:
source: 'Q2.png'
FloatLayout:
size: root.width, root.height/2
Button:
size_hint: 0.3, 0.25
pos_hint: {"x":0.09, "top":1.16}
background_color: 1, 1, 1, 0.2
on_release: root.manager.current = app.random_screen()
<Q3>:
Image:
source: 'Q3.png'
FloatLayout:
size: root.width, root.height/2
Button:
size_hint: 0.3, 0.25
pos_hint: {"x":0.09, "top":1.16}
background_color: 1, 1, 1, 0.2
on_release: root.manager.current = app.random_screen()
另一件要考虑的事情,我不确定这将如何工作,因为我没有像您那样使用图像,但是您可以让按钮更改图像而不是更改屏幕......在应用程序 class 中可以有一个字符串属性,该属性的更改方式与按钮更改屏幕的方式相同。 在 kv 文件中,让图像源引用此字符串属性 app.Pic,例如下面...
from kivy.app import App
from kivy.uix.properties import StringProperty
from kivy.uix.screenmanager import ScreenManager, Screen
import random
class Q1(Screen):
Pass
class TestApp(App):
Pic = StringProperty('Q1.png')
def random_pic(self):
Pics = ['Q1.png', 'Q2.png', 'Q3.png']
self.Pic = random.choice(Pics)
def build(self):
sm = ScreenManager()
sm.add_widget(Q1(name='Q1'))
return sm
if __name__ == '__main__':
TestApp().run()
千伏:
<Q1>:
Image:
source: app.Pic
FloatLayout:
size: root.width, root.height/2
Button:
size_hint: 0.3, 0.25
pos_hint: {"x":0.09, "top":1.16}
background_color: 1, 1, 1, 0.2
on_release: app.random_pic()
我知道这不是您原始问题的另一个答案,但根据上面的评论,这里是一个真正配对的后备测验应用程序,让您了解如何更改问题和答案并使用相同的按钮和屏幕......
我将所有内容都放入应用程序 class 中,这样可以更轻松地从 kv 文件访问。 我尝试添加一些评论来尝试解释代码
from kivy.app import App
from kivy.properties import StringProperty, BooleanProperty,ObjectProperty, NumericProperty
from kivy.uix.screenmanager import ScreenManager, Screen
TestBank = {1 : {"Current Question": "Press 3", "Correct Answer": "3", "Chosen Answer": "", "Multiple Chocies": ["1","2","3","4"]},
2 : {"Current Question": "Press 4", "Correct Answer": "4", "Chosen Answer": "", "Multiple Chocies": ["1","2","3","4"]},
3 : {"Current Question": "Press 1", "Correct Answer": "1", "Chosen Answer": "", "Multiple Chocies": ["1","2","3","4"]},
4 : {"Current Question": "Press 2", "Correct Answer": "2", "Chosen Answer": "", "Multiple Chocies": ["1","2","3","4"]}}
def CreateTest(A_Test = TestBank):
#do something to randomise your test, maybe select a certain number of questions or merge several test banks etc...
return A_Test
class MenuScreen(Screen):
pass
class ResultScreen(Screen):
pass
class TestScreen(Screen):
pass
class QuizApp(App):
TestCurrentQuestion = StringProperty()
'This is updated when next question is selcted'
ChosenAnswerText = StringProperty()
'Every time an answer is selected this property is updated with the selected answer, then the label is automatically updated'
CurrentQuestion = NumericProperty(1)
'The Next and Previous buttons change this property up or down'
TotalQuestions = 4
AnswerButtonA = StringProperty()
AnswerButtonB = StringProperty()
AnswerButtonC = StringProperty()
AnswerButtonD = StringProperty()
'These are the four answer buttons, the Next and Previous buttons update these properties with the answer options, the button texts are then autmatically updated'
Score = NumericProperty()
def StartTest(self):
self.Test = CreateTest() #The test is created
self.UpdateQuestionAndAnswerButtons() #This method updates the text properties that updates all the buttons
def NextQuestion(self):
self.CurrentQuestion +=1 #changes the current question property +1
self.UpdateQuestionAndAnswerButtons() #This method updates the text properties that updates all the buttons
def PreviousQuestion(self):
self.CurrentQuestion -=1 #changes the current question property -1
self.UpdateQuestionAndAnswerButtons() #This method updates the text properties that updates all the buttons
def UpdateChosenAnswer(self, button):
self.Test[self.CurrentQuestion]["Chosen Answer"] = button.text #so that a score can be calculated, the chosen answer is stored in the dictionary TestBank
self.ChosenAnswerText = self.Test[self.CurrentQuestion]["Chosen Answer"] #ChosenAnswerProperty is updated, this then updates the label so the chosen answer appears on screen
def UpdateQuestionAndAnswerButtons(self):
self.TestCurrentQuestion = self.Test[self.CurrentQuestion]["Current Question"]
#TestCurrentQuestion is the property, it is updated to ["Current Question"] for the Test Dic
self.AnswerButtonA, self.AnswerButtonB, self.AnswerButtonC, self.AnswerButtonD = self.Test[self.CurrentQuestion]["Multiple Chocies"]
#["Multiple Chocies"] is a list containing 4 items, so the four properties are updated in one line
self.ChosenAnswerText = self.Test[self.CurrentQuestion]["Chosen Answer"]
#The chosen answer is updated, this is needed here incase the previous button is selcted, the previous selected answer will be updated to avoid confusion for the user
def CalculateScore(self):
score = 0
for Question in self.Test.keys():
if self.Test[Question]["Chosen Answer"]== self.Test[Question]["Correct Answer"]:
score+=1
self.Score = score
def build(self):
sm = ScreenManager()
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(ResultScreen(name='result'))
sm.add_widget(TestScreen(name='test'))
return sm
QuizApp().run()
和 KV 文件
<ResultScreen>
BoxLayout:
orientation: "vertical"
padding: "20px"
spacing: "20px"
BoxLayout:
Label:
text: f"Your Score was {app.Score} out of {app.TotalQuestions}\n {round(app.Score/app.TotalQuestions*100)}%"
Label:
text: "PASS" if app.Score/app.TotalQuestions*100 >= 70 else "FAIL" #pass mark is 70%
Button:
text: "Good Bye"
on_press: app.get_running_app().stop()
<MenuScreen>
BoxLayout:
orientation: "vertical"
padding: "20px"
spacing: "20px"
Label:
text:"Wecome to the Test App"
Button:
text: "New Test"
on_press: app.StartTest(); root.manager.current = "test"
<TestScreen>
BoxLayout:
orientation: "vertical"
BoxLayout:
padding: "20px"
orientation: "vertical"
Label:
text: app.TestCurrentQuestion
halign: "center"
Label:
text: app.ChosenAnswerText
GridLayout:
padding: "20px"
spacing: "20px"
cols: 2
rows: 2
Button:
text: app.AnswerButtonA
on_press: app.UpdateChosenAnswer(self)
Button:
text: app.AnswerButtonB
on_press: app.UpdateChosenAnswer(self)
Button:
text: app.AnswerButtonC
on_press: app.UpdateChosenAnswer(self)
Button:
text: app.AnswerButtonD
on_press: app.UpdateChosenAnswer(self)
BoxLayout:
size_hint: (1,None)
orientation: "horizontal"
padding: "20px"
spacing: "20px"
Button:
text: "Previous"
size_hint: (0.3,1)
on_press: app.PreviousQuestion()
disabled: True if app.CurrentQuestion == 1 else False
Button:
text: "Submit"
size_hint: (0.4,1)
on_press: app.CalculateScore(); root.manager.current = "result"
Button:
text: "Next"
on_press: app.NextQuestion();
size_hint: (0.3,1)
disabled: True if app.CurrentQuestion == app.TotalQuestions else False
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.