GoSuda

Skapa en bildvisare med Tk och filförteckning i Go

By Yunjin Lee
views ...

I det förra inlägget gav vi en kort översikt över CGo-Free Tcl/Tk-biblioteket. Den här gången kommer vi att använda det förra exemplet för att skapa en bildvisare.

Plan för bildvisare

  1. Bildvisaren från förra gången saknade en funktion för att ta bort bilder, vilket gjorde att fönstret blev för litet när man laddade in flera bilder. Låt oss ta bort de oanvända etiketterna.
  2. Om bildvisaren ska lista flera bilder, låt oss skapa en lista.
  3. Det är bäst att ladda flera bilder samtidigt.
  4. Låt oss också implementera möjligheten att ta bort bilder som inte ska visas från listan.
  5. Låt oss skapa en funktion för att välja och visa en specifik bild bland flera.

Modifierat Tcl/Tk 9.0-bibliotek

Det befintliga biblioteket har en bristfällig implementering av Listbox, vilket gör det svårt att visa en bildlista. Låt oss ladda ner det modifierade biblioteket. Om Git CLI inte är installerat kan du ladda ner det som en tarball- eller zip-fil.

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

Låt oss först titta på några av de tillagda funktionerna.

Innan vi går igenom de nya funktionerna, låt oss kort förstå strukturen hos de befintliga funktionerna genom att titta på Destroy-funktionen på rad 1017 i tk.go.

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

Denna funktion är implementerad genom att skicka operationen i Tcl-skriptformat till funktionen evalErr. Det betyder att för att implementera önskad funktionalitet behöver man bara skicka kommandot i motsvarande Tcl-skriptformat.

Låt oss som exempel implementera en metod för att lägga till objekt i en Listbox. Först, för Tcl-skriptning, låt oss titta på insert bland de kommandon som är tillgängliga för listbox i den officiella manualen.

insert-kommando

Om man tittar på beskrivningssidan för insert-kommandot, infogar insert listade objekt vid ett specifikt index. Då kan vi skriva följande kod för att implementera detta:

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

och så vidare.

Nu när vi har en allmän förståelse för implementeringsprincipen, kommer jag att förklara de ytterligare funktionerna för Listbox.

Lista: Infoga/ta bort

 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}
23

I programmet ovan lägger AddItem till olika objekt, avgränsade med mellanslag, från index 0 i ordning. item1-item3 kommer att ha index 0, 1, 2 i ordning. Kör exemplet för att se hur borttagning av objekt fungerar.

Lista: Hämta valda objekt

Nu ska vi hämta och kontrollera de valda objekten i 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 hämtar index för alla valda objekt i den aktuella Listbox. GetOne-metoden hämtar värdet för objektet vid det angivna indexet. Resultatet kan ses i konsolutskriften. Observera att den liknande metoden Get tar start- och slutindex och hämtar alla objekt inom intervallet.

Därefter ska vi ändra färgerna på Listbox.

Låt oss först titta på exemplet nedan.

 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 av färgtillämpning

Som det skrevs i koden ovan har höjden ökats. Dessutom kan man se att färgerna har applicerats korrekt. Eftersom ett alternativ är specificerat för att ändra färgen endast för ett specifikt objekt, kan man se att endast den första raden har en annan färg.

Även om det inte är en stor skillnad, kan Relief-metoden användas för att ändra kantstilen på widgeten till flat, groove, raise, ridge, solid eller sunken.

Exempel på bildvisare

Låt oss nu skapa en bildvisare med hjälp av de widgetar vi just lärt oss. Exempelprogrammet är som följer:

  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)) //Aktivera flerval och slå på filtret.
 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    //Om du vill använda ett tema, ange temanamn och sökväg.
139    fileMenu := menubar.Menu()
140    extensions = make([]FileType,0,1)
141    extensions = append(extensions, FileType{ "Supported Images", []string {".png",".ico"}, "" } )
142    //Lägg till png och ico i filtret.
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}
186

Resultat av bildvisarens körning

I detta exempel, för att förenkla implementeringen, förbereds alla bild-widgets i förväg när de laddas in, och dubbla filer kontrolleras inte. Du kan förbättra de problem som nämndes tidigare, och du kan också försöka ändra temat med DefaultTheme-metoden, som är utkommenterad. Försök att öva genom att skapa ett nytt program som förbättrar dessa aspekter.

Sammanfattning

I den här artikeln har vi undersökt hur Go-språkets Tcl/Tk-bibliotek anropar kommandon och skapat en bildvisare med en Listbox.

  1. Tcl/Tk-bibliotekets kommandoanropsmetod
  2. Hur man använder Listbox
  3. Ändra Listbox-widgetens egenskaper
  4. Skriva en bildvisare

På detta sätt, försök att utmana dig själv att modifiera andra bibliotek och skapa kompletta program med de tillagda funktionerna.