[英]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.