forked from Epihaius/DirectGui-layout-system
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
275 lines (219 loc) · 11.2 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
#!/usr/bin/env python
# Author: Epihaius
# Date: 2019-09-23
# Last revision: 2020-10-08
#
# This is a basic example of how to use the sizer-based GUI system.
from panda3d.core import *
from direct.showbase.ShowBase import ShowBase
from direct.gui.DirectGui import *
from gui import *
class MyApp:
def __init__(self):
# initialize the Panda3D showbase
self.showbase = showbase = ShowBase()
# the root node of all DirectGui widgets needs to be pixel2d in order to work
# with the automatic layout system
self.gui_root = gui_root = showbase.pixel2d
# initialize the GUI system
self.gui = gui = GUI(showbase)
# Build the GUI layout
# add a horizontally expanding title bar
title = "Panda3D: GUI layout example"
label = DirectLabel(parent=gui_root, text=title, frameSize=(0, 0, -20, 30),
text_scale=20, borderWidth=(6, 6), relief=DGG.SUNKEN)
widget = Widget(label)
borders = (10, 10, 20, 10)
# by default, the title bar will take up all of the width and height of its
# cell (the default value for the `alignments` parameter of the `Sizer.add`
# method is `("expand", "expand")`), but the cell itself still needs to be
# able to take up the entire width of the window; this is done by setting
# the horizontal proportion (which gets applied to the cell's column) to a
# value bigger than zero
gui.sizer.add(widget, proportions=(1., 0.), borders=borders)
# add a horizontally growable sizer that will be expanded horizontally
self.frame_area_sizer = sizer = Sizer("horizontal")
borders = (10, 10, 20, 10)
gui.sizer.add(sizer, proportions=(1., 0.), borders=borders)
# add a vertically growable subsizer to the previous sizer;
# set the vertical gap between each two of its cells to 10 pixels
# (this is a more convenient alternative to setting the same borders
# for all but the last of its cells, i.e. `(0, 0, 10, 0)`)
btn_sizer = Sizer("vertical", gaps=(0, 10))
borders = (0, 20, 0, 0)
sizer.add(btn_sizer, borders=borders)
# add horizontally expanding buttons to the subsizer;
# they will have the same width, determined by the initially largest button
text = "Add button to frame"
button = DirectButton(parent=gui_root, text=text, text_scale=20,
borderWidth=(2, 2), command=self.__add_button)
widget = Widget(button)
btn_sizer.add(widget)
text = "Add checkbutton to frame"
button = DirectButton(parent=gui_root, text=text, text_scale=20,
borderWidth=(2, 2), command=self.__add_checkbutton)
widget = Widget(button)
btn_sizer.add(widget)
text = "Add radiobuttons to frame"
button = DirectButton(parent=gui_root, text=text, text_scale=20,
borderWidth=(2, 2), command=self.__add_radiobuttons)
widget = Widget(button)
btn_sizer.add(widget)
text = "Add menu to frame"
button = DirectButton(parent=gui_root, text=text, text_scale=20,
borderWidth=(2, 2), command=self.__add_menu)
widget = Widget(button)
btn_sizer.add(widget)
text = "Add slider to frame"
button = DirectButton(parent=gui_root, text=text, text_scale=20,
borderWidth=(2, 2), command=self.__add_slider)
widget = Widget(button)
btn_sizer.add(widget)
# add vertical space with a fixed size
btn_sizer.add((0, 30))
text = "Destroy frame"
button = DirectButton(parent=gui_root, text=text, text_scale=25,
textMayChange=True, borderWidth=(3, 3), command=self.__toggle_frame)
self.frame_toggle_button = widget = Widget(button)
btn_sizer.add(widget)
# add some horizontally stretching space, so that widgets added after it
# will be pushed to the right
sizer.add((0, 0), proportions=(1., 0.))
self.has_frame = False
# add a frame resizable in both directions and taking up two thirds of
# the available horizontal space (because of the ratio of the proportions
# used for the frame and the stretching space that was previously added)
frame = self.__toggle_frame(update_layout=False)
frame_sizer = self.frame_sizer
# add a non-resizing input field, centered horizontally and vertically within
# its cell, which itself is assigned all of the space available to it, by
# setting its proportions to 1.0
field = DirectEntry(parent=gui_root, text_scale=20, focus=1)
widget = Widget(field)
gui.sizer.add(widget, proportions=(1., 1.), alignments=("center", "center"))
# add a horizontally expanding status bar
status_text = "GUI ready and awaiting input"
label = DirectLabel(parent=gui_root, text=status_text, text_pos=(20, -10),
textMayChange=1, frameSize=(0, 0, -10, 10), text_scale=20,
text_align=TextNode.A_left)
widget = Widget(label)
borders = (10, 10, 10, 20)
gui.sizer.add(widget, proportions=(1., 0.), borders=borders)
# let the GUI system create the layout
gui.layout()
# run the app
showbase.run()
def __toggle_frame(self, update_layout=True):
self.has_frame = not self.has_frame
if self.has_frame:
# add a frame resizable in both directions and taking up two thirds of
# the available horizontal space (because of the ratio of the proportions
# used for the frame and the stretching space that was previously added)
self.frame = frame = DirectFrame(parent=self.gui_root, frameColor=(.5, .6, .7, 1.))
self.frame_widget = widget = Widget(frame)
self.frame_area_sizer.add(widget, proportions=(2., 1.))
# assign a sizer to the frame to manage the layout of its child widgets
self.frame_sizer = frame_sizer = Sizer("vertical")
widget.sizer = self.frame_sizer
# add a horizontally expanding label with right-aligned text to the frame
text = "right-aligned text"
label = DirectLabel(parent=frame, text=text,
text_scale=20, text_align=TextNode.A_right)
widget = Widget(label)
borders = (10, 10, 20, 10)
frame_sizer.add(widget, proportions=(1., 0.), borders=borders)
# add some vertically stretching space to the frame, so that widgets added
# after it will be pushed downwards
frame_sizer.add((0, 0), proportions=(0., 1.))
# add a non-resizing, right-aligned button to the frame
text = "Button in frame "
button = DirectButton(parent=frame, text=text, text_scale=20, borderWidth=(2, 2))
widget = Widget(button)
borders = (0, 10, 10, 20)
frame_sizer.add(widget, alignments=("max", "min"), borders=borders)
self.frame_toggle_button.dgui_obj["text"] = "Destroy frame"
else:
# remove the frame, destroying it and all of its child widgets
self.frame_area_sizer.remove_cell(self.frame_widget.sizer_cell, destroy=True)
self.frame = frame = None
# make the button text very long to see how it affects the layout
text = "Create a new frame to the right"
self.frame_toggle_button.dgui_obj["text"] = text
if update_layout:
self.frame_toggle_button.reset_frame_size()
# update the GUI layout
self.gui.layout()
return frame
def __add_button(self):
if not self.has_frame:
return
def remove_button():
self.frame_sizer.remove_cell(widget.sizer_cell, destroy=True)
self.gui.layout()
button = DirectButton(parent=self.frame, text=("Feel free to remove me", "Goodbye!",
"Yeah I'm still here", "Nobody home"), borderWidth=(6, 6),
text_scale=20, command=remove_button)
widget = Widget(button)
borders = (10, 10, 10, 10)
# add the button to the frame, below the right-aligned text label, using index=1
self.frame_sizer.add(widget, proportions=(1., 0.), borders=borders, index=1)
# update the GUI layout
self.gui.layout()
def __add_checkbutton(self):
if not self.has_frame:
return
btn = DirectCheckButton(parent=self.frame, text="CheckButton",
text_scale=20, boxPlacement="right", borderWidth=(2, 2), indicator_text_scale=20,
indicator_text_pos=(0, 4), indicator_borderWidth=(2, 2), boxBorder=1)
widget = Widget(btn)
borders = (10, 10, 10, 10)
# add the checkbutton to the frame, below the right-aligned text label, using index=1
self.frame_sizer.add(widget, proportions=(1., 0.), borders=borders, index=1)
# update the GUI layout
self.gui.layout()
def __add_radiobuttons(self):
if not self.has_frame:
return
v = [0]
buttons = [
DirectRadioButton(parent=self.frame, text='RadioButton0', variable=v,
value=[0], boxPlacement="right", text_scale=20, indicator_text_pos=(0, 5),
borderWidth=(2, 2), indicator_text_scale=20, indicator_borderWidth=(2, 2)),
DirectRadioButton(parent=self.frame, text='RadioButton1', variable=v,
value=[1], boxPlacement="right", text_scale=20, indicator_text_pos=(0, 5),
borderWidth=(2, 2), indicator_text_scale=20, indicator_borderWidth=(2, 2))
]
borders = (10, 10, 10, 10)
for button in reversed(buttons):
widget = Widget(button)
# add the radiobuttons to the frame, below the right-aligned text label, using index=1
self.frame_sizer.add(widget, proportions=(1., 0.), borders=borders, index=1)
button.setOthers(buttons)
# update the GUI layout
self.gui.layout()
def __add_menu(self):
if not self.has_frame:
return
menu = DirectOptionMenu(parent=self.frame, text="options", scale=20,
borderWidth=(.3, .3), items=["item1","item2","item3"], initialitem=2,
frameSize=(0, .25, -.75, .75), highlightColor=(.65, .65, .65, 1.),
text_pos=(.5, -.25), popupMarkerBorder=(.6, 0.))
widget = Widget(menu)
borders = (10, 10, 10, 10)
# add the menu to the frame, below the right-aligned text label, using index=1
self.frame_sizer.add(widget, proportions=(1., 0.), borders=borders, index=1)
# update the GUI layout
self.gui.layout()
def __add_slider(self):
if not self.has_frame:
return
slider = DirectSlider(parent=self.frame, range=(0,100), value=50,
pageSize=10, thumb_frameSize=(-10, 10, -15, 15), frameSize=(0, 0, -15, 15),
frameColor=(.3, .3, .3, 1.), borderWidth=(3, 3))
widget = Widget(slider)
borders = (10, 10, 10, 10)
# add the slider to the frame, below the right-aligned text label, using index=1
self.frame_sizer.add(widget, proportions=(1., 0.), borders=borders, index=1)
# update the GUI layout
self.gui.layout()
MyApp()