![](/img/trans.png)
[英]How to change MDRectangleFlatIconButton text colour in Kivy/KivyMD
[英]How to I set Text Colour to a Disabled Button in KivyMD
我在 Kivy 中創建了一個測驗應用程序,當出現問題時,有 4 個選項(4 個切換按鈕)。 選擇一個切換按鈕選擇一個答案,您的答案將被存儲,以便計算結果。
在測驗結束時,可以選擇查看測驗。 使用與測試期間相同的屏幕,但這次禁用了 4 個切換按鈕。 在這里,我很難嘗試在 KivyMD 中重新創建我在 Kivy 中擁有的功能......我在這篇文章的末尾包含了原始的 KIVY 代碼和下面的 KivyMD 版本。
在審查期間,每個切換按鈕都被禁用,但文本顏色指示正確或錯誤答案。 正確答案文本顏色為“綠色”,如果用戶選擇了錯誤答案,則該文本顏色為“紅色”,所有其他按鈕都保留為默認值。 如果用戶選擇了正確的答案,則只有一個“綠色”文本,其他所有文本均為默認值。
在 Kivy 中,我通過創建四個屬性來實現這一點:
Button_A_Text_Color = StringProperty() Button_B_Text_Color = StringProperty()
然后我創建了一個屬性 UpdateButtons(),當調用它時會檢查它是“測試模式”還是“審查模式”。 如果測試處於“測試模式”,這些屬性將設置為默認顏色,但如果測試處於“審閱模式”,則顏色將根據正確答案和用戶給出的答案進行設置。 每當用戶從一個問題轉到另一個問題時,都會調用 UpdateButtons()...
現在,我認為我的問題在於 KivyMD 使用主題,並且在后台發生了更多事情,所以我的 UpdateButtons() 被覆蓋了,但是 kivy 切換按鈕屬性!
我整個上午都在瀏覽 KivyMD 模塊,確實找到了一些我在創建 MyToggleButton class 時嘗試修改的屬性,但我能做的最好的事情就是在測試期間將文本設置為“綠色”或“紅色”或其他任何內容模式,在“審閱模式”中,文本顏色保持默認。 在默認模式下,按鈕都設置為禁用,所以我認為某處有一個屬性在禁用時將按鈕文本設置為某種顏色。 但是我沒找到!!
任何想法如何做到這一點???
很抱歉這個長問題,但只是想提供足夠的細節......下面是代碼和 KV 文件,我試圖剝離所有不必要的代碼,並留下足夠的內容來展示我正在嘗試做的事情!
謝謝
愛因
PY代碼:
from kivymd.app import MDApp
from kivymd.uix.screenmanager import MDScreenManager
from kivymd.uix.screen import MDScreen
from kivy.properties import StringProperty, BooleanProperty,ObjectProperty, NumericProperty
from random import shuffle
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
from kivymd.uix.button import MDRoundFlatButton
source = [
{"question":"Press 1","A":"1","B":"2","C":"3","D":"4","answer":"A"},
{"question":"Press 2","A":"3","B":"2","C":"1","D":"4","answer":"B"},
{"question":"Press 3","A":"2","B":"2","C":"3","D":"4","answer":"C"},
{"question":"Press 4","A":"1","B":"4","C":"2","D":"3","answer":"D"},
]
TestQuestions = {}
for dict in source:
TestQuestions[dict["question"]] = ([dict["A"].title(),dict["B"].title(),dict["C"].title(),dict["D"].title() ],dict[dict["answer"]].title() )
def CreateTest(test = TestQuestions):
Test = {}
for Number, Question in enumerate([x for x in test.keys()]):
Test[Number+1] = {
"Current Question" : Question,
"Correct Answer" : TestQuestions[Question][1],
"Chosen Answer" : "Blank",
"Multiple Chocies" : TestQuestions[Question][0]}
return Test
class QuestionsScreen(MDScreen):
pass
class ResultScreen(MDScreen):
pass
class TestScreen(MDScreen):
pass
class MyToggleButton(MDRoundFlatButton, MDToggleButton):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.background_down = MDApp.get_running_app().theme_cls.primary_dark
class QuizTestApp(MDApp):
Status = BooleanProperty(False)
TestComplete = BooleanProperty(False)
Test = ObjectProperty()
PassMark = 70
TestCurrentQuestion = StringProperty()
CurrentQuestionText = StringProperty("1")
TotalQuestionsText = StringProperty("1")
ChosenAnswerText = StringProperty()
CurrentQuestion = 1
TotalQuestions = NumericProperty(1)
AnswerButtonA = StringProperty()
AnswerButtonB = StringProperty()
AnswerButtonC = StringProperty()
AnswerButtonD = StringProperty()
AnswerButtonA_state = StringProperty("normal")
AnswerButtonB_state = StringProperty("normal")
AnswerButtonC_state = StringProperty("normal")
AnswerButtonD_state = StringProperty("normal")
Score = NumericProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.Status = False
self.CorrectAnswer = ""
self.TestComplete = False
self.CurrentQuestion = 1
self.Test = CreateTest()
self.TotalQuestions = 4
self.TotalQuestionsText = str(self.TotalQuestions)
self.UpdateQuestionAndAnswerButtons()
def UpdateChosenAnswer(self, button):
self.Test[self.CurrentQuestion]["Chosen Answer"] = button.text
self.ChosenAnswerText = self.Test[self.CurrentQuestion]["Chosen Answer"]
self.DisableSubmitButton()
def NextQuestion(self):
self.CurrentQuestion +=1
self.UpdateQuestionAndAnswerButtons()
def PreviousQuestion(self):
self.CurrentQuestion -=1
self.UpdateQuestionAndAnswerButtons()
def StartTest(self, number):
self.Status = False
self.CorrectAnswer = ""
self.TestComplete = False
self.CurrentQuestion = 1
self.Test = CreateTest(int(number), occuarnces = self.Stats["Questions Breakdown"])
self.TotalQuestions = int(number)
self.TotalQuestionsText = str(self.TotalQuestions)
self.UpdateQuestionAndAnswerButtons()
def UpdateQuestionAndAnswerButtons(self):
self.CurrentQuestionText = str(self.CurrentQuestion)
self.TestCurrentQuestion = self.Test[self.CurrentQuestion]["Current Question"]
self.AnswerButtonA, self.AnswerButtonB, self.AnswerButtonC, self.AnswerButtonD = self.Test[self.CurrentQuestion]["Multiple Chocies"]
self.ChosenAnswerText = self.Test[self.CurrentQuestion]["Chosen Answer"]
self.HighLightButtonIfAnswered()
def HighLightButtonIfAnswered(self):
self.AnswerButtonA_state = "normal"
self.AnswerButtonB_state = "normal"
self.AnswerButtonC_state = "normal"
self.AnswerButtonD_state = "normal"
def func(button_text):
if self.Test[self.CurrentQuestion]["Chosen Answer"] == button_text:
return "down"
elif self.Test[self.CurrentQuestion]["Chosen Answer"] == "Blank":
return "normal"
else:
return "normal"
self.AnswerButtonA_state = func(self.AnswerButtonA)
self.AnswerButtonB_state = func(self.AnswerButtonB)
self.AnswerButtonC_state = func(self.AnswerButtonC)
self.AnswerButtonD_state = func(self.AnswerButtonD)
def SubmitTest(self):
if self.Status == False:
self.Score = self.CalculateScoreAndUpdateTestQuestionsBreakdown()
def DisableSubmitButton(self):
for Question in self.Test.keys():
if self.Test[Question]["Chosen Answer"] == "Blank":
self.TestComplete = False
break
else:
self.TestComplete = True
def CalculateScoreAndUpdateTestQuestionsBreakdown(self):
score = 0
for Question in self.Test.keys():
if self.Test[Question]["Chosen Answer"]== self.Test[Question]["Correct Answer"]:
score+=1
return score
def StartReview(self):
self.TestComplete = True
self.Status = True
self.CurrentQuestion = 1
self.CurrentQuestionText = str(self.CurrentQuestion)
def build(self):
self.theme_cls.theme_style = "Light"
self.theme_cls.primary_palette = "BlueGray"
sm = MDScreenManager()
sm.add_widget(TestScreen(name='test'))
sm.add_widget(ResultScreen(name='result'))
return sm
QuizTestApp().run()
KV 文件...
<MDLabel>:
halign: "center"
theme_text_color: "Secondary"
font_style: "Body1"
<ResultScreen>
MDBoxLayout:
orientation: "vertical"
padding: "20px"
spacing: "20px"
MDBoxLayout:
orientation: "vertical"
MDLabel:
text: f"Your Score was {app.Score} out of {app.TotalQuestions}\n{round(app.Score/app.TotalQuestions*100)}%"
MDLabel:
text: "PASS" if app.Score/app.TotalQuestions*100 >= app.PassMark else "FAIL"
MDBoxLayout:
size_hint: (1,None)
min_height: dp(10)
orientation: "horizontal"
spacing: "20px"
MDRoundFlatButton:
size_hint: (1,1)
text: "Review Questions"
on_press: app.StartReview(); root.manager.current = "test"; app.UpdateQuestionAndAnswerButtons()
MDRoundFlatButton:
size_hint: (1,1)
text: "exit"
on_press: app.get_running_app().stop()
<TestScreen>
id: TestScreen
MDBoxLayout:
orientation: "vertical"
MDBoxLayout:
id: TopNumbers
size_hint: 1, None
height: dp(30)
orientation: "horizontal"
MDBoxLayout:
id: TopNumbers2
orientation: "horizontal"
size_hint: 1, None
height: dp(30)
MDBoxLayout:
id: TopNumbers3
orientation: "horizontal"
size_hint: 1, None
height: dp(30)
MDBoxLayout:
padding: "20px"
orientation: "vertical"
MDLabel:
text: app.TestCurrentQuestion
text_size: self.width, None
halign: "center"
MDBoxLayout:
orientation: "vertical"
padding: "20px"
spacing: "20px"
MDBoxLayout:
orientation: "horizontal"
MyToggleButton:
id: AnswerButtonA
group: 1
text_size: self.width, None
#text_color: app.AnswerButtonA_color
text: app.AnswerButtonA
on_press: app.UpdateChosenAnswer(AnswerButtonA)
state: app.AnswerButtonA_state
disabled: True if self.text == "" or app.Status else False
size_hint: (0.5,1)
MyToggleButton:
id: AnswerButtonB
group: 1
text_size: self.width, None
#text_color: app.AnswerButtonB_color
text: app.AnswerButtonB
on_press: app.UpdateChosenAnswer(AnswerButtonB)
state: app.AnswerButtonB_state
disabled: True if self.text == "" or app.Status else False
size_hint: (0.5,1)
MDBoxLayout:
orientation: "horizontal"
MyToggleButton:
id: AnswerButtonC
group: 1
text_size: self.width, None
#text_color: app.AnswerButtonC_color
text: app.AnswerButtonC
on_press: app.UpdateChosenAnswer(AnswerButtonC)
state: app.AnswerButtonC_state
disabled: True if self.text == "" or app.Status else False
size_hint: (0.5,1)
MyToggleButton:
id: AnswerButtonD
group: 1
text_size: self.width, None
#text_color: app.AnswerButtonD_color
text: app.AnswerButtonD
on_press: app.UpdateChosenAnswer(AnswerButtonD)
state: app.AnswerButtonD_state
disabled: True if self.text == "" or app.Status else False
size_hint: (0.5,1)
MDBoxLayout:
size_hint: (1,None)
min_height: dp(10)
orientation: "horizontal"
padding: "20px"
spacing: "20px"
MDRoundFlatButton:
text_size: self.width, None
text: "Previous"
size_hint: (0.3,1)
on_press: AnswerButtonA.state = "normal"; AnswerButtonB.state = "normal"; AnswerButtonC.state = "normal"; AnswerButtonD.state = "normal"; app.PreviousQuestion()
disabled: True if app.CurrentQuestionText == "1" else False
MDRoundFlatButton:
text_size: self.width, None
text: " Close Review" if app.Status else "Answer All Questions" if app.TestComplete==False else "Submit"
#text_size: (50, None) if app.Status else (75, None) if app.TestComplete==False else (50, None)
size_hint: (0.4,1)
on_press: AnswerButtonA.state = "normal"; AnswerButtonB.state = "normal"; AnswerButtonC.state = "normal"; AnswerButtonD.state = "normal";
on_release: app.SubmitTest(); root.manager.current = "result"
disabled: True if app.Status==False and app.TestComplete==False else False
MDRoundFlatButton:
text_size: self.width, None
text: "Next"
size_hint: (0.3,1)
on_press: AnswerButtonA.state = "normal"; AnswerButtonB.state = "normal"; AnswerButtonC.state = "normal"; AnswerButtonD.state = "normal"; app.NextQuestion()
disabled: True if str(app.CurrentQuestionText) == str(app.TotalQuestions) else False
這是實現結果的原始 KIVY 代碼。 在評論頁面中,按鈕文本顏色會根據答案發生變化...
from kivy.app import App
from kivy.properties import StringProperty, BooleanProperty,ObjectProperty, NumericProperty
from kivy.uix.screenmanager import ScreenManager, Screen
source = [
{"question":"Press 1","A":"1","B":"2","C":"3","D":"4","answer":"A"},
{"question":"Press 2","A":"3","B":"2","C":"1","D":"4","answer":"B"},
{"question":"Press 3","A":"2","B":"1","C":"3","D":"4","answer":"C"},
{"question":"Press 4","A":"1","B":"4","C":"2","D":"3","answer":"B"},
]
TestQuestions = {}
for dict in source:
TestQuestions[dict["question"]] = ([dict["A"].title(),dict["B"].title(),dict["C"].title(),dict["D"].title() ],dict[dict["answer"]].title() )
def CreateTest(test = TestQuestions):
Test = {}
for Number, Question in enumerate([x for x in test.keys()]):
Test[Number+1] = {
"Current Question" : Question,
"Correct Answer" : TestQuestions[Question][1],
"Chosen Answer" : "Blank",
"Multiple Chocies" : TestQuestions[Question][0]}
return Test
class QuestionsScreen(Screen):
pass
class ResultScreen(Screen):
pass
class TestScreen(Screen):
pass
class QuizTestApp(App):
Status = BooleanProperty(False)
TestComplete = BooleanProperty(False)
Test = ObjectProperty()
PassMark = 70
TestCurrentQuestion = StringProperty()
CurrentQuestionText = StringProperty("1")
TotalQuestionsText = StringProperty("1")
ChosenAnswerText = StringProperty()
CurrentQuestion = 1
TotalQuestions = NumericProperty(1)
AnswerButtonA = StringProperty()
AnswerButtonB = StringProperty()
AnswerButtonC = StringProperty()
AnswerButtonD = StringProperty()
AnswerButtonA_state = StringProperty("normal")
AnswerButtonB_state = StringProperty("normal")
AnswerButtonC_state = StringProperty("normal")
AnswerButtonD_state = StringProperty("normal")
AnswerButtonA_color = ObjectProperty([1,1,1,1])
AnswerButtonB_color = ObjectProperty([1,1,1,1])
AnswerButtonC_color = ObjectProperty([1,1,1,1])
AnswerButtonD_color = ObjectProperty([1,1,1,1])
Score = NumericProperty()
CurrentQuestionWidgetList = []
StatsTestsCompleted = NumericProperty()
StatsTestsPassed = NumericProperty()
StatsQuestionsAnswered = NumericProperty()
StatsCorrectAnswers = NumericProperty()
StatsAverageResult = NumericProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.Status = False
self.CorrectAnswer = ""
self.TestComplete = False
self.CurrentQuestion = 1
self.Test = CreateTest()
self.TotalQuestions = 4
self.TotalQuestionsText = str(self.TotalQuestions)
self.UpdateQuestionAndAnswerButtons()
def UpdateChosenAnswer(self, button):
self.Test[self.CurrentQuestion]["Chosen Answer"] = button.text
self.ChosenAnswerText = self.Test[self.CurrentQuestion]["Chosen Answer"]
self.DisableSubmitButton()
def NextQuestion(self):
self.CurrentQuestion +=1
self.UpdateQuestionAndAnswerButtons()
def PreviousQuestion(self):
self.CurrentQuestion -=1
self.UpdateQuestionAndAnswerButtons()
def UpdateQuestionAndAnswerButtons(self):
self.CurrentQuestionText = str(self.CurrentQuestion)
self.TestCurrentQuestion = self.Test[self.CurrentQuestion]["Current Question"]
self.AnswerButtonA, self.AnswerButtonB, self.AnswerButtonC, self.AnswerButtonD = self.Test[self.CurrentQuestion]["Multiple Chocies"]
self.ChosenAnswerText = self.Test[self.CurrentQuestion]["Chosen Answer"]
self.HighLightButtonIfAnswered()
def HighLightButtonIfAnswered(self):
self.AnswerButtonA_state = "normal"
self.AnswerButtonB_state = "normal"
self.AnswerButtonC_state = "normal"
self.AnswerButtonD_state = "normal"
self.AnswerButtonA_color = [1,1,1,1]
self.AnswerButtonB_color = [1,1,1,1]
self.AnswerButtonC_color = [1,1,1,1]
self.AnswerButtonD_color = [1,1,1,1]
def func(button_text):
if self.Test[self.CurrentQuestion]["Chosen Answer"] == button_text:
return "down"
elif self.Test[self.CurrentQuestion]["Chosen Answer"] == "Blank":
return "normal"
else:
return "normal"
self.AnswerButtonA_state = func(self.AnswerButtonA)
self.AnswerButtonB_state = func(self.AnswerButtonB)
self.AnswerButtonC_state = func(self.AnswerButtonC)
self.AnswerButtonD_state = func(self.AnswerButtonD)
if self.Status == True: #Review mode
def color_func(button_text):
if self.Test[self.CurrentQuestion]["Chosen Answer"] == button_text:
if self.Test[self.CurrentQuestion]["Chosen Answer"] == self.Test[self.CurrentQuestion]["Correct Answer"]:
return [0,1,0,1] #Green
else:
return [1,0,0,1] #Red
elif self.Test[self.CurrentQuestion]["Correct Answer"] == button_text:
return [0,1,0,1] #Green
else:
return [1,1,1,0.5]
self.AnswerButtonA_color = color_func(self.AnswerButtonA)
self.AnswerButtonB_color = color_func(self.AnswerButtonB)
self.AnswerButtonC_color = color_func(self.AnswerButtonC)
self.AnswerButtonD_color = color_func(self.AnswerButtonD)
def SubmitTest(self):
if self.Status == False:
self.Score = self.CalculateScoreAndUpdateTestQuestionsBreakdown()
def DisableSubmitButton(self):
for Question in self.Test.keys():
if self.Test[Question]["Chosen Answer"] == "Blank":
self.TestComplete = False
break
else:
self.TestComplete = True
def CalculateScoreAndUpdateTestQuestionsBreakdown(self):
score = 0
for Question in self.Test.keys():
if self.Test[Question]["Chosen Answer"]== self.Test[Question]["Correct Answer"]:
score+=1
return score
def StartReview(self):
self.TestComplete = True
self.Status = True
self.CurrentQuestion = 1
self.CurrentQuestionText = str(self.CurrentQuestion)
def build(self):
sm = ScreenManager()
sm.add_widget(TestScreen(name='test'))
sm.add_widget(ResultScreen(name='result'))
return sm
QuizTestApp().run()
千伏
<Label>:
text_size: self.width, None
halign: "center"
<ResultScreen>
BoxLayout:
orientation: "vertical"
padding: "20px"
spacing: "20px"
BoxLayout:
orientation: "vertical"
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 >= app.PassMark else "FAIL"
BoxLayout:
size_hint: (1,None)
min_height: dp(10)
orientation: "horizontal"
spacing: "20px"
Button:
text: "Review Questions"
on_press: app.StartReview(); root.manager.current = "test"; app.UpdateQuestionAndAnswerButtons()
Button:
text: "exit"
on_press: app.get_running_app().stop()
<TestScreen>
id: TestScreen
BoxLayout:
orientation: "vertical"
BoxLayout:
id: TopNumbers
size_hint: 1, None
height: dp(30)
orientation: "horizontal"
BoxLayout:
id: TopNumbers2
orientation: "horizontal"
size_hint: 1, None
height: dp(30)
BoxLayout:
id: TopNumbers3
orientation: "horizontal"
size_hint: 1, None
height: dp(30)
BoxLayout:
padding: "20px"
orientation: "vertical"
Label:
text: app.TestCurrentQuestion
text_size: self.width, None
halign: "center"
GridLayout:
padding: "20px"
spacing: "20px"
cols: 2
rows: 2
ToggleButton:
id: AnswerButtonA
group: 1
color: app.AnswerButtonA_color
text: app.AnswerButtonA
on_press: app.UpdateChosenAnswer(AnswerButtonA)
state: app.AnswerButtonA_state
disabled: True if self.text == "" or app.Status else False
ToggleButton:
id: AnswerButtonB
group: 1
color: app.AnswerButtonB_color
text: app.AnswerButtonB
on_press: app.UpdateChosenAnswer(AnswerButtonB)
state: app.AnswerButtonB_state
disabled: True if self.text == "" or app.Status else False
ToggleButton:
id: AnswerButtonC
group: 1
color: app.AnswerButtonC_color
text: app.AnswerButtonC
on_press: app.UpdateChosenAnswer(AnswerButtonC)
state: app.AnswerButtonC_state
disabled: True if self.text == "" or app.Status else False
ToggleButton:
id: AnswerButtonD
group: 1
color: app.AnswerButtonD_color
text: app.AnswerButtonD
on_press: app.UpdateChosenAnswer(AnswerButtonD)
state: app.AnswerButtonD_state
disabled: True if self.text == "" or app.Status else False
BoxLayout:
size_hint: (1,None)
min_height: dp(10)
orientation: "horizontal"
padding: "20px"
spacing: "20px"
Button:
text: "Previous"
size_hint: (0.3,1)
on_press: AnswerButtonA.state = "normal"; AnswerButtonB.state = "normal"; AnswerButtonC.state = "normal"; AnswerButtonD.state = "normal"; app.PreviousQuestion()
disabled: True if app.CurrentQuestionText == "1" else False
Button:
text: " Close Review" if app.Status else "Answer All Questions" if app.TestComplete==False else "Submit"
#text_size: (50, None) if app.Status else (75, None) if app.TestComplete==False else (50, None)
size_hint: (0.4,1)
on_press: AnswerButtonA.state = "normal"; AnswerButtonB.state = "normal"; AnswerButtonC.state = "normal"; AnswerButtonD.state = "normal";
on_release: app.SubmitTest(); root.manager.current = "result"
disabled: True if app.Status==False and app.TestComplete==False else False
Button:
text: "Next"
size_hint: (0.3,1)
on_press: AnswerButtonA.state = "normal"; AnswerButtonB.state = "normal"; AnswerButtonC.state = "normal"; AnswerButtonD.state = "normal"; app.NextQuestion()
disabled: True if str(app.CurrentQuestionText) == str(app.TotalQuestions) else False
from kivy.lang import Builder
from kivymd.app import MDApp
KV = '''
MDFloatLayout:
MDFlatButton:
text: "MDFlatButton"
pos_hint: {'center_x': .5, 'center_y': .5}
disabled: True
disabled_color: "red"
'''
class Example(MDApp):
dialog = None
def build(self):
return Builder.load_string(KV)
Example().run()
它從 KivyMD 庫版本 1.0.0 開始工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.