⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 buttons.py

📁 minimal python variant for small footprint apps like embedded apps
💻 PY
字号:
# Module 'Buttons'# Import module 'rect' renamed as '_rect' to avoid exporting it on# 'from Buttons import *'#import rect_rect = rectdel rect# Field indices in mouse event detail#_HV = 0_CLICKS = 1_BUTTON = 2_MASK = 3# LabelAppearance provides defaults for all appearance methods.# selected state not visible# disabled --> crossed out# hilited  --> inverted#class LabelAppearance:	#	# Initialization	#	def init_appearance(self):		self.bounds = _rect.empty		self.enabled = 1		self.hilited = 0		self.selected = 0		self.text = ''	#	# Size enquiry	#	def getminsize(self, m, (width, height)):		width = max(width, m.textwidth(self.text) + 6)		height = max(height, m.lineheight() + 6)		return width, height	#	def getbounds(self):		return self.bounds	#	# Changing the parameters	#	def settext(self, text):		self.text = text		if self.bounds <> _rect.empty:			self.recalctextpos()			self.redraw()	#	def setbounds(self, bounds):		self.bounds = bounds		if self.bounds <> _rect.empty:			self.recalc()	#	def realize(self):		pass	#	# Changing the state bits	#	def enable(self, flag):		if flag <> self.enabled:			self.enabled = flag			if self.bounds <> _rect.empty:				self.flipenable(self.parent.begindrawing())	#	def hilite(self, flag):		if flag <> self.hilited:			self.hilited = flag			if self.bounds <> _rect.empty:				self.fliphilite(self.parent.begindrawing())	#	def select(self, flag):		if flag <> self.selected:			self.selected = flag			if self.bounds <> _rect.empty:				self.redraw()	#	# Recalculate the box bounds and text position.	# This can be overridden by buttons that draw different boxes	# or want their text in a different position.	#	def recalc(self):		if self.bounds <> _rect.empty:			self.recalcbounds()			self.recalctextpos()	#	def recalcbounds(self):		self.hilitebounds = _rect.inset(self.bounds, (3, 3))		self.crossbounds = self.bounds	#	def recalctextpos(self):		(left, top), (right, bottom) = self.bounds		m = self.parent.beginmeasuring()		h = (left + right - m.textwidth(self.text)) / 2		v = (top + bottom - m.lineheight()) / 2		self.textpos = h, v	#	# Generic drawing interface.	# Do not override redraw() or draw() methods; override drawit() c.s.	#	def redraw(self):		if self.bounds <> _rect.empty:			d = self.parent.begindrawing()			d.erase(self.bounds)			self.draw(d, self.bounds)	#	def draw(self, d, area):		area = _rect.intersect([area, self.bounds])		if area == _rect.empty:			return		d.cliprect(area)		self.drawit(d)		d.noclip()	#	# The drawit() method is fairly generic but may be overridden.	#	def drawit(self, d):		self.drawpict(d)		if self.text:			d.text(self.textpos, self.text)		if not self.enabled:			self.flipenable(d)		if self.hilited:			self.fliphilite(d)	#	# Default drawing detail functions.	# Overriding these is normally sufficient to get different	# appearances.	#	def drawpict(self, d):		pass	#	def flipenable(self, d):		_xorcross(d, self.crossbounds)	#	def fliphilite(self, d):		d.invert(self.hilitebounds)# A Strut is a label with no width of its own.class StrutAppearance(LabelAppearance):	#	def getminsize(self, m, (width, height)):		height = max(height, m.lineheight() + 6)		return width, height	## ButtonAppearance displays a centered string in a box.# selected --> bold border# disabled --> crossed out# hilited  --> inverted#class ButtonAppearance(LabelAppearance):	#	def drawpict(self, d):		d.box(_rect.inset(self.bounds, (1, 1)))		if self.selected:			# Make a thicker box			d.box(self.bounds)			d.box(_rect.inset(self.bounds, (2, 2)))			d.box(_rect.inset(self.bounds, (3, 3)))	## CheckAppearance displays a small square box and a left-justified string.# selected --> a cross appears in the box# disabled --> whole button crossed out# hilited  --> box is inverted#class CheckAppearance(LabelAppearance):	#	def getminsize(self, m, (width, height)):		minwidth = m.textwidth(self.text) + 6		minheight = m.lineheight() + 6		width = max(width, minwidth + minheight + m.textwidth(' '))		height = max(height, minheight)		return width, height	#	def drawpict(self, d):		d.box(self.boxbounds)		if self.selected: _xorcross(d, self.boxbounds)	#	def recalcbounds(self):		LabelAppearance.recalcbounds(self)		(left, top), (right, bottom) = self.bounds		self.size = bottom - top - 4		self.boxbounds = (left+2, top+2), (left+2+self.size, bottom-2)		self.hilitebounds = self.boxbounds	#	def recalctextpos(self):		m = self.parent.beginmeasuring()		(left, top), (right, bottom) = self.boxbounds		h = right + m.textwidth(' ')		v = top + (self.size - m.lineheight()) / 2		self.textpos = h, v	## RadioAppearance displays a round indicator and a left-justified string.# selected --> a dot appears in the indicator# disabled --> whole button crossed out# hilited  --> indicator is inverted#class RadioAppearance(CheckAppearance):	#	def drawpict(self, d):		(left, top), (right, bottom) = self.boxbounds		radius = self.size / 2		center = left + radius, top + radius		d.circle(center, radius)		if self.selected:			d.fillcircle(center, radius*3/5)	## NoReactivity ignores mouse events.#class NoReactivity:	def init_reactivity(self): pass# BaseReactivity defines hooks and asks for mouse events,# but provides only dummy mouse event handlers.# The trigger methods call the corresponding hooks set by the user.# Hooks (and triggers) mean the following:# down_hook	called on some mouse-down events# move_hook	called on some mouse-move events# up_hook	called on mouse-up events# on_hook	called for buttons with on/off state, when it goes on# hook		called when a button 'fires' or a radiobutton goes on# There are usually extra conditions, e.g., hooks are only called# when the button is enabled, or active, or selected (on).#class BaseReactivity:	#	def init_reactivity(self):		self.down_hook = self.move_hook = self.up_hook = \			self.on_hook = self.off_hook = \			self.hook = self.active = 0		self.parent.need_mouse(self)	#	def mousetest(self, hv):		return _rect.pointinrect(hv, self.bounds)	#	def mouse_down(self, detail):		pass	#	def mouse_move(self, detail):		pass	#	def mouse_up(self, detail):		pass	#	def down_trigger(self):		if self.down_hook: self.down_hook(self)	#	def move_trigger(self):		if self.move_hook: self.move_hook(self)	#	def up_trigger(self):		if self.up_hook: self.up_hook(self)	#	def on_trigger(self):		if self.on_hook: self.on_hook(self)	#	def off_trigger(self):		if self.off_hook: self.off_hook(self)	#	def trigger(self):		if self.hook: self.hook(self)# ToggleReactivity acts like a simple pushbutton.# It toggles its hilite state on mouse down events.#class ToggleReactivity(BaseReactivity):	#	def mouse_down(self, detail):		if self.enabled and self.mousetest(detail[_HV]):			self.active = 1			self.hilite(not self.hilited)			self.down_trigger()	#	def mouse_move(self, detail):		if self.active:			self.move_trigger()	#	def mouse_up(self, detail):		if self.active:			self.up_trigger()			self.active = 0	#	def down_trigger(self):		if self.hilited:			self.on_trigger()		else:			self.off_trigger()		self.trigger()	## TriggerReactivity acts like a fancy pushbutton.# It hilites itself while the mouse is down within its bounds.#class TriggerReactivity(BaseReactivity):	#	def mouse_down(self, detail):		if self.enabled and self.mousetest(detail[_HV]):			self.active = 1			self.hilite(1)			self.down_trigger()	#	def mouse_move(self, detail):		if self.active:			self.hilite(self.mousetest(detail[_HV]))			if self.hilited:				self.move_trigger()	#	def mouse_up(self, detail):		if self.active:			self.hilite(self.mousetest(detail[_HV]))			if self.hilited:				self.up_trigger()				self.trigger()			self.active = 0			self.hilite(0)	## CheckReactivity handles mouse events like TriggerReactivity,# It overrides the up_trigger method to flip its selected state.#class CheckReactivity(TriggerReactivity):	#	def up_trigger(self):		self.select(not self.selected)		if self.selected:			self.on_trigger()		else:			self.off_trigger()		self.trigger()# RadioReactivity turns itself on and the other buttons in its group# off when its up_trigger method is called.#class RadioReactivity(TriggerReactivity):	#	def init_reactivity(self):		TriggerReactivity.init_reactivity(self)		self.group = []	#	def up_trigger(self):		for b in self.group:			if b <> self:				if b.selected:					b.select(0)					b.off_trigger()		self.select(1)		self.on_trigger()		self.trigger()# Auxiliary class for 'define' method.# Call the initializers in the right order.#class Define:	#	def define(self, parent):		self.parent = parent		parent.addchild(self)		self.init_appearance()		self.init_reactivity()		return self	#	def destroy(self):		self.parent = 0	#	def definetext(self, parent, text):		self = self.define(parent)		self.settext(text)		return self# Subroutine to cross out a rectangle.#def _xorcross(d, bounds):	((left, top), (right, bottom)) = bounds	# This is s bit funny to make it look better	left = left + 2	right = right - 2	top = top + 2	bottom = bottom - 3	d.xorline(((left, top), (right, bottom)))	d.xorline((left, bottom), (right, top))# Ready-made button classes.#class Label(NoReactivity, LabelAppearance, Define): passclass Strut(NoReactivity, StrutAppearance, Define): passclass PushButton(TriggerReactivity, ButtonAppearance, Define): passclass CheckButton(CheckReactivity, CheckAppearance, Define): passclass RadioButton(RadioReactivity, RadioAppearance, Define): passclass ToggleButton(ToggleReactivity, ButtonAppearance, Define): pass

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -