Grid Inventory

a 4x3 grid of selectable item slots.

▶ Run in browser

Tags: ui inventory game-ui

An inventory is a grid of slots the player picks from. A GridContainer lays its children out in rows of columns, so the slots are plain Buttons added in order and the grid places them; nothing here computes a position.

Each slot is a toggle button in one ButtonGroup. Joining a group turns a button into a toggle, and the group keeps exactly one checked, so the chosen slot stays drawn in its checked state until another is picked. The group’s checked_changed(button) signal is the one place selection is handled: it fills the detail line under the grid with the item name and slot number, or says the slot is empty. A slot’s colour swatch is its bg_colour, which colours the button’s normal state; hovered and checked slots draw the theme’s colours.

The grid and its labels sit in a VBoxContainer inset inside a Panel placed with anchor=Anchor.CENTER, so the whole inventory stays centred as the window resizes. Click or tap a slot to select it.

Source

 1# /// simvx
 2# tags = ["ui", "inventory", "game-ui"]
 3# web = { width = 800, height = 600, responsive = true }
 4# ///
 5"""Grid Inventory: a 4x3 grid of selectable item slots.
 6
 7An inventory is a grid of slots the player picks from. A `GridContainer` lays its
 8children out in rows of `columns`, so the slots are plain `Button`s added in
 9order and the grid places them; nothing here computes a position.
10
11Each slot is a toggle button in one `ButtonGroup`. Joining a group turns a button
12into a toggle, and the group keeps exactly one checked, so the chosen slot stays
13drawn in its checked state until another is picked. The group's
14`checked_changed(button)` signal is the one place selection is handled: it fills
15the detail line under the grid with the item name and slot number, or says the
16slot is empty. A slot's colour swatch is its `bg_colour`, which colours the
17button's normal state; hovered and checked slots draw the theme's colours.
18
19The grid and its labels sit in a `VBoxContainer` inset inside a `Panel` placed
20with `anchor=Anchor.CENTER`, so the whole inventory stays centred as the window
21resizes. Click or tap a slot to select it.
22"""
23
24from simvx.core import Anchor, ButtonGroup, Colour, HAlign, Label, Node, Panel
25from simvx.core.ui import Button, GridContainer, VBoxContainer
26from simvx.graphics import App
27
28# (name, swatch colour); None marks an empty slot.
29ITEMS = [
30    ("Sword", "#C0392B"),
31    ("Shield", "#2980B9"),
32    ("Potion", "#27AE60"),
33    ("Key", "#F1C40F"),
34    ("Bow", "#8E44AD"),
35    ("Arrow", "#7F8C8D"),
36    ("Gem", "#16A085"),
37    ("Map", "#E67E22"),
38    ("Bread", "#D35400"),
39    (None, None),
40    ("Torch", "#E74C3C"),
41    (None, None),
42]
43
44
45class InventoryDemo(Node):
46    """A centred grid inventory with click-to-select slots."""
47
48    def on_ready(self):
49        panel = Panel(anchor=Anchor.CENTER, size=(480, 400))
50        panel.bg_colour = Colour.hex("#1B1B26")
51        self.add_child(panel)
52
53        column = VBoxContainer(anchor=Anchor.FULL_RECT, inset=(24, 20), separation=16)
54        panel.add_child(column)
55        column.add_child(Label("Inventory", font_size=22, alignment=HAlign.CENTRE))
56
57        self.slots = ButtonGroup()
58        self.slots.checked_changed.connect(self.on_slot_selected)
59        grid = GridContainer(columns=4, separation=8)
60        for name, swatch in ITEMS:
61            slot = Button(name or "(empty)", group=self.slots, size=(96, 64))
62            if swatch:
63                slot.bg_colour = Colour.hex(swatch)
64            grid.add_child(slot)
65        column.add_child(grid)
66
67        self.detail = Label("Select an item.", font_size=15, alignment=HAlign.CENTRE)
68        self.detail.text_colour = Colour.LIGHT_GRAY
69        column.add_child(self.detail)
70
71    def on_slot_selected(self, slot: Button):
72        number = self.slots.buttons.index(slot) + 1
73        name = ITEMS[number - 1][0]
74        self.detail.text = f"Selected: {name} (slot {number})" if name else f"Slot {number} is empty."
75
76
77if __name__ == "__main__":
78    App(title="SimVX Inventory", width=800, height=600).run(InventoryDemo())