Gå til indholdet

mte.ui — byggere til formularbeskrivelser

Hver brugerfladeflade fra fase 3 — ctx.docks.add_panel og ctx.settings_page.register — tager en formularbeskrivelse: en almindelig ordbog, der beskriver et kontroltræ. Byg disse beskrivelser med mte.ui.*-hjælperne, så du ikke skal skrive JSON'en i hånden.

from mte.ui import (
    Column, Row, Group,
    Label, Button, Checkbox, LineEdit, NumberSpin, ComboBox, List,
)

Intet i mte.ui taler med Qt eller PySide — hver hjælper giver en ordbog tilbage, der følger det format, værtens formularfortolker i C++ forventer. Du må gerne sætte dem sammen, sætte lister ind i hinanden eller frembringe dem programmatisk:

from mte.ui import Column, Row, Label, Button

def make_toolbar(commands):
    return Row([Button(text=c["label"], on_click=c["id"])
                for c in commands])

form = Column([Label(text="Actions:"),
               make_toolbar(my_commands)])

Beskrivelsen efterprøves på værtssiden; ukendte kontroltyper eller manglende påkrævede felter giver en InvalidParams-fejl, som du vil se i loggen.

Mærkaterne i en formularbeskrivelse oversættes ikke

Hver overskrift, du sætter i en beskrivelse — paneltitler, afkrydsningsmærkater, gruppeoverskrifter — vises præcis, som du skrev den, uanset brugerfladens sprog. De er data, dit udvidelsesmodul sender til editoren, og ikke tekststrenge, editoren kan slå op i et oversættelseskatalog. Skal dit modul tale mere end ét sprog, så vælg selv tekststrengene, inden du kalder register; det nuværende sprog i brugerfladen er ctx.app_settings.get_string(mte.keys.UI_LANGUAGE) (tom betyder »følg systemet«). Det samme gælder det name og den description, din plugin.json viser på Indstillinger ▸ Udvidelsesmoduler.


Layout

Layoutbyggere tager en liste af underordnede ordbøger og stiller dem op lodret eller vandret.

Column(children)

Stabler de underordnede oppefra og ned med en strækning til sidst — kontrollerne bliver ved med at have deres naturlige højde i stedet for at svulme op og udfylde et højt panel.

Row(children)

Samme tanke, fra venstre mod højre, med en vandret strækning til sidst.

Group(children, *, title="")

En ramme med titel (gengivet som en QGroupBox), der indeholder en lodret stabel. Brug den til visuelt at samle beslægtede kontroller:

Group([
    Checkbox(id="cs", label="Case sensitive", binds="settings:cs"),
    Checkbox(id="ww", label="Whole words",    binds="settings:ww"),
], title="Search options")

Layout kan indlejres frit — en Row inde i en Column inde i en Group er helt fint.


Enkeltkontroller

Hver enkeltkontrol tager imod de samme fire fælles bindinger som nøgleordsargumenter:

Argument Betydning
id= Et stabilt id, som ctx.ui.get / ctx.ui.set og (underforstået) binds bruger.
binds= "settings:<key>" — gemmes automatisk gennem ctx.settings.
on_click= Id'et på den kommando, der skal kaldes — kun knapper.
on_change= Håndterings-id (ctx.docks.on_change(...)) — hver anden kontrol.

Kun enkeltkontroller, der blotlægger en »værdi«, understøtter binds og on_change.

Label(*, text="", id=None)

Fast tekst.

Button(*, text, on_click=None, id=None)

En trykknap. At udløse on_click kalder den registrerede kommando; vil du holde knappen i takt med noget andet, kan du bruge ctx.ui.set på dens text.

Checkbox(*, label="", default=False, id=None, binds=None, on_change=None)

En boolsk kontrol. default er udgangstilstanden; binds tilsidesætter den med den gemte værdi, hvis der findes en.

LineEdit(*, placeholder="", default="", id=None, binds=None, on_change=None)

Et tekstfelt på én linje.

NumberSpin(*, default=0, min=None, max=None, step=1, id=None, binds=None, on_change=None)

Et talfelt med pile. min og max begrænser området (begge valgfrie; den underliggende QSpinBox bruger sit standardområde, når de ikke er sat). step er springet på pilene.

Talområde

NumberSpin bygger på QSpinBox, som gemmer en int (32 bit). Værdier uden for -2_147_483_648 … 2_147_483_647 mættes ved platformens grænse.

ComboBox(*, items, default="", id=None, binds=None, on_change=None)

En rulleliste. items er en liste — hver post kan enten være en almindelig tekststreng eller et objekt som {"value": "cpp", "label": "C++"} (kun value bruges i dag; label er reserveret til en senere forfining).

List(*, items, id=None, on_change=None)

En listekontrol, hvor der kan markeres én ad gangen. on_change udløses med teksten på den nyligt markerede post. Ingen binds — gem selv markeringen, hvis du har brug for det.


Adgang under kørslen

Når panelet er registreret, kan du styre det fra enhver kommando:

panel_id = ctx.docks.add_panel(id="my.panel", ..., form=Column([
    LineEdit(id="needle"),
    Checkbox(id="cs"),
]))

# Read current values
needle = ctx.ui.get(panel_id, "needle")
cs     = ctx.ui.get(panel_id, "cs") == "true"

# Write values (does NOT fire on_change)
ctx.ui.set(panel_id, "needle", "hello")
ctx.ui.set(panel_id, "cs", True)

Se ctx.ui for hele dokumentationen.


At gemme værdier

binds="settings:<key>" er den korteste vej til at gemme en kontrols værdi:

  • Når panelet bygges, læser kontrollen sin udgangsværdi fra ctx.settings.get(key, <default>).
  • Ved hver ændring fra brugeren skriver kontrollen tilbage via ctx.settings.set(key, new_value).

Fordi både paneler og indstillingssider deler ctx.settings, spejler to kontroller med den samme binds-tekststreng hinanden med det samme. Det er sådan, HelloPythons panel og indstillingsside holder afkrydsningsfeltet »Loud« i takt.

Har du brug for at gemme noget, ordforrådet ikke dækker (f.eks. en markering i en List), så læs og skriv direkte gennem ctx.settings i et on_change-tilbagekald.