Oprettelse af en billedfremviser med en filliste i Tk fra 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 skabe en billedfremviser.
Plan for billedfremviser
- Den billedfremviser fra sidste gang havde ikke en funktion til at slette billeder, så når man indlæste flere billeder, blev vinduets størrelse utilstrækkelig. Lad os slette de ubrugte labels.
- Hvis billedfremviseren skal liste flere billeder, lad os oprette en liste.
- Det er bedst at indlæse flere billeder på én gang.
- Implementer også funktionen til at fjerne billeder, der ikke skal ses, fra listen.
- Lad os oprette en funktion til at vælge og vise et specifikt billede blandt flere billeder.
Modificeret Tcl/Tk 9.0-bibliotek
Den eksisterende bibliotek har en mangelfuld Listbox-implementering, hvilket gør det vanskeligt at vise en billedliste. Lad os downloade det modificerede bibliotek. Hvis Git CLI ikke er installeret, kan du også downloade det som en tarball eller 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 ved at kigge på 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 en funktion kaldet evalErr. Det betyder, at for at implementere den ønskede funktion, skal man blot overføre kommandoen i det tilsvarende Tcl-scriptformat.
Lad os som eksempel implementere en metode til at tilføje elementer til en listbox. Først, for Tcl-scripting, lad os se på kommandoen 'insert' blandt de kommandoer, der kan bruges med listbox i den officielle manual.
Hvis man ser på 'insert'-kommandoens beskrivelsesside, indsætter 'insert' de anførte elementer ved et bestemt indeks. For at implementere dette kan man 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 generel forståelse af implementeringsprincippet, vil jeg forklare de yderligere funktioner til Listbox.
Liste: Indsættelse/Sletning
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 ovenstående program indsætter AddItem elementer, adskilt af mellemrum, i rækkefølge fra indeks 0. item1-item3 vil have henholdsvis indeks 0, 1 og 2. Kør eksemplet for at forstå, hvordan elementssletning fungerer.
Liste: Hentning af valgte elementer
Nu vil vi hente de valgte elementer fra Listbox og derefter verificere dem.
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 indeksene for alle valgte elementer i den aktuelle Listbox. GetOne-metoden henter værdien af elementet, der svarer til det pågældende indeks. Dette kan ses ud fra resultatet, der udskrives til konsollen. Bemærk, at den lignende Get-metode tager et start- og slutindeks 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 det ses, at farverne er blevet anvendt korrekt. Da der er angivet en mulighed for at anvende forskellige farver kun på specifikke elementer, kan det ses, at kun den første linje har fået en anderledes farve.
Desuden, selvom forskellen ikke er stor, kan Relief-metoden bruges til at ændre widget-grænsens stil til flat, groove, raise, ridge, solid, eller sunken.
Eksempel på billedfremviser
Lad os nu bygge en billedfremviser ved hjælp af de widgets, vi lige har lært. 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 //Angiv temaets navn og sti, hvis du ønsker at bruge et tema.
139 fileMenu := menubar.Menu()
140 extensions = make([]FileType,0,1)
141 extensions = append(extensions, FileType{ "Supported Images", []string {".png",".ico"}, "" } )
142 //Tilføj 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}
186
I dette eksempel, for at forenkle implementeringen, oprettes alle billedwidgets på forhånd, når de indlæses, og duplikerede filer kontrolleres ikke. Du kan forbedre de nævnte problemer, og du kan også prøve at ændre temaet ved at bruge DefaultTheme-metoden, som er kommenteret ud. Prøv at øve dig ved at oprette et nyt program, der forbedrer disse aspekter.
Sammenfatning
I denne artikel undersøgte vi, hvordan kommandokald i Go-sprogets Tcl/Tk-bibliotek fungerer, og vi oprettede en billedfremviser med en tilføjet Listbox.
- Tcl/Tk-bibliotekets kommandokaldsmetode
- Sådan bruges Listbox
- Ændring af Listbox-widgetens egenskaber
- Oprettelse af en billedfremviser
På denne måde kan du også forsøge at modificere andre biblioteker og skrive færdige programmer med de tilføjede funktioner.