|
|||
| Forrige < |
Innhold ^
|
Neste >
|
|
TkFrame eller TkRoot)
og deretter lager du de widgets som skal være inne i beholderen,
slik som knapper og tekst. Når du er klar for å starte det grafiske
brukergrensesnittet, kaller du Tk.mainloop. Tk sin motor tar da
kontroll over programmet, viser widgets og kaller din kode når den mottar
hendelser i fra grensesnittet.
require 'tk'
root = TkRoot.new { title "Ex1" }
TkLabel.new(root) {
text 'Hello, World!'
pack { padx 15 ; pady 15; side 'left' }
}
Tk.mainloop
|
| Figur 15.1: Hello world program skjermbilde |
![]() |
tk utvidelsesmodulen, lager vi en
rotnivå vindusramme ved hjelp av TkRoot.new.
Deretter lager vi en tekst widget som blir barnet til rotrammen.
Helt til slutt pakker vi rotrammen og går inn i grensesnittets hendelsesløkke.
Det er en god vane å angi rotrammen eksplisitt, men du kunne ha utelatt den---sammen med de ekstra opsjonene---og kuttet dette ned til en tre-linjers snutt:
require 'tk'
TkLabel.new { text 'Hello, World!' }
Tk.mainloop
|
Tk foran. For eksempel blir widgets Label, Button og
Entry til klassene TkLabel, TkButton, and
TkEntry. Du lager en instans av en widget ved å bruke
new, som du ville gjort for et hvert annet objekt. Hvis du
ikke angir en forelder til en gitt widget, brukes rotnivå vindusrammen.
Vanligvis ønsker vi å spesifisere forelderen til en gitt widget sammen
med mange andre opsjoner---farge, størrelse og så videre. Vi trenger også
å kunne få informasjon tilbake fra våre widgets mens programmet kjører, ved
å sette opp tilbakekall og delt data.
Hash.
Du kan gjøre dette i Ruby også, men et alternativ er å sende opsjonene ved
hjelp av en kodeblokk; opsjonsnavnet brukes som et metodenavn inne i blokken
og argumenter til opsjonen viser seg som argumenter til metodekallet.
Widgets tar en forelder som første argument, fulgt av en valgfri hash fylt med opsjoner eller kodeblokken med opsjoner. Dette gjør at de to følgende variantene er ekvivalente.
TkLabel.new(parent_widget) {
text 'Hello, World!'
pack('padx' => 5,
'pady' => 5,
'side' => 'left')
}
# or
TkLabel.new(parent_widget, text => 'Hello, World!').pack(...)
|
padx og pady i disse eksemplene) antas å være målt i piksler, men kan også spesifiseres i andre enheter ved å bruke en av de følgende endelsene ``c'' (centimeter),
``i'' (inch eller tomme), ``m'' (millimeter),
eller ``p'' (punkt).
command
(vist i kallet til TkButton i neste eksempel) tar inn et Proc-objekt som vil bli kjørt når en hendelse avfyrer tilbakekallet.
Her bruker vi
Kernel::proc
for å konvertere blokken {exit} om til et Proc-objekt.
TkButton.new(bottom) {
text "Ok"
command proc { p mycheck.value; exit }
pack('side'=>'left', 'padx'=>10, 'pady'=>10)
}
|
TkVariable som mellomledd.
Dette ser vi i neste eksempel.
Legg merke til hvordan TkCheckButton settes opp;
dokumentasjonen sier at variable opsjonen tar en var reference som argument. Vi lager en Tk variabel referanse ved å bruke
TkVariable.new.
Kaller man så mycheck.value vil man få tilbake
``0'' eller ``1'', beroende på om avkrysningsboksen er avkrysset eller ikke.
Denne mekanismen kan benyttes for enhver ting som størrer var referanser, slik som radioknapper og tekstfelt.
mycheck = TkVariable.new
TkCheckButton.new(top) {
variable mycheck
pack('padx'=>5, 'pady'=>5, 'side' => 'left')
}
|
configure , som tar en Hash eller en kodeblokk, på samme måte som new. Vi kan forandre det første eksempelet slik at teksten endres når en knapp trykkes:
lbl = TkLabel.new(top) { justify 'center'
text 'Hello, World!';
pack('padx'=>5, 'pady'=>5, 'side' => 'top') }
TkButton.new(top) {
text "Cancel"
command proc { lbl.configure('text'=>"Goodbye, Cruel World!") }
pack('side'=>'right', 'padx'=>10, 'pady'=>10)
}
|
Cancel trykkes, vil teksten endre seg umiddelbart fra
``Hello, World!'' til ``Goodbye, Cruel
World!''
Du kan også spørre widgets om verdien av spesifikke opsjoner ved å bruke cget:
require 'tk'
|
||
b = TkButton.new {
|
||
text "OK"
|
||
justify 'left'
|
||
border 5
|
||
}
|
||
b.cget('text')
|
» |
"OK"
|
b.cget('justify')
|
» |
"left"
|
b.cget('border')
|
» |
5
|
| Figur 15.2: Pig Latin program skjermbilde |
![]() |
require 'tk'
class PigBox
def pig(word)
leadingCap = word =~ /^A-Z/
word.downcase!
res = case word
when /^aeiouy/
word+"way"
when /^([^aeiouy]+)(.*)/
$2+$1+"ay"
else
word
end
leadingCap ? res.capitalize : res
end
def showPig
@text.value = @text.value.split.collect{|w| pig(w)}.join(" ")
end
def initialize
ph = { 'padx' => 10, 'pady' => 10 } # common options
p = proc {showPig}
@text = TkVariable.new
root = TkRoot.new { title "Pig" }
top = TkFrame.new(root)
TkLabel.new(top) {text 'Enter Text:' ; pack(ph) }
@entry = TkEntry.new(top, 'textvariable' => @text)
@entry.pack(ph)
TkButton.new(top) {text 'Pig It'; command p; pack ph}
TkButton.new(top) {text 'Exit'; command {proc exit}; pack ph}
top.pack('fill'=>'both', 'side' =>'top')
end
end
PigBox.new
Tk.mainloop
|
| Litt på siden: Håndtering av geometrien | |||||||||||||||||
I kodeeksemplene i dette kapittelet vil du ofte se bruk av widget metoden
pack. Det er en viktig metode, viser det seg---dersom du glemmer
å kalle den, får du ikke se din widget. Metoden pack er en kommando
som gir beskjed til kontrolleren som styrer geometrien om å plasse vår
widget i følge de beskrankninger vi har angitt. Tre kommandoer kan sendes
til geometrikontrollere:
pack er den kommandoen som brukes oftest, vil vi holde oss til den i våre eksempler.
|
|||||||||||||||||
bind hos din widget.
La oss for eksempel anta at vi har laget en knapp som viser et bilde.
Vi ønsker at bildet skal endre seg når brukeren har muspekeren over knappen.
image1 = TkPhotoImage.new { file "img1.gif" }
image2 = TkPhotoImage.new { file "img2.gif" }
b = TkButton.new(@root) {
image image1
command proc { doit }
}
b.bind("Enter") { b.configure('image'=>image2) }
b.bind("Leave") { b.configure('image'=>image1) }
|
TkPhotoImage. Dernest lager vi en knapp (som kalles ``b''
for button), som viser bildet image1. Så binder vi hendelsen
``Enter'' slik at den dynamisk endrer bildet som vises på knappen til
image2, og ``Leave'' hendelsen slik at den bytter tilbake til image1.
Dette eksempelet viser de enkle hendelsene ``Enter'' og ``Leave.''
Ben hendelsen gitt som argument til bind kan være sammensatt av flere understrenger, separert med bindestrek, av rekkefølgen
modifikator-modifikator-type-detalj.
Modifikatorene er listet opp i Tk referansen og inkluderer
Button1, Control, Alt, Shift, og så
videre. Type er navnet på hendelsen (tatt utifra navnekonvensjonene
til X11) og inkluderer hendelser som ButtonPress, KeyPress,
og Expose. Detail er enten et tall fra 1 til 5 for
knapper eller en keysym(??) for innput fra tastaturet.
For eksempel, en binding som som vil kjøres når musens første knapp slippes samtidig med at Control tasten holdes inne, kunne spesifiseres slik:
Control-Button1-ButtonRelease
Control-ButtonRelease-1
Selve hendelsen kan inneholde visse felt, slik som tidspunktet og koordinatene til hendelsen. bind kan sende disse videre til tilbakekallsrutinen ved å bruke hendelsesfeltkoder (event field codes). Disse brukes på samme måte som printf spesifikasjoner.
For eksempel, for å få tak i x og y koordinatene til en musbevegelse, spesifiserer du kallet til bind med tre parametre. Den andre parameteren er Proc-objektet som skal brukes som tilbakekallsrutine, og den tredje parameteren er hendelsens feltstreng.
canvas.bind("Motion", proc{|x, y| do_motion (x, y)}, "%x %y")
|
require 'tk'
class Draw
def do_press(x, y)
@start_x = x
@start_y = y
@current_line = TkcLine.new(@canvas, x, y, x, y)
end
def do_motion(x, y)
if @current_line
@current_line.coords @start_x, @start_y, x, y
end
end
def do_release(x, y)
if @current_line
@current_line.coords @start_x, @start_y, x, y
@current_line.fill 'black'
@current_line = nil
end
end
def initialize(parent)
@canvas = TkCanvas.new(parent)
@canvas.pack
@start_x = @start_y = 0
@canvas.bind("1", proc{|e| do_press(e.x, e.y)})
@canvas.bind("2", proc{ puts @canvas.postscript({}) })
@canvas.bind("B1-Motion", proc{|x, y| do_motion(x, y)}, "%x %y")
@canvas.bind("ButtonRelease-1",
proc{|x, y| do_release (x, y)}, "%x %y")
end
end
root = TkRoot.new{ title 'Canvas' }
Draw.new(root)
Tk.mainloop
|
| Figur 15.3: ``We couldn't find the artist, so we had to hang the picture....'' |
![]() |
TkCanvas, TkListbox og
TkText kan settes opp til å bruke rullegardiner (scrollbars), slik at du kan arbeide med et mindre utsnitt av hele bildet.
Kommunikasjonen mellom en rullegardin og en widget er toveis. Flyttes rullegardinen må den tilhørende widget endre det den fiser frem. Men også når en widget endres, må rullegardinen oppdateres for å vise den nye posisjonen.
Siden vi ikke har brukt lister noe særlig ennå, vil rullegardineksempelet
vårt bruke en rullende liste med tekst. I den neste kodebiten begynner vi
med å lage en ganske alminnelig TkListbox.
Deretter lager vi en TkScrollbar.
Rullegardinets tilbakekallsrutine (som settes med command) vil
kalle listens widgets yview metode, som endrer verdien til den
synlige porsjonen av listen i y-retningen.
Etter at den tilbakekallsrutinen er satt opp, lager vi den motsatte
bindingen også: når listen føler behov for å rulle, angir vi den passende
rekkevidden til rullegardinet med
TkScrollbar#set.
Vi kommer til å bruke akkurat denne kodebiten i et fullstendig funksjonelt program i neste avsnitt.
list_w = TkListbox.new(frame, 'selectmode' => 'single')
scroll_bar = TkScrollbar.new(frame,
'command' => proc { |*args| list_w.yview *args })
scroll_bar.pack('side' => 'left', 'fill' => 'y')
list_w.yscrollcommand(proc { |first,last|
scroll_bar.set(first,last) })
|
File.new
bruker en blokk for å forsikre seg om at filen blir lukket etter at man er ferdig med å bruke den? Vi kan gjøre en lignende ting med metoden busy, som vist i det neste eksempelet.
Dette programmet demonstrer også noen enkle manipulasjoner man kan gjøre med en TkListbox---legge elementer til listen, sette opp et tilbakekall på slipp av musknappen,[Du ønsker sannsynligvis knappeslipp og ikke knappetrykk, da knappetrykkhendelsen selekterer widget.]
og hente ut det nåværende valget.
Inntill nå har vi brukt TkPhotoImage utelukkende til å vise frem ikoner direkte, men du kan også forstørre, redusere og vise deler av bilder også. Her bruker vi reduksjon til å skalere bildet ned for visning.
require 'tk'
def busy
begin
$root.cursor "watch" # Set a watch cursor
$root.update # Make sure it updates the screen
yield # Call the associated block
ensure
$root.cursor "" # Back to original
$root.update
end
end
$root = TkRoot.new {title 'Scroll List'}
frame = TkFrame.new($root)
list_w = TkListbox.new(frame, 'selectmode' => 'single')
scroll_bar = TkScrollbar.new(frame,
'command' => proc { |*args| list_w.yview *args })
scroll_bar.pack('side' => 'left', 'fill' => 'y')
list_w.yscrollcommand(proc { |first,last|
scroll_bar.set(first,last) })
list_w.pack('side'=>'left')
image_w = TkPhotoImage.new
TkLabel.new(frame, 'image' => image_w).pack('side'=>'left')
frame.pack
list_contents = Dir["screenshots/gifs/*.gif"]
list_contents.each {|x|
list_w.insert('end',x) # Insert each file name into the list
}
list_w.bind("ButtonRelease-1") {
index = list_w.curselection[0]
busy {
tmp_img = TkPhotoImage.new('file'=> list_contents[index])
scale = tmp_img.height / 100
scale = 1 if scale < 1
image_w.copy(tmp_img, 'subsample' => [scale,scale])
tmp_img = nil # Be sure to remove it, the
GC.start # image may have been large
}
}
Tk.mainloop
|
| Figur 15.4: Scroll List skjermbilde |
![]() |
nil og kalte på søppeltømmeren umiddelbart for å fjerne rasket.
TkWidget som brukes, og ikke instansen av din klasse.
Perl/Tk: $widget = $parent->Widget( [ option => value ] )
Ruby: widget = TkWidget.new(parent, option-hash)
widget = TkWidget.new(parent) { code block }
|
Perl/Tk: -background => color
Ruby: 'background' => color
{ background color }
|
Perl/Tk: -textvariable => \$variable
-textvariable => varRef
Ruby: ref = TkVariable.new
'textvariable' => ref
{ textvariable ref }
|
TkVariable for å koble en Ruby variabel til en variabel i en widget. Du kan da bruke value tilgangsmetodene i
TkVariable
(TkVariable#value og
TkVariable#value=)
for å påvirke innholdet i en widget direkte.
( In progress translation to Norwegian by NorwayRUG. $Revision: 1.9 $ )
$Log: ext_tk.xml,v $ Revision 1.9 2002/10/20 20:09:19 kent skriveleif. Revision 1.8 2002/09/23 19:38:50 kent Første kladd ferdig. Revision 1.7 2002/09/21 13:11:51 kent Nesten frem til canvas med første kladd. Revision 1.6 2002/09/21 09:56:26 kent Frem til geometri håndtering. Revision 1.5 2002/09/16 18:35:24 kent Et par avsnitt, frem til "Getting Widget Data" Revision 1.4 2002/09/14 08:37:30 kent Såvidt begynt.
| Forrige < |
Innhold ^
|
Neste >
|