The whole point of GUIs is events! We want events to be generated whenever the user does something, such as clicking a button, moving a scale, or pressing a key...

We also, sometimes, want events to happen repeatedly (in a loop) or in the background (because they might take a long time).

Slow Actions

If you want to do something that takes a long time, such as downloading a file, you should schedule it to happen in the background. If you don't, the GUI will hang (stop working until the action finishes).

The after() function will cause the named function to be run in the background, and optionally delayed:


Loops are like Slow Actions, if you put something in a loop, the GUI will hang until the loop finishes.
You can use after() to replicate a loop:

def myLoop():
    app.after(100, myLoop)

app.after(0, myLoop)

This will print Looping every 100 milliseconds forever.

Alternatively, appJar is always running a loop, and you can add functions to it:

This is great for updating statuses, checking for messages, etc...

#function to set the status bar
def getLocation():
    x,y,z = mc.player.getPos()
    app.setStatusbar("X: "+ str(round(x,3)), 0)
    app.setStatusbar("Y: "+ str(round(y,3)), 1)
    app.setStatusbar("Z: "+ str(round(z,3)), 2)

# call the getLocation function every second

User Actions

To make something happen you have to set a function for a widget.
appJar currenly supports four basic use cases:


Be careful it's possible to generate a RuntimeError. If you've got two widgets changing the same variable, say a Scale and a SpinBox, and you want a change in one widget to cause an update in the other, you might inadvertently end up stuck in a recursive loop, until the stack overflows.

In this case, make sure you set the optional parameter callFunction = False when you call the set XXX Function() of a widget.

from appJar import gui

def songChanged(rb):

def reset(btn):
    # set back to the default, but don't call the change function
    app.setRadioButton("song", "Killer Queen", callFunction=False)

app.addRadioButton("song", "Killer Queen")
app.addRadioButton("song", "Paradise City")
app.setRadioButtonChangeFunction("song", songChanged)
app.addButton("Reset", reset)
    from appJar import gui

    def enter(wdgt): 
        print("IN", wdgt)
    def leave(wdgt):
        print("OUT", wdgt)

    app.addLabel("l1", "Testing...")
    app.setLabelOverFunction("l1", [enter, leave])

Registering Other Event Types

It's possible to register any of the standard event types with appJar widgets

app.getEntryWidget("widget_name").bind("<FocusOut>", function_name, add="+")

Binding Keys

As well as changing widgets, we sometimes want keys to trigger events.
The classic example is the <Return> key, we often want to be able to hit the <Return> key to submit a form...

You may also want to bind other keys to events.

Stopping the GUI

Usually the user just presses the close icon to stop the GUI.
However, you might want to let them do it in other ways - maybe by pressing a button... To stop the GUI, simply call app.stop()

If you want to add a feature to confirm the user really wants to exit, or to save some data, then you'll need a stop function.

def checkStop():
    return app.yesNoBox("Confirm Exit", "Are you sure you want to exit the application?")