Grouping Widgets


The standard way of using appJar, is simply to place all widgets into a single window.
Everything is grouped into that single window, and any changes affect everything in that window.

It's sometimes desirable to group widgets together within a window.
Or to have multiple pages of widgets.
A number of options are provided to make this easier.

Format

All of these methods work in the same way.
You call the start function when you want to start a container, then the stop function when you're done.
When you call start you can pass in positional arguments like any other widget (row, column, rowspan, colspan).
Any GUI Options you set, within the container, will only affect that container.

Reopening Containers

If you want to dynamically add widgets to a container, once the gui has been started, you can open a specific container, perform the desired actions, then stop it again.

def addRows(btn):
    count = app.getEntry("numRows")
    app.openTab("tabbedPane", "Details Tab") # open the required tab
    for rowLoop in range(count):
        # add a new label, with a unique ID
        # make sure to put it in the right place
        app.addLabel("dyn"+str(rowLoop), "Dynamic Label", rowLoop+5)
    app.stopTab()

Frame

A way of grouping together widgets.
Position the Frame within the grid, then position widgets inside the Frame

Frame

from appJar import gui 

app=gui("FRAME DEMO", "250x150")
app.setBg("yellow")

app.startFrame("LEFT", row=0, column=0)
app.setBg("blue")
app.setSticky("NEW")
app.setStretch("COLUMN")

app.addLabel("LEFT LABEL", "Label on the left 1")
app.setLabelBg("LEFT LABEL", "red")
app.addLabel("LEFT LABEL2", "Label on the left 2")
app.setLabelBg("LEFT LABEL2", "orange")
app.addLabel("LEFT LABEL3", "Label on the left 3")
app.setLabelBg("LEFT LABEL3", "yellow")
app.stopFrame()

app.startFrame("RIGHT", row=0, column=1)
app.setBg("green")
app.setFg("white")
for x in range(5):
    app.addRadioButton("RADIO", "Choice " + str(x))
app.stopFrame()

app.go()

Or in v1.0:

from appJar import gui 

with gui("FRAME DEMO", "250x150", bg='yellow') as app:

    with app.frame("LEFT", row=0, column=0, bg='blue', sticky='NEW', stretch='COLUMN'):
        app.label("Label on the left 1", bg='red')
        app.label("Label on the left 2", bg='orange')
        app.label("Label on the left 3", bg='yellow')

    with app.frame("RIGHT", row=0, column=1, bg='green', fg='white'):
        for x in range(5):
            app.radio("RADIO", "Choice " + str(x))

Start/Stop Frames

Juggling Frames

from appJar import gui 

with gui() as app:
    with app.frame("ONE", 0,0):
        app.label("In frame one")
    with app.frame("TWO", 0,0):
        app.label("In frame two")

    app.buttons(["ONE", "TWO"], app.raiseFrame)

Frame Stack


A way of having mutiple frames on top of each other, with all but one hidden.
Each frame is created and added to the stack. Then they can be navigated through, using first, next, prev and last.

from appJar import gui

def press(btn):
    if btn == "FIRST": app.firstFrame("Pages")
    elif btn == "NEXT": app.nextFrame("Pages")
    elif btn == "PREV": app.prevFrame("Pages")
    elif btn == "LAST": app.lastFrame("Pages")

app=gui("FRAME STACK")

app.startFrameStack("Pages")

app.startFrame()
for i in range(5):
    app.addLabel("Text: " + str(i))
app.stopFrame()

app.startFrame()
for i in range(5):
    app.addEntry("e" + str(i))
app.stopFrame()

app.startFrame()
for i in range(5):
    app.addButton(str(i), None)
app.stopFrame()

app.stopFrameStack()

app.addButtons(["FIRST", "PREV", "NEXT", "LAST"], press)
app.go()

Or in v1.0:

from appJar import gui 

def press(btn):
    if btn == "FIRST": app.firstFrame("Pages")
    elif btn == "NEXT": app.nextFrame("Pages")
    elif btn == "PREV": app.prevFrame("Pages")
    elif btn == "LAST": app.lastFrame("Pages")

