簡體   English   中英

ScreenManager 中的隨機屏幕 python kivy

[英]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()


你那里有很多錯誤...

  1. Myscreen class 根本沒有連接到您的其他類或 kv 文件,因此根本找不到 function。

  2. 您的第三個 add.widget 調用添加了“Q2”屏幕而不是 Q3

  3. 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM