Resources to simplify programming with the PyFLTK GUI framework.
Copyright (c) 2023 by David McNab
This package offers classes and functions to reduce much of the repetitive and error-prone work of managing widgets on FLTK GUIs.
PyFLTK is a SWIG wrapper on top of the long-famed FLTK GUI framework. For decades, FLTK has been a popular framework choice for GUIs which need to be simple, light on resources, easy to learn. Howerver, FLTK does have some downsides.
As a low-level GUI framework, FLTK (and PyFLTK) gives the programmer all the responsibility for managing widget sizes and locations.
The example programs with both FLTK and PyFLTK typically feature widgets being placed into their parent containers with absolute (x,y) locations and with absolute (width, height) sizes.
This is not so much a problem when first creating a GUI layout programmatically. But when maintaining this layout later, to add, remove, move and reorganise widgets, the programmer has to recalculate all the (x,y) locations of all the widgets which can become very distracting, tiring and often, a source of errors.
The fltkHelpers.cursor
module provides classes which act as
GUI widget placement 'cursors', which allows widgets to be
placed in their containers at positions which are relative to
prior widgets. As such, it automatically calculates the required
(x, y) locations for each added widget.
Here is a small demo (extracted from examples/example1.py
) which shows widgets being placed at
relative
locations:
from fltkHelpers.cursor import FLCursor
class MyApp:
def __init__(self):
# origin of window on the screen
winOrg = FLCursor(100, 50)
# size of the window
winSize = FLCursor(300, 140)
# standard size of buttons we wish to place
btnSize = FLCursor(80, 20)
# now place the window on the screen
self.win, right, down = winOrg.Fl_Window(winSize, "example1.py")
# now create first 'cursor' object to start the layout within this window
# and apply an offset to provide room for text field label and some vertical pad
fldOrg = winOrg.topLeft() + (80, 20)
# place a write-only field, plus a button
self.outTime, right, down = fldOrg.Fl_Output((180, 20), "Datetime:")
self.btnGetTime, right, down = down.Fl_Button(btnSize, "Update")
self.btnGetTime.callback(self.on_btnUpdate)
# get a cursor for adding n widgets of given height to bottom row of window
bottomOrg = winSize.bottomCentre(btnSize, 1)
# now we can place that bottom button
self.btnQuit, _, _ = bottomOrg.Fl_Button(btnSize, "Quit")
self.btnQuit.callback(self.on_btnQuit)
self.win.show()
self.win.end()
def on_btnUpdate(self, *args):
"""
callback for when user clicks the 'Update' button
"""
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
self.outTime.value(now)
def on_btnQuit(self, *args):
"""
callback for when user clicks the 'Quit' button
"""
self.win.hide()
def run(self):
fltk.Fl.run()
def main():
app = MyApp()
app.run()
if __name__ == '__main__':
main()