GoSuda

Képnézegető létrehozása fájllistával Go-ban Tk-val

By Yunjin Lee
views ...

Az előző bejegyzésben röviden áttekintettük a CGo-Free Tcl/Tk könyvtárat. Ezúttal az előző példa felhasználásával képnézegetőt fogunk készíteni.

Képnézegető tervezése

  1. Az előző alkalommal bemutatott képkijelző nem rendelkezett kép törlési funkcióval, így minél több képet töltöttünk be, annál kisebb lett az ablak mérete. Töröljük a nem használt Label-eket.
  2. Ha több képet szeretnénk listázni a képkijelzőben, hozzunk létre egy Listát.
  3. Előnyös, ha egyszerre több képet is be tudunk tölteni.
  4. Implementáljuk azt a funkciót is, amellyel eltávolíthatjuk a listából azokat a képeket, amelyeket nem szeretnénk megtekinteni.
  5. Hozzunk létre egy funkciót, amellyel kiválaszthatunk és megtekinthetünk egy adott képet a több kép közül.

Módosított Tcl/Tk 9.0 könyvtár

A meglévő könyvtárban a Listbox implementációja hiányos, így nehéz képlistát megjeleníteni. Töltsük le a módosított könyvtárat. Ha nincs telepítve a Git CLI, letölthetjük tarball vagy zip fájlként is.

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

Először tekintsünk át néhány hozzáadott funkciót.

Mielőtt azonban az új funkciókat megvizsgálnánk, nézzük meg röviden, hogyan épülnek fel a meglévő funkciók a tk.go fájl 1017. sorában található Destroy függvényen keresztül.

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

Ez a függvény az evalErr nevű függvényen keresztül, Tcl script formájában kapja meg a műveletet, és így valósul meg. Ez azt jelenti, hogy a kívánt funkció megvalósításához elegendő a megfelelő Tcl script formátumú parancsot átadni.

Példaként implementáljuk egy listboxhoz elemeket hozzáadó metódust. Először is, a Tcl szkripteléshez nézzük meg a hivatalos kézikönyvben a listboxhoz használható parancsok közül az "insert" parancsot.

insert parancs

Az "insert" parancs leírása szerint az "insert" egy adott indexre illeszti be a felsorolt elemeket. Ezt megvalósíthatjuk a következő kóddal:

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

Ezzel a kóddal megírhatjuk.

Most, hogy nagyjából megismertük a megvalósítás alapelveit, bemutatom a Listbox további funkcióit.

Lista: Beszúrás/Törlés

 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

A fenti programban az AddItem szóközökkel elválasztott, különböző elemeket szúr be a 0. indexről kezdve. Az item1-item3 sorrendben a 0, 1, 2 indexeket kapja meg. Futtassa a példát, hogy megértse, hogyan működik az elem törlése.

Lista: Kiválasztott elemek lekérése

Most nézzük meg, hogyan lehet lekérni és ellenőrizni a Listboxban kiválasztott elemeket.

 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}

A Selected metódus lekéri a Listboxban kiválasztott összes elem indexét. A GetOne metódus lekéri az adott indexhez tartozó elem értékét. Ez a konzolon megjelenő eredményből látható. Megjegyzésként, a hasonló Get metódus egy kezdő és egy záró indexet fogad el, és visszaadja az összes elem értékét az adott tartományban.

Ezután módosítani fogjuk a listbox színét.

Először vizsgáljuk meg az alábbi példát.

 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}

Színalkalmazás eredménye

A fenti kódban leírtak szerint a magasság megnőtt. Látható, hogy a színek is jól alkalmazódtak. Itt egy adott elemre eltérő színbeállítás van megadva, így látható, hogy csak az első sor színe tér el.

Emellett, bár nincs nagy különbség, a Relief metódussal a flat, groove, raise, ridge, solid, sunken stílusok közül választhatjuk ki a widget keretének stílusát.

Képnézegető példa

Most készítsünk egy képnézegetőt a fentiekben tanult widgetek felhasználásával. A példaprogram a következő:

  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)) //Többszörös kiválasztás engedélyezése és szűrők bekapcsolása.
 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    //A téma használatához adja meg a téma nevét és elérési útját.
139    fileMenu := menubar.Menu()
140    extensions = make([]FileType,0,1)
141    extensions = append(extensions, FileType{ "Supported Images", []string {".png",".ico"}, "" } )
142    //Adja hozzá a png és ico fájlokat a szűrőhöz.
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

Képnézegető futási eredménye

Ebben a példában az implementáció egyszerűsítése érdekében az összes kép widgetet előre elkészítjük a betöltéskor, és nem ellenőrizzük a duplikált fájlokat. Fejlesztheti a fent említett problémákat, vagy módosíthatja a témát a megjegyzésbe helyezett DefaultTheme metódus használatával. Kérjük, gyakoroljon úgy, hogy új programot készít ezeknek a részeknek a javításával.

Összefoglalás

Ebben a cikkben megvizsgáltuk, hogyan működik a Go nyelvű Tcl/Tk könyvtár parancshívása, és képnézegetőt készítettünk Listbox hozzáadásával.

  1. A Tcl/Tk könyvtár parancshívási módja
  2. A Listbox használata
  3. A Listbox widget tulajdonságainak módosítása
  4. Képnézegető készítése

Hasonló módon próbálja meg más könyvtárak módosítását is, és írjon kész programokat a hozzáadott funkciókkal.