User Tools

Site Tools


coding:lua:lgiquickstart

Getting Started with LGI (Lua GTK)

This tutorial covers everything you need to know to build your first GUI application using Lua and the GTK3 toolkit on Linux (I will be assuming Arch Linux, but any distro will work just fine). The focus will be on clean code architecture and understanding the core concepts that often confuse beginners.

Prerequisites

Before writing code, ensure the environment is set up correctly. Three main components are needed:

Lua: The programming language interpreter.
GTK3: The underlying C library that draws the windows and widgets (buttons, labels, etc.).
LGI: The Lua binding that allows your Lua code to talk to the GTK C library.

We will use Luarocks (the Lua package manager) for the Lua-specific libraries to ensure we have the most up-to-date version.

Installation

First, ensure you have the necessary system tools and the GTK3 library. Open your terminal:

sudo pacman -S vim gtk3 luarocks

Now, install the Lua bindings using Luarocks. This pulls down the LGI library which bridges Lua and GTK.

luarocks install lgi
luarocks install luafilesystem

The Mental Model: How GTK Works

Before typing code, it is crucial to understand how GTK (and therefore LGI) structures an application. If you skip this, the code will feel arbitrary.

Widgets

Everything is a β€œWidget”. A window is a widget. A button is a widget. A text label is a widget. You build an application by creating widgets and stacking them together.

Containers and Packing

A Window widget can only hold one child item. If you want a window with 5 buttons, you cannot simply β€œadd” 5 buttons to the window. The window will reject them. Instead, you add a Container (like a Box) to the window, and then you β€œpack” your 5 buttons into that Box.

Visual Representation

Window
    Box (Container)
        Button 1
        Button 2
        Label

Properties as Tables

In traditional C programming, setting a button label looks like a function: gtkbuttonset_label(btn, β€œClick Me”). In LGI Lua, we use a cleaner object-oriented style. Properties are treated like table fields:

btn.label = "Click Me"

First Application

We will build a simple β€œGreeter” application. It will have a text input field, a button, and a result label.

Project Setup

Create a directory for your project to keep things organized. We will use Vim to create and edit our main file.

mkdir lua_greeter
cd lua_greeter
vim main.lua

Writing the Code

Press i to enter Insert Mode in Vim, then paste the following code. Read the comments (lines starting with –) to understand what each part does.

-- 1. LOAD THE LIBRARY
local lgi = require("lgi")
local Gtk = lgi.require("Gtk", "3.0")
 
-- 2. INITIALIZE GTK
-- This function checks the system environment and prepares the GTK engine.
-- It must be called before creating any widgets.
Gtk.init()
 
-- 3. CREATE THE MAIN WINDOW
local window = Gtk.Window {
    title = "My First LGI App",
    default_width = 400,
    default_height = 300,
-- CONNECTING SIGNALS:
-- When the user clicks the 'X' button, the 'destroy' signal is emitted.
-- We connect this directly to Gtk.main_quit to stop the application loop.
-- Without this, the window would close, but the process would keep running in the background.
on_destroy = Gtk.main_quit
 
}
 
-- 4. CREATE CONTAINERS
-- Since a Window can only hold one item, we create a vertical Box.
-- This Box will stack our items top-to-bottom.
local vbox = Gtk.Box {
    orientation = "VERTICAL",
    spacing = 10,         -- 10 pixels of space between children
-- Margins create padding around the edges of the box inside the window
margin_top = 20,
margin_bottom = 20,
margin_start = 20,
margin_end = 20
 
}
 
-- 5. CREATE WIDGETS
local entry = Gtk.Entry {
    placeholder_text = "Type your name here..."
}
 
local btn = Gtk.Button {
    label = "Greet Me"
}
 
local resultLabel = Gtk.Label {
    label = "Result will appear here..."
}
 
-- 6. DEFINE LOGIC (SIGNAL HANDLERS)
-- We define what happens when the button is clicked.
-- 'on_clicked' is a special event listener built into Gtk.Button.
function btn:on_clicked()
    local name = entry.text -- Access the text property of the entry widget
if name == "" then
    resultLabel.label = "Please enter a name!"
else
    resultLabel.label = "Hello, " .. name .. "!"
end
 
end
 
-- 7. ASSEMBLE THE UI
-- We use pack_start to add widgets to our Box container.
-- Syntax: box:pack_start(widget, expand, fill, padding)
-- expand (false): Should this widget take up all extra vertical space? (No)
-- fill (false): If expanded, should the widget fill that space? (No)
-- padding (0): Extra pixels outside the widget.
 
vbox:pack_start(entry, false, false, 0)
vbox:pack_start(btn, false, false, 0)
 
-- For the label, we set expand to 'true'. It will take all remaining empty space.
vbox:pack_start(resultLabel, true, true, 0)
 
-- Finally, add the fully populated Box to the Window.
window:add(vbox)
 
-- 8. RUN THE APPLICATION
-- show_all() renders the window and all its children.
window:show_all()
 
-- Gtk.main() starts the Event Loop.
-- The program pauses here and waits for user actions (clicks, key presses).
-- It will only exit when Gtk.main_quit() is called.
Gtk.main()

Press Esc to exit Insert Mode, then type :wq and press Enter to save and quit Vim.

Running the Application

Back in the terminal, run your script with the Lua interpreter:

lua main.lua

You should see a native Linux window appear. Try typing your name and clicking the button.


Key Concepts Deep Dive

The Event Loop

You will notice that the script does not finish execution immediately. It hangs at the line Gtk.main(). This is intentional.

GUI applications are event-driven. They do not run linearly from start to finish; they wait. The Gtk.main() function creates a loop that constantly listens for events (mouse movements, clicks, system redraw requests). The program sleeps inside this loop until an event occurs.

Layout Management (Packing)

The pack_start function is the heart of GTK layout. It determines how widgets behave when you resize the window.

Expand (true/false): Does the widget grow if the window gets larger?
Fill (true/false): If the widget grows, does the content fill the new space, or does the widget just float in the center?

Example: If you set a Button to expand=true and fill=false, the button would stay its normal size but float in the middle of a large empty space when you maximize the window.


Finding Documentation

LGI documentation is sparse, but you can use the official GTK3 C documentation and β€œtranslate” it to Lua mentally.

C Syntax: gtk_button_new_with_label("Hello")

Lua Syntax: Gtk.Button { label = "Hello" }

C Syntax: gtk_window_set_title(win, "Title")

Lua Syntax: window.title = "Title"

Resource: Search for GTK3 Reference Manual online. It lists all widgets (Buttons, ComboBoxes, Scrollbars) and their properties, which apply directly to LGI.


snippet.cpp
by:
β––     β–˜β––β––
β–Œ β–Œβ–Œβ–›β–˜β–Œβ–™β–Œ
β–™β––β–™β–Œβ–™β––β–Œ β–Œ
 
written: February 25 2026
coding/lua/lgiquickstart.txt Β· Last modified: by luci4