menu_05.py Full Listing
menu_05.py
1"""
2Menu.
3
4Shows the usage of almost every gui widget, switching views and making a modal.
5"""
6
7from typing import List
8
9import arcade
10import arcade.gui
11
12# Screen title and size
13SCREEN_WIDTH = 800
14SCREEN_HEIGHT = 600
15SCREEN_TITLE = "Making a Menu"
16
17
18class MainView(arcade.View):
19 """This is the class where your normal game would go."""
20
21 def __init__(self):
22 super().__init__()
23
24 self.manager = arcade.gui.UIManager()
25
26 switch_menu_button = arcade.gui.UIFlatButton(text="Pause", width=150)
27
28 # Initialise the button with an on_click event.
29 @switch_menu_button.event("on_click")
30 def on_click_switch_button(event):
31 # Passing the main view into menu view as an argument.
32 menu_view = MenuView(self)
33 self.window.show_view(menu_view)
34
35 # Use the anchor to position the button on the screen.
36 self.anchor = self.manager.add(arcade.gui.UIAnchorLayout())
37
38 self.anchor.add(
39 anchor_x="center_x",
40 anchor_y="center_y",
41 child=switch_menu_button,
42 )
43
44 def on_hide_view(self):
45 # Disable the UIManager when the view is hidden.
46 self.manager.disable()
47
48 def on_show_view(self):
49 """This is run once when we switch to this view"""
50 arcade.set_background_color(arcade.color.DARK_BLUE_GRAY)
51
52 # Enable the UIManager when the view is showm.
53 self.manager.enable()
54
55 def on_draw(self):
56 """Render the screen."""
57 # Clear the screen
58 self.clear()
59
60 # Draw the manager.
61 self.manager.draw()
62
63
64class MenuView(arcade.View):
65 """Main menu view class."""
66
67 def __init__(self, main_view):
68 super().__init__()
69
70 self.manager = arcade.gui.UIManager()
71
72 resume_button = arcade.gui.UIFlatButton(text="Resume", width=150)
73 start_new_game_button = arcade.gui.UIFlatButton(text="Start New Game", width=150)
74 volume_button = arcade.gui.UIFlatButton(text="Volume", width=150)
75 options_button = arcade.gui.UIFlatButton(text="Options", width=150)
76
77 exit_button = arcade.gui.UIFlatButton(text="Exit", width=320)
78
79 # Initialise a grid in which widgets can be arranged.
80 self.grid = arcade.gui.UIGridLayout(
81 column_count=2, row_count=3, horizontal_spacing=20, vertical_spacing=20
82 )
83
84 # Adding the buttons to the layout.
85 self.grid.add(resume_button, column=0, row=0)
86 self.grid.add(start_new_game_button, column=1, row=0)
87 self.grid.add(volume_button, column=0, row=1)
88 self.grid.add(options_button, column=1, row=1)
89 self.grid.add(exit_button, column=0, row=2, column_span=2)
90
91 self.anchor = self.manager.add(arcade.gui.UIAnchorLayout())
92
93 self.anchor.add(
94 anchor_x="center_x",
95 anchor_y="center_y",
96 child=self.grid,
97 )
98
99 self.main_view = main_view
100
101 @resume_button.event("on_click")
102 def on_click_resume_button(event):
103 # Pass already created view because we are resuming.
104 self.window.show_view(self.main_view)
105
106 @start_new_game_button.event("on_click")
107 def on_click_start_new_game_button(event):
108 # Create a new view because we are starting a new game.
109 main_view = MainView()
110 self.window.show_view(main_view)
111
112 @exit_button.event("on_click")
113 def on_click_exit_button(event):
114 arcade.exit()
115
116 @volume_button.event("on_click")
117 def on_click_volume_button(event):
118 volume_menu = SubMenu(
119 "Volume Menu",
120 "How do you like your volume?",
121 "Enable Sound",
122 [
123 "Play: Rock",
124 "Play: Punk",
125 "Play: Pop",
126 "Play: Jazz",
127 "Play: Blues",
128 "Play: Classical",
129 "Play: Country",
130 "Play: Electronic",
131 "Play: Hip Hop",
132 "Play: Metal",
133 "Play: R&B",
134 "Play: Reggae",
135 ],
136 "Adjust Volume",
137 )
138 self.manager.add(volume_menu, layer=1)
139
140 @options_button.event("on_click")
141 def on_click_options_button(event):
142 options_menu = SubMenu(
143 "Funny Menu",
144 "Too much fun here",
145 "Fun?",
146 [
147 "Make Fun",
148 "Enjoy Fun",
149 "Like Fun",
150 "Share Fun",
151 "Spread Fun",
152 "Find Fun",
153 "Create Fun",
154 "Discover Fun",
155 "Embrace Fun",
156 "Celebrate Fun",
157 "Inspire Fun",
158 "Maximize Fun",
159 ],
160 "Adjust Fun",
161 )
162 self.manager.add(options_menu, layer=1)
163
164 def on_hide_view(self):
165 # Disable the UIManager when the view is hidden.
166 self.manager.disable()
167
168 def on_show_view(self):
169 """This is run once when we switch to this view"""
170
171 # Makes the background darker
172 arcade.set_background_color([rgb - 50 for rgb in arcade.color.DARK_BLUE_GRAY])
173
174 # Enable the UIManager when the view is showm.
175 self.manager.enable()
176
177 def on_draw(self):
178 """Render the screen."""
179 # Clear the screen
180 self.clear()
181 self.manager.draw()
182
183
184class SubMenu(arcade.gui.UIMouseFilterMixin, arcade.gui.UIAnchorLayout):
185 """Acts like a fake view/window."""
186
187 def __init__(
188 self,
189 title: str,
190 input_text: str,
191 toggle_label: str,
192 dropdown_options: List[str],
193 slider_label: str,
194 ):
195 super().__init__(size_hint=(1, 1))
196
197 # Setup frame which will act like the window.
198 frame = self.add(arcade.gui.UIAnchorLayout(width=300, height=400, size_hint=None))
199 frame.with_padding(all=20)
200
201 # Add a background to the window.
202 # Nine patch smoothes the edges.
203 frame.with_background(
204 texture=arcade.gui.NinePatchTexture(
205 left=7,
206 right=7,
207 bottom=7,
208 top=7,
209 texture=arcade.load_texture(
210 ":resources:gui_basic_assets/window/dark_blue_gray_panel.png"
211 ),
212 )
213 )
214
215 back_button = arcade.gui.UIFlatButton(text="Back", width=250)
216 # The type of event listener we used earlier for the button will not work here.
217 back_button.on_click = self.on_click_back_button
218
219 title_label = arcade.gui.UILabel(text=title, align="center", font_size=20, multiline=False)
220 # Adding some extra space around the title.
221 title_label_space = arcade.gui.UISpace(height=30, color=arcade.color.DARK_BLUE_GRAY)
222
223 input_text_widget = arcade.gui.UIInputText(text=input_text, width=250).with_border()
224
225 # Load the on-off textures.
226 on_texture = arcade.load_texture(
227 ":resources:gui_basic_assets/simple_checkbox/circle_on.png"
228 )
229 off_texture = arcade.load_texture(
230 ":resources:gui_basic_assets/simple_checkbox/circle_off.png"
231 )
232
233 # Create the on-off toggle and a label
234 toggle_label = arcade.gui.UILabel(text=toggle_label)
235 toggle = arcade.gui.UITextureToggle(
236 on_texture=on_texture, off_texture=off_texture, width=20, height=20
237 )
238
239 # Align toggle and label horizontally next to each other
240 toggle_group = arcade.gui.UIBoxLayout(vertical=False, space_between=5)
241 toggle_group.add(toggle)
242 toggle_group.add(toggle_label)
243
244 # Create dropdown with a specified default.
245 # When many options are provided, the dropdown automatically scrolls.
246 dropdown = arcade.gui.UIDropdown(
247 default=dropdown_options[0],
248 options=dropdown_options,
249 height=20,
250 width=250,
251 show_scroll_bar=True,
252 )
253
254 slider_label = arcade.gui.UILabel(text=slider_label)
255 pressed_style = arcade.gui.UISlider.UIStyle(
256 filled_track=arcade.color.GREEN, unfilled_track=arcade.color.RED
257 )
258 default_style = arcade.gui.UISlider.UIStyle()
259 style_dict = {
260 "press": pressed_style,
261 "normal": default_style,
262 "hover": default_style,
263 "disabled": default_style,
264 }
265 # Configuring the styles is optional.
266 slider = arcade.gui.UISlider(value=50, width=250, style=style_dict)
267
268 widget_layout = arcade.gui.UIBoxLayout(align="left", space_between=10)
269 widget_layout.add(title_label)
270 widget_layout.add(title_label_space)
271 widget_layout.add(input_text_widget)
272 widget_layout.add(toggle_group)
273 widget_layout.add(dropdown)
274 widget_layout.add(slider_label)
275 widget_layout.add(slider)
276
277 widget_layout.add(back_button)
278
279 frame.add(child=widget_layout, anchor_x="center_x", anchor_y="top")
280
281 def on_click_back_button(self, event):
282 # Removes the widget from the manager.
283 # After this the manager will respond to its events like it previously did.
284 self.parent.remove(self)
285
286
287def main():
288 window = arcade.Window(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_TITLE, resizable=True)
289 main_view = MainView()
290 window.show_view(main_view)
291 arcade.run()
292
293
294if __name__ == "__main__":
295 main()