GoSuda

Oprettelse af en billedfremviser med en filliste tilføjet til Tk i Go

By Yunjin Lee
views ...

I det sidste indlæg så vi kort på CGo-Free Tcl/Tk-biblioteket. Denne gang vil vi anvende eksemplet fra sidst til at lave en billedfremviser.

Plan for billedfremviser

  1. Billedfremviseren fra sidste gang havde ingen funktion til at slette billeder, så jo flere billeder der blev indlæst, desto mindre plads var der i vinduet. Lad os slette ubrugte labels.
  2. Hvis vi skal liste flere billeder i billedfremviseren, så lad os oprette en liste.
  3. Det er bedst at indlæse flere billeder på én gang.
  4. Lad os også implementere muligheden for at fjerne billeder fra listen, som vi ikke vil se.
  5. Lad os oprette en funktion til at vælge og se et specifikt billede blandt flere billeder.

Modificeret Tcl/Tk 9.0-bibliotek

Det eksisterende bibliotek har en mangelfuld Listbox-implementering, hvilket gør det svært at vise en billedliste. Lad os downloade det modificerede bibliotek. Hvis Git CLI ikke er installeret, kan du downloade det som en tarball eller en zip-fil.

1git clone https://github.com/gg582/tk9.0

Lad os først se på nogle af de tilføjede funktioner.

Før vi ser på de nye funktioner, lad os kort forstå strukturen af de eksisterende funktioner gennem Destroy-funktionen på linje 1017 i tk.go.

1func Destroy(options ...Opt) {
2	evalErr(fmt.Sprintf("destroy %s", collect(options...)))
3}

Denne funktion er implementeret ved at overføre handlingen i Tcl-scriptformat til funktionen evalErr. Det betyder, at for at implementere den ønskede funktionalitet, er det kun nødvendigt at overføre kommandoen i det tilsvarende Tcl-scriptformat.

Som et eksempel, lad os implementere en metode til at tilføje elementer til en listeboks. Først, for Tcl-scripting, lad os se på kommandoen insert, som er tilgængelig for listbox i den officielle manual.

insert-kommando

Beskrivelsessiden for insert-kommandoen viser, at insert indsætter listede elementer ved et specifikt indeks. For at implementere dette kan vi skrive kode som

1func (l *ListboxWidget) AddItem(index int, items string) {
2	evalErr(fmt.Sprintf("%s insert %d %s", l.fpath, index, items))
3}

.

Nu hvor vi har en grov forståelse af implementeringsprincippet, vil jeg forklare de yderligere funktioner til Listbox.

Liste: Indsæt/Slet

 1package main
 2import . "modernc.org/tk9.0"
 3
 4func main() {
 5    length := 3
 6    l := Listbox()
 7    l.AddItem(0, "item1 item2 item3")
 8    b1 := TButton(Txt("Delete Multiple Items, index (0-1)"), Command( func(){
 9        if length >= 2 {
10            l.DeleteItems(0,1)
11            length-=2
12        }
13    }))
14    b2 := TButton(Txt("Delete One Item, index (0)"), Command( func () {
15        if length > 0 {
16            l.DeleteOne(0) 
17            length-=1
18        }
19    }))
20    Pack(TExit(),l,b1,b2)
21    App.Wait()
22}

I ovenstående program indsætter AddItem forskellige elementer, adskilt af mellemrum, sekventielt fra indeks 0. item1-item3 vil have indekserne 0, 1, 2 sekventielt. Kør eksemplet for at finde ud af, hvordan elementfjernelse fungerer.

Liste: Hent valgte elementer

Lad os nu hente og kontrollere de valgte elementer fra Listbox.

 1package main
 2
 3import . "modernc.org/tk9.0"
 4
 5func main() {
 6    l := Listbox()
 7    l.SelectMode("multiple")
 8    l.AddItem(0, "item1 item2 item3")
 9    btn := TButton(Txt("Print Selected"), Command( func() {
10        sel := l.Selected()
11        for _, i := range sel {
12            println(l.GetOne(i))
13        }
14    }))
15
16    Pack(TExit(), l, btn)
17    App.Wait()
18}

Selected-metoden henter indekserne for alle valgte elementer i den aktuelle Listbox. GetOne-metoden henter værdien af elementet, der svarer til det givne indeks. Resultatet kan ses i konsoloutputtet. Bemærk, at den lignende metode Get tager start- og slutindekser og henter værdierne for alle elementer inden for området.

Dernæst vil vi ændre farven på listboxen.

Lad os først se på eksemplet nedenfor.

 1package main
 2
 3import . "modernc.org/tk9.0"
 4
 5func main() {
 6    l := Listbox()
 7    l.Background("blue")
 8    l.Foreground("yellow")
 9    l.SelectBackground("black")
10    l.SelectForeground("white")
11    l.Height(20)
12    l.Width(6)
13    l.AddItem(0, "item1 item2 item3")
14    l.ItemForeground(0,"red")
15    l.ItemBackground(0,"green")
16    l.ItemSelectBackground(0,"white")
17    l.ItemSelectForeground(0,"black")
18    l.Relief("ridged")
19    Pack(TExit(),l)
20    App.Wait()
21}