with gui("FRAME STACK") as app:
    with app.frameStack("Pages", start=0):
        with app.frame():
            for i in range(5):
                app.label("Text: " + str(i))
        with app.frame():
            for i in range(5):
                app.entry("e" + str(i))
        with app.frame():
            for i in range(5):
                app.button(str(i), None)

    app.buttons(["FIRST", "PREV", "NEXT", "LAST"], press)

Start/Stop Frame Stacks

Label Frame


A way of grouping widgets into a box, with a label at the top of the box.
Position the LabelFrame within the grid, then position widgets inside the LabelFrame

NB. LabelFrames have a different stickiness to the appJar GUI - they only stick widgets to the w (left) side.
If you want your widgets to stretch across the LabelFrame, like the rest of appJar, you will need to call app.setSticky("ew") after starting the LabelFrame.

LabelFrame

from appJar import gui

app=gui()

app.startLabelFrame("Login Details")
# these only affect the labelFrame
app.setSticky("ew")
app.setFont(20)

app.addLabel("l1", "Name", 0, 0)
app.addEntry("Name", 0, 1)
app.addLabel("l2", "Password", 1, 0)
app.addEntry("Password", 1, 1)
app.addButtons(["Submit", "Cancel"], None, 2, 0, 2)
app.stopLabelFrame()

app.go()

Start/Stop Label Frames

Set Label Frames

Scroll Pane


A scrollable pane, inside a frame, to contain widgets.
Allows you to have more widgets than will fit on the screen, or have a smaller window than required.

ScrollPane

from appJar import gui 

app=gui("SCROLLABLE DEMO", "150x150")

app.startScrollPane("PANE")
for x in range(10):
    for y in range(10):
        name = str(x) + "-" + str(y)
        app.addLabel(name, name, row=x, column=y)
        app.setLabelBg(name, app.RANDOM_COLOUR())
app.stopScrollPane()

app.go()

Scrolling

The ScrollPane has been configured to allow scrolling through lots of different methods:

Start/Stop Scroll Panes

Toggle Frame


A collapsible container for a group of related widgets.
By default, the contents of the frame are hidden.
They can be revealed/hidden again by clicking an associated button.
ToggleFrame ToggleFrame

from appJar import gui

app=gui()
app.setFont(20)

app.startToggleFrame("Options")
app.addCheckBox("Show this")
app.addCheckBox("Show that")
app.addCheckBox("Show the other")
app.setCheckBox("Show that")
app.stopToggleFrame()

app.go()

Start/Stop Toggle Frames

Set Toggle Frames

Get Toggle Frames

Tabbed Frame


A way to create a (basic) tabbed-style interface.
Position the TabbedFrame within the grid, start a Tab, then position widgets inside the Tab
TabbedFrame

from appJar import gui

app=gui()

app.startTabbedFrame("TabbedFrame")
app.startTab("Tab1")
app.addLabel("l1", "Tab 1 Label")
app.stopTab()

app.startTab("Tab2")
app.addLabel("l2", "Tab 2 Label")
app.stopTab()

app.startTab("Tab3")
app.addLabel("l3", "Tab 3 Label")
app.stopTab()
app.stopTabbedFrame()

app.go()

Start/Stop Tabbed Frames

Set TabbedFrame

Changing Colours

TabbedFrames have a set of colours that can be changed:

These are all changed via the standard property changing functions, eg:

It is also possible to change the colour of individual panes.
Call .setBg("colour") while adding widgets to the specific pane.
Or .setTabBg(title, tab, 'colour') at other times.

Get TabbedFrame

Notebook


NB. This will only work with ttk enabled.
NB. Notes have a different stickiness to the appJar GUI - they only stick widgets to the w (left) side. If you want your widgets to stretch across the Note, like the rest of appJar, you will need to call app.setSticky("ew") after starting the Note.

Similar to the Tabbed Frame, it is a way of placing widgets in different tabs or 'notes'. Position the Notebook within the grid, start a Note, then position widgets inside the Note.

Notebook

from appJar import gui

app = gui("Notebook", useTtk=True)

app.setTtkTheme("clam")

app.startNotebook("Notebook")

app.startNote("Note 1")
app.addLabel("l1", "Note 1")
app.stopNote()

app.startNote("Note 2")
app.addLabel("l2", "Note 2")
app.stopNote()

app.startNote("Note 3")
app.addLabel("l3", "Note 3")
app.stopNote()

app.stopNotebook()

app.go()

Start/Stop Notebooks

Set Notebooks

Styles & Colours

Paned Frame


A way to present re-sizable panes, separated by drag-bars.
Once the first pane is placed, all additional panes should be placed inside it.
By default, panes will be placed side-by-side (horizontally).
This can be changed by setting the pane to vertical, then they'll be placed underneath each other.

Start/Stop Paned Frames

Set Paned Frames

Horizontal Pane Layout

Horizontal Panes

from appJar import gui
app = gui()

# start initial pane
app.startPanedFrame("p1")
app.addLabel("l1", "Inside Pane 1")

# start additional panes inside initial pane
app.startPanedFrame("p2")
app.addLabel("l2", "Inside Pane 2")
app.stopPanedFrame()

app.startPanedFrame("p3")
app.addLabel("l3", "Inside Pane 3")
app.stopPanedFrame()

# stop initial pane
app.stopPanedFrame()

app.go()

Vertical Pane Layout

Vertical Panes

from appJar import gui
app = gui()

# start initial, vertical pane
app.startPanedFrameVertical("p1")
app.addLabel("l1", "Inside Pane 1")

# start additional panes inside initial pane
app.startPanedFrame("p2")
app.addLabel("l2", "Inside Pane 2")
app.stopPanedFrame()

app.startPanedFrame("p3")
app.addLabel("l3", "Inside Pane 3")
app.stopPanedFrame()

# stop initial pane
app.stopPanedFrame()

app.go()

E-Pane Layout

E-Panes

from appJar import gui
app = gui()

# start initial pane
app.startPanedFrame("p1")
app.addLabel("l1", "Inside Pane 1")

# start second, vertical pane inside initial pane
app.startPanedFrameVertical("p2")
app.addLabel("l2", "Inside Pane 2")

# start additional panes inside second pane
app.startPanedFrame("p3")
app.addLabel("l3", "Inside Pane 3")
app.stopPanedFrame()

# stop second & initial panes
app.stopPanedFrame()
app.stopPanedFrame()

app.go()

T-Pane Layout

T-Panes

from appJar import gui
app = gui()

# start intial, vertical pane
app.startPanedFrameVertical("p1")
app.addLabel("l1", "Inside Pane 1")

# start second pane
app.startPanedFrame("p2")
app.addLabel("l2", "Inside Pane 2")

# start additional panes inside second pane 
app.startPanedFrame("p3")
app.addLabel("l3", "Inside Pane 3")
app.stopPanedFrame()

# stop second & initial panes
app.stopPanedFrame()
app.stopPanedFrame()

app.go()

Paged Window


A container that mimics a classic phone based interface.
It provides PREVIOUS/NEXT buttons to navigate through a series of pages.
It has an optional widget title, and shows the current page, in a page counter.
Keyboard bindings are provided to navigate with arrow key presses. CTRL-arrow will navigate to the beginning/end.
Events can be bound to page changes, the page can be changed via a function call, and the current page number can be queried.
PagedWindow

from appJar import gui

app=gui()

app.setBg("DarkKhaki")
app.setSize(280,400)

app.startPagedWindow("Main Title")
app.startPage()
app.addLabel("l13", "Label 1")
app.stopPage()

app.startPage()
app.addLabel("l21", "Label 2")
app.stopPage()

app.startPage()
app.addLabel("l3", "Label 3")
app.stopPage()

app.startPage()
app.addLabel("l4", "Label 4")
app.stopPage()
app.stopPagedWindow()

app.go()

Start/Stop Paged Windows

Set Paged Windows

Get Paged Windows

Sub Window


A way to add additional windows, which can be hidden and shown.
SubWindow

This has been moved to its own page: Multiple Windows.