【发布时间】:2018-03-26 09:46:08
【问题描述】:
关于以下代码,它是我的计算游戏应用程序的子集,我有两个问题:
1) 为什么dummy_series 没有绘制,虽然坐标轴(带有刻度和标签已绘制)
2) 如何获得退出按钮以正确退出应用程序(它是否必须从根小部件中删除所有小部件?是否有与 AppObject.run() 相反的,停止应用程序? - 已解决:App.get_running_app ().stop()
对于第一个问题,代码的相关部分在StatisticScreen 和PlotScreen 类中找到。第一个创建dummy_series,初始化图形小部件的创建并将屏幕更改为PlotScreen。在PlotScreen类中,有showPlot的方法,基本上是从github README复制过来的。
到目前为止,我尝试将整体背景颜色更改为白色。既是通过“画布之前”一个白色矩形,又是通过真正改变窗口的背景颜色。两者都没有效果(除了轴和标签被隐藏,因为它们也是白色的)。然后我尝试在每次创建图表时对图表进行不同的着色(取自同一个 github 存储库,if __name__ == '__main__': 中有一个 TestApp)。但仍然没有图表。
对于第二个问题,请考虑CalculationRoot 的changeScreen 方法。如果以quit 作为参数调用它,当前它只是清空screen_list 并返回False。这个想法是调用“返回”按钮的回调(key=27,1000)。由于使用“后退”按钮关闭应用程序实际上可以工作,鉴于screen_list 是空的,我想我可以使用这个现有的过程。同样调度app对象CalculationApp的keyHandler-方法也没有想要的关闭app的效果。
# Python build-in Modules
import os
import operator # better handling of +, #, *, etc.
import webbrowser # access homepages via the about section
import random # create random math questions
import datetime # for the timer
import itertools # eg for cycling colors
from functools import partial # schedule callback functions that take arguments different from 'dt'
# Kivy
from kivy.lang.builder import Builder
from kivy.app import App
from kivy.core.window import Window
from kivy.utils import platform
from kivy.uix.screenmanager import Screen
from kivy.properties import ObjectProperty, NumericProperty, StringProperty
from kivy.storage.dictstore import DictStore
from kivy.utils import get_color_from_hex as rgb
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.uix.scrollview import ScrollView
from kivy.clock import Clock
from kivy.uix.label import Label
from kivy.logger import Logger
from kivy.garden.graph import Graph, MeshLinePlot, SmoothLinePlot
# Non-standard python
import numpy as np
###############################################################################
# Constants
###############################################################################
BACKGROUND_COLOR = [0,0,0,0]
TEXT_COLOR = [1,1,1,1]
kv_string = """
#:import Factory kivy.factory.Factory
#:set color_button (0.784, 0.4, 0.216, 1) # brown
#:set color_button_pressed (0.659, 0.3, 0.431, 1) # darker brown
#:set color_background_down '(0.4, 0.4, 0.4, 1)' # purple
<WrappedLabel@Label>:
size_hint_y: None
height: self.texture_size[1] + self.texture_size[1]/2
markup: True
<GridLabel@Label>:
font_size: min(root.width, root.height) * .3
<StatisticsSpinner@Spinner>:
background_color: color_button if self.state == 'normal' else color_button_pressed
background_down: color_background_down
option_cls: Factory.get("SpinnerLabel")
<SpinnerLabel@SpinnerOption>:
background_color: color_button if self.state == 'down' else color_button_pressed
background_down: color_background_down
<CalculationRoot>:
orientation: 'vertical'
cg_screen_manager: cg_screen_manager
statistic_screen: statistic_screen
plot_screen: plot_screen
ScreenManager:
id: cg_screen_manager
StartScreen:
name: 'StartScreen'
StatisticScreen:
id: statistic_screen
name: 'StatisticScreen'
PlotScreen:
id: plot_screen
name: 'PlotScreen'
<StartScreen@Screen>:
BoxLayout:
orientation: 'vertical'
padding: root.width * .02, root.height * .02
spacing: min(root.width, root.height) * .02
WrappedLabel:
text: '[b] Calculation Game [/b]'
font_size: min(root.width, root.height) * .1
Button:
text: 'Statistic'
on_release: app.root.changeScreen(self.text.lower())
Button:
text: 'Quit'
<StatisticScreen@Screen>:
stats_operation_spinner: stats_operation_spinner
stats_difficulty_spinner: stats_difficulty_spinner
stats_num_questions_button: stats_num_questions_button
BoxLayout:
orientation: 'vertical'
padding: root.width * .02, root.height * .02
spacing: min(root.width, root.height) * .02
WrappedLabel:
text: '[b] Statistics [/b]'
halign: 'center'
font_size: min(root.width, root.height) * .1
GridLayout:
size_hint: .9,.4
cols: 2
pos_hint: {'center_x': .5}
GridLabel:
text: 'Operation Type'
StatisticsSpinner:
id: stats_operation_spinner
text: '+'
values: ['+', '-', '*', ':', '%']
GridLabel:
text: 'Difficulty'
StatisticsSpinner:
id: stats_difficulty_spinner
text: '1'
values: ['1','2','3','4']
GridLabel:
text: 'Number of Questions'
Button:
id: stats_num_questions_button
text: '8'
on_release: app.root.statistic_screen.switchNumQuestions(self, self.text)
# on_release: self.text = '16' if self.text == '8' else self.text = '8'
background_color: color_button if self.state == 'normal' else color_button_pressed
Button:
size_hint: 1, .2
text: 'Plot'
on_release: app.root.statistic_screen.showPlot()
font_size: min(root.width, root.height) * .1
<PlotScreen@Screen>:
"""
###############################################################################
# Widgets
###############################################################################
class StatisticScreen(Screen):
""" Selection screen, where you can fix the parameters for
a pot of your statistics.
"""
def __init__(self, *args, **kwargs):
super(StatisticScreen, self).__init__(*args, **kwargs)
def showPlot(self):
""" 'onPlotButtonPress'
callback for the 'plot'-Button on the bottom of StatisticScreen
"""
dummy_series = np.random.randint(1, 10, (12,))
App.get_running_app().root.ids.plot_screen.createKivyPlot(dummy_series)
App.get_running_app().root.changeScreen('plot')
def switchNumQuestions(self, instance, text):
""" 'onNumQuestionsButtonPress'
callback for the 'choose number of questions'-button.
"""
if int(text) == 16:
instance.text = '8'
else:
instance.text = '16'
class PlotScreen(Screen):
def __init__(self, *args, **kwargs):
super(PlotScreen, self).__init__(*args, **kwargs)
self.series = None
self.graph_figure = None # error if uncommented... why? (referred to former name self.canvas)
self.colors = itertools.cycle([rgb('7dac9f'), rgb('dc7062'), rgb('66a8d4'), rgb('e5b060')])
def createKivyPlot(self, series=np.array(range(12))):
graph_theme = {
'label_options': {
'color': rgb('444444'), # color of tick labels and titles
'bold': True},
'background_color': rgb('f8f8f2'), # back ground color of canvas
'tick_color': rgb('808080'), # ticks and grid
'border_color': rgb('808080')} # border drawn around each graph
self.graph_figure = Graph(xlabel='Last 12 games', ylabel='Average Response Time', x_ticks_minor=1,
x_ticks_major=5, y_ticks_major=1,
y_grid_label=True, x_grid_label=True, padding=10,
x_grid=True, y_grid=True, xmin=0, xmax=len(series), ymin=0, ymax=int(1.5*max(series)), **graph_theme)
plot = SmoothLinePlot(mode='line_strip', color=next(self.colors))
plot.points = [(x, series[x]) for x in range(0, len(series))]
self.graph_figure.add_plot(plot)
self.add_widget(self.graph_figure)
def destroy(self):
self.remove_widget(self.graph_figure)
self.graph_figure = None
###############################################################################
# Root Widget
###############################################################################
class CalculationRoot(BoxLayout):
""" Root of all widgets
"""
calculation_screen = ObjectProperty(None)
def __init__(self, *args, **kwargs):
super(CalculationRoot, self).__init__(*args, **kwargs)
self.screen_list = [] # previously visited screens
def changeScreen(self, next_screen):
if self.screen_list == [] or self.ids.cg_screen_manager.current != self.screen_list[-1]:
self.screen_list.append(self.ids.cg_screen_manager.current)
if next_screen == 'start':
self.ids.cg_screen_manager.current = 'StartScreen'
elif next_screen == 'statistic':
self.ids.cg_screen_manager.current = 'StatisticScreen'
elif next_screen == 'plot':
self.ids.cg_screen_manager.current = 'PlotScreen'
elif next_screen == 'quit':
self.screen_list == []
#self.onBackBtnPress() # not working
#Clock.schedule_once(partial(App.get_running_app().keyHandler(27)), 0) # not working
return False
def onBackBtnPress(self):
if self.screen_list:
self.ids.cg_screen_manager.current = self.screen_list.pop()
return True
return False
###############################################################################
# App Object
###############################################################################
class CalculationApp(App):
""" App object
"""
def __init__(self, *args, **kwargs):
super(CalculationApp, self).__init__(*args, **kwargs)
self.use_kivy_settings = False
def keyHandler(self, *args):
key = args[1]
print(key)
if key in (1000, 27):
return self.root.onBackBtnPress()
def post_build_init(self, ev):
if platform == 'android':
pass
win = self._app_window
win.bind(on_keyboard = self.keyHandler)
def build(self):
Builder.load_string(kv_string)
self.bind(on_start=self.post_build_init)
return CalculationRoot()
if __name__ in ('__main__', '__android__'):
CalculationApp().run()
【问题讨论】:
-
关闭应用可以使用
App.get_running_app().stop()