Oprettelse af en billedfremviser med en filliste tilføjet til Tk i Go
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
- 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.
- Hvis vi skal liste flere billeder i billedfremviseren, så lad os oprette en liste.
- Det er bedst at indlæse flere billeder på én gang.
- Lad os også implementere muligheden for at fjerne billeder fra listen, som vi ikke vil se.
- 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.
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}

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}

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.
- Tcl/Tk-bibliotekets kommandoopkaldsmetode
- Sådan bruges Listbox
- Ændring af Listbox-widgetens egenskaber
- 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.