Resultat af farveanvendelse

Som skrevet i koden ovenfor er højden øget. Desuden kan vi se, at farverne er anvendt korrekt. Her er en mulighed specificeret, der anvender forskellige farver kun til et specifikt element, så det ses, at kun den første linje har fået en anden farve.

Derudover, selvom der ikke er nogen stor forskel, kan Relief-metoden bruges til at ændre stilen af widget-kanten blandt flat, groove, raise, ridge, solid, sunken.

Eksempel på billedfremviser

Så lad os bruge de widgets, vi lige har lært, til at lave en billedfremviser. Eksempelprogrammet er som følger:

  1package main
  2
  3import (
  4    "fmt"
  5    "log"
  6    "os"
  7    "runtime"
  8    "strings"
  9    "path"
 10
 11    . "modernc.org/tk9.0"
 12)
 13
 14var pbuttons []*TButtonWidget
 15var extensions []FileType
 16var pbutton *TButtonWidget = nil
 17var listbox, listbox2 *ListboxWidget
 18var cur *LabelWidget = nil
 19var imagesLoaded []*LabelWidget
 20func PhotoName(fileName string) string {
 21        fileName = path.Base(fileName)
 22        return fileName[:len(fileName)-len(path.Ext(fileName))]
 23}
 24
 25func handleFileOpen() {
 26    res := GetOpenFile(Multiple(true),Filetypes(extensions)) //aktiverer multiselection og tænder for filteret.
 27    s := make([]string,0,1000)
 28    for _, itm := range res {
 29        if itm != "" {
 30            tmp := strings.Split(itm," ")
 31            s = append(s,tmp...)
 32        }
 33    }
 34
 35    for _, photo := range s {
 36        formatCheck := strings.Split(photo, ".")
 37        format := formatCheck[len(formatCheck)-1]
 38
 39        if (strings.Compare(format, "png") == 0) || (strings.Compare(format, "ico") == 0) {
 40            picFile, err := os.Open(photo)
 41            if err != nil {
 42                log.Println("Error while opening photo, error is: ", err)
 43            }
 44
 45            pictureRawData := make([]byte, 10000*10000)
 46            picFile.Read(pictureRawData)
 47
 48            imageLabel := Label(Image(NewPhoto(Data(pictureRawData))))
 49                        imagesLoaded = append(imagesLoaded,imageLabel)
 50            var deleteTestButton *TButtonWidget
 51            deleteTestButton = TButton(
 52                Txt("Unshow Image"),
 53            Command(func() {
 54                GridForget(imageLabel.Window)
 55                GridForget(deleteTestButton.Window)
 56            }))
 57
 58            pbuttons = append(pbuttons,deleteTestButton)
 59
 60                        listbox.AddItem(len(imagesLoaded)-1,PhotoName(photo))
 61                        listbox2.AddItem(len(imagesLoaded)-1,PhotoName(photo))
 62            picFile.Close()
 63        }
 64    }
 65}
 66
 67func DeleteSelected () {
 68    s:=listbox.Selected()
 69    if len(s) == 0 {
 70        return
 71        }
 72    for _, i := range s {
 73        listbox.DeleteOne(i)
 74        listbox2.DeleteOne(i)
 75        if len(imagesLoaded)-1>i {
 76            continue
 77        }
 78        if cur == imagesLoaded[i] {
 79            pbutton = nil
 80            cur = nil
 81        }
 82        Destroy(imagesLoaded[i])
 83        Destroy(pbuttons[i])
 84                imagesLoaded = append(imagesLoaded[:i],imagesLoaded[i+1:]...)
 85        pbuttons = append(pbuttons[:i], pbuttons[i+1:]...)
 86    }
 87}
 88
 89func SelectImage() {
 90        s:=listbox2.Selected()
 91        if len(s) == 0 {
 92                return
 93        }
 94
 95    if len(imagesLoaded) -1 < s[0] {
 96        return
 97    }
 98    if imagesLoaded[s[0]] == nil {
 99        return
100    }
101    if cur != nil {
102            GridForget(cur.Window)
103    }
104    if pbutton != nil {
105        GridForget(pbutton.Window)
106    }
107
108        Grid(imagesLoaded[s[0]], Row(0), Column(2))
109    Grid(pbuttons[s[0]], Row(0), Column(3))
110    cur = imagesLoaded[s[0]]
111    pbutton = pbuttons[s[0]]
112}
113
114func SelectIndex(index int) {
115
116    if len(imagesLoaded) -1 <index {
117        return
118    }
119    if imagesLoaded[index] == nil {
120        return
121    }
122    if cur != nil {
123            GridForget(cur.Window)
124    }
125    if pbutton != nil {
126        GridForget(pbutton.Window)
127    }
128
129        Grid(imagesLoaded[index], Row(0), Column(2))
130    Grid(pbuttons[index], Row(0), Column(3))
131    cur = imagesLoaded[index]
132    pbutton = pbuttons[index]
133}
134
135func main() {
136    menubar := Menu()
137    //DefaultTheme("awdark","themes/awthemes-10.4.0")
138    //Hvis du vil bruge et tema, skal du angive temaets navn og sti.
139    fileMenu := menubar.Menu()
140    extensions = make([]FileType,0,1)
141    extensions = append(extensions, FileType{ "Supported Images", []string {".png",".ico"}, "" } )
142    //Tilføjer png og ico til filteret.
143    fileMenu.AddCommand(Lbl("Open..."), Underline(0), Accelerator("Ctrl+O"), Command(func () {
144        handleFileOpen()
145        SelectIndex(len(imagesLoaded)-1)
146    } ))
147    Bind(App, "<Control-o>", Command(func() { fileMenu.Invoke(0) }))
148    fileMenu.AddCommand(Lbl("Exit"), Underline(1), Accelerator("Ctrl+Q"), ExitHandler())
149    Bind(App, "<Control-q>", Command(func() { fileMenu.Invoke(1) }))
150    menubar.AddCascade(Lbl("File"), Underline(0), Mnu(fileMenu))
151        imagesLoaded = make([]*LabelWidget, 0, 10000)
152    pbuttons = make([]*TButtonWidget,0,10000)
153    var scrollx, scroll, scroll2, scrollx2 *TScrollbarWidget
154        listbox = Listbox(Yscrollcommand(func(e *Event) { e.ScrollSet(scroll)}) , Xscrollcommand( func(e *Event) { e.ScrollSet(scrollx)}))
155        listbox2 = Listbox(Yscrollcommand(func(e *Event) { e.ScrollSet(scroll2)}), Xscrollcommand(func(e *Event) { e.ScrollSet(scrollx2)}))
156        listbox.SelectMode("multiple")
157        listbox2 = Listbox()
158        listbox.Background("white")
159        listbox.SelectBackground("blue")
160        listbox.SelectForeground("yellow")
161        listbox2.Background("grey")
162        listbox2.SelectBackground("green")
163    listbox2.SelectForeground("blue")
164    listbox2.SelectBackground("brown")
165        listbox.Height(5)
166        listbox.Width(4)
167        listbox2.Height(5)
168        listbox2.Width(4)
169        delBtn := Button(Txt("Delete"), Command(func () { DeleteSelected() }))
170        selBtn := Button(Txt("Select"), Command(func () { SelectImage() }))
171        scroll = TScrollbar(Command(func(e *Event) { e.Yview(listbox) }))
172        scrollx = TScrollbar(Orient("horizontal"),Command(func(e *Event) { e.Xview(listbox) }))
173    scroll2 = TScrollbar(Command(func(e *Event) { e.Yview(listbox2) }))
174        scrollx2 = TScrollbar(Orient("horizontal"),Command(func(e *Event) { e.Xview(listbox2) }))
175        Grid(listbox,Row(1),Column(0), Sticky("nes"))
176        Grid(scroll,Row(1),Column(1), Sticky("nes"))
177    Grid(scrollx,Row(2),Column(0),  Sticky("nes"))
178        Grid(delBtn,Row(3),Column(0), Sticky("nes"))
179        Grid(listbox2,Row(1),Column(2), Sticky("nes"))
180        Grid(scroll2,Row(1),Column(3), Sticky("nes"))
181    Grid(scrollx2,Row(2),Column(2), Sticky("nes"))
182        Grid(selBtn,Row(3),Column(2), Sticky("nes"))
183    App.WmTitle(fmt.Sprintf("%s on %s", App.WmTitle(""), runtime.GOOS))
184    App.Configure(Mnu(menubar), Width("80c"), Height("60c")).Wait()
185}

Resultat af billedfremviser

I dette eksempel, for at forenkle implementeringen, oprettes alle billedwidgets på forhånd, når de indlæses, og der kontrolleres ikke for duplikerede filer. Du kan forbedre de nævnte problemer og også prøve at ændre temaet ved hjælp af DefaultTheme-metoden, som er kommenteret ud. Prøv at øve dig ved at oprette et nyt program, der forbedrer disse dele.

Resumé

I denne artikel har vi undersøgt, hvordan Go-sprogets Tcl/Tk-biblioteks kommandoopkald fungerer, og vi har lavet en billedfremviser med en Listbox.

  1. Tcl/Tk-bibliotekets kommandoopkaldsmetode
  2. Sådan bruges Listbox
  3. Ændring af Listbox-widgetens egenskaber
  4. Oprettelse af en billedfremviser

På denne måde kan du også prøve at modificere andre biblioteker og skrive færdige programmer med de tilføjede funktioner.