LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Perl (126) - Gtk2 - textové okno a práce s pozicemi

Perl Základním widgetem pro zobrazování a editaci textu v Gtk2 je textové pole. Umí řadu zajímavých věcí - mimo očekávaných funkcionalit také formátování textu a vkládání widgetů. Na to vše je potřeba dobře rozumět reprezentaci pozic, což jsou objekty určující místa v textovém poli.

27.1.2011 00:00 | Jiří Václavík | Články autora | přečteno 7268×

Gtk2::TextView je často používaný widget na zobrazování a editaci textu. Tento widget má ještě podstatně více různých funkcí a nastavení, než textová pole v Tk a Wx, která jsme si již představovali.

Na úvod se podívejme na základní použití.

$text = Gtk2::TextView->new;
$buffer = $text->get_buffer();
$buffer->set_text("zkus sem neco napsat");

Právě jsme vytvořili textové pole a napsali do něj text. Uživatel ho může libovolně editovat.

.

Ukázka Gtk2::TextView

Na první pohled je kód zdánlivě zbytečně složitý (Proč nepoužít něco jako Gtk2::TextView->set_text? Proč to musíme řešit přes buffer?). Uvidíme, že to zas o tolik složitější není a že lze takto s textem pohodlně manipulovat. Text (společně s informací, jak má být zobrazen) je zde reprezentován speciálním widgetem Gtk2::TextBuffer a až ten můžeme nastavit pomocí set_buffer.

Podívejme se na úvod jen ve stručnosti na některé základní metody Gtk2::TextView.

MetodaVýznam
set_wrap_modemetoda zalamování; možné hodnoty jsou none, char nebo word
set_editablefalse pro read-only, true pro editaci
set_cursor_visibleviditelnost kurzoru (kurzor bychom měli schovat vždy, když používáme read-only režim)
set_justificationzarovnání textu; možné hodnoty jsou left, right, center
set_left_margin, set_right_marginokraje
set_indentodsazení

Existuje-li metoda s názvem set_něco, pak také často existuje metoda get_něco, která detekuje aktuální nastavení.

Objekt typu Gtk2::TextIter reprezentuje pozici v bufferu. Pozice je platná vždy jen do okamžiku, kdy se obsah bufferu (tj. text v Gtk2::TextView) změní. Protože často chceme pozice zachovat i po změně obsahu bufferu, byly vytvořeny objekty typu Gtk2::TextMark, což jsou hýbající se pozice.

Vlastnosti TextBufferu

Gtk2::TextBuffer je vytvořen vždy, když vytvoříme Gtk2::TextView. Samozřejmě si ale můžeme standardní cestou vytvořit TextBuffer vlastní.

$textbuffer = Gtk2::TextBuffer->new;

Podívejme se na metody, kterými lze s textem v TextBufferu manipulovat.

MetodaVýznam
set_textnastaví text
insert($textiter, $text)vloží $text na pozici $textiter (jak víme, pozice je objekt typu Gtk2::TextIter; více o tom dále)
insert_at_cursorvloží text na aktuální pozici
insert_range($kam, $zacatek, $konec)výsek určený dle $zacatek, $konec se uloží na pozici $kam
get_text($zacatek, $konec, $ukazat_skryte)vrátí výsek
get_slice($zacatek, $konec, $ukazat_skryte)vrátí výsek, obrázky budou vráceny jako znak 0xFFFC; více o tom dále
get_line_count, get_char_count zjistí počet řádků, resp. znaků

Práce s pozicemi

Již víme, že pozici v TextBufferu uchovává objekt Gtk2::TextIter. Podívejme se na to, jak s pozicemi pracovat. Pozici v bufferu definujeme jednou z následujících metod zavolaných nad TextBufferem.

PříkazKde se vytvoří TextIter?
$textiter=$textbuffer->get_start_iter;před prvním znakem
$textiter=$textbuffer->get_end_iter;za posledním znakem
$textiter=$textbuffer->get_iter_at_offset(50);před padesátým znakem
$textiter=$textbuffer->get_iter_at_line($radek);před prvním znakem řádku č. $radek
$textiter=$textbuffer->get_iter_at_line_offset(5, 10);před 10. znak na 5. řádku
$textiter=$textbuffer->get_iter_at_mark($mark);na pozici existujícícho Gtk2::TextMark
($ti1,$ti2)=$buffer->get_selection_bounds;na hranice vybrané oblasti

Nad objekty typu Gtk2::TextIter lze pak volat obrovské množství dalších metod. Podívejme se na seznam těch, které se mohou hodit.

MetodaVýznam
Detekce pozice v kontextu slov a řádků
starts_word, ends_word, inside_word, starts_sentence, ends_sentence, inside_sentence, starts_line, ends_line, is_end, is_start, is_cursor_positionzjišťování informací o pozici
in_range($zacatek, $konec)jsme v daném rozmezí?
Zjišťování absolutní pozice
get_offsetvrátí číslo znaku
get_linevrátí číslo řádku
get_line_offsetvrátí číslo znaku na řádku
Pohyb TextIterů
forward_char, backward_char, forward_word_end, backward_word_start, forward_sentence_end, backward_sentence_start, forward_line, backward_line, forward_to_line_end, forward_cursor_position, backward_cursor_position, forward_to_endpohyb na pozici v kontextu slov a řádků
forward_chars($kolik), backward_chars($kolik), forward_word_ends($kolik), backward_word_starts($kolik), forward_sentence_ends($kolik), backward_sentence_starts($kolik), forward_lines($kolik), backward_lines($kolik), forward_cursor_positions($kolik), backward_cursor_positions($kolik)to samé vícenásobně
set_offset($offset)nastaví na danou pozici
set_line($radek)nastaví na daný řádek
set_line_offset($offset_na_radku)nastaví na pozici na aktuálním řádku
Získávání textu z TextBufferu
get_char vrátí znak
get_text($do)vrátí úsek textu
get_slice($do)vrátí úsek textu
Detekce dalších objektů na dané pozici
get_marksvrátí seznam objektů Gtk2::TextMark
get_tagsvrátí seznam tagů, tj. objektů typu Gtk2::TextTag
get_pixbufvrátí seznam objektů Gtk2::PixBuf
get_child_anchorvrátí seznam objektů Gtk2::TextChildAnchor
has_tag, begins_tag, ends_tagdetekce tagů
Hledání v textu
forward_search($retezec, 'text-only', $kam_az)vrátí dvouprvkový seznam s počáteční a koncovou pozicí typu Gtk2::TextIter, hledání dopředu; druhý parametr je typu Gtk2::TextSearchFlags
backward_search($retezec, 'text-only', $kam_az)vrátí dvouprvkový seznam s počáteční a koncovou pozicí typu Gtk2::TextIter, hledání dozadu; druhý parametr je typu Gtk2::TextSearchFlags
Ostatní
get_attributesvrátí objekt typu Gtk2::TextAttributes

Gtk2::TextMark je podobný jako Gtk2::TextIter, avšak zachovává pozice při změnách TextBufferu.

Podívejme se opět, jak lze vytvořit objekt typu Gtk2::TextMark.

PříkazKde se vytvoří TextMark?
$textmark = $textbuffer->get_insertaktuální pozice kurzoru
$textmark = $textbuffer->get_selection_bounddruhý konec výběru (prvním koncem je pozice kurzoru)
$textmark = $textbuffer->create_mark($nazev, $textiter, $zleva)Gtk2::TextMark s názvem $nazev se vytvoří na pozici $textiter s tím, že při vkládání na tuto pozici se posouvá/neposouvá doleva

TextMarky lze ručně posouvat pomocí TextIterů jedním z následujících příkazů.

$textbuffer->move_mark($mark, $kam);
$textbuffer->move_mark_by_name($nazev, $kam); 

Metodou get_mark získáme objekt typu Gtk2::TextMark na základě svého názvu.

Tagy - formátování textu

Objekty typu Gtk2::TextTag jsou dalším obsahem TextBufferů. Obsahují informace o formátování. Každý tag funguje na daných pozicích a má nějaký svůj efekt (například zvětšuje písmo na druhém řádku).

Společně s bufferem se vždy vytvoří i objekt typu Gtk2::TextTagTable. Zde je uchováván seznam tagů.

Tag vytvoříme metodou create_tag zavolanou nad TextBufferem.

$tag = $textbuffer->create_tag($nazev, %vlastnosti); 

Poté jsou dvě možnosti, jak tagy aplikovat. Buď přímo nebo opět podle názvu.

$textbuffer->apply_tag($tag, $zacatek, $konec); 
$textbuffer->apply_tag_by_name($nazev, $zacatek, $konec);

Stejně tak můžeme tagy odstraňovat.

$textbuffer->remove_tag($tag, $zacatek, $konec); 
$textbuffer->remove_tag_by_name($nazev, $zacatek, $konec);

Vlastnosti lze nastavovat metodou set_property.

Pomocí set_priority nastavujeme pro tag prioritu mezi 0 a velikostí Gtk2::TextTagTable.

Podívejme se na hash parametrů, které ovlivňují chování tagu. Jaké všechny paramety můžeme používat?

KlíčVýznam a hodnoty
background, background-gdkbarva pozadí pomocí řetězce, resp, Gtk2::Gdk::Color
foreground, foreground-gdkbarva popředí pomocí řetězce, resp, Gtk2::Gdk::Color
background-stipple, foreground-stipplepoužije se na pozadí / popředí maska (bitmapa)
fontpísmo (například Times 12)
size, size-pointsvelikost písma v Pango bodech, resp. v bodech
scalerelativní velikost písma oproti okolí
font-descstyl písma (jako objekt typu Gtk2::Pango::FontDescription)
familynapříklad Times
underlinepodtržené písmo
style, variant, weight, stretchhodnoty jsou v dokumentaci
pixels-above-lines, pixels-below-linesmezera v pixelech nad / pod řádkem
wrap-modejak zalamovat (none, word, char)
justificationleft, right, center
directionsměr toku textu (right-to-left, left-to-right)
left-margin, right-marginokraje
indentodsazení odstavce
strikethroughdělení
riseposunutí nahoru (dolů při záporném parametru)
background-full-heightmá-li tag ovlivnit celý řádek ve smyslu barvy pozadí

Zkusíme si vytvořit nějaký tag.

$tag = $buffer->create_tag("zvyrazneny_text",
    "font" => "Helvetica 30",
    "underline" => PANGO_UNDERLINE_DOUBLE,
    "foreground" => "darkgreen",
    "background-gdk" => Gtk2::Gdk::Color->new(60, 0, 200)); 
$buffer->apply_tag($tag, $buffer->get_iter_at_offset(3), $buffer->get_iter_at_offset(7)); 

Výsledek spatříme po spuštění aplikace.

TextView s otagovaným úsekem textu

Vkládání widgetů

Do textového pole lze vkládat také obrázky nebo rovnou celé widgety. Obrázky reprezentované jako Gtk2::PixBuf můžeme vkládat metodou insert_pixbuf na danou pozici. Takový obrázek se bude chovat jako unicodový znak 0xFFFC.

$textbuffer->insert_pixbuf($textiter, $pixbuf) 

S widgety je to trochu složitější, ale v zásadě podobné. Vytvoříme objekt typu Gtk2::TextChildAnchor na místě, kde chceme, aby byl widget. Poté na toto místo widget vložíme.

$anchor = Gtk2::TextChildAnchor->new;
$textbuffer->insert_child_anchor($iter, $anchor);
$textview->add_child_at_anchor($widget, $anchor);

Ukážeme si konkrétnější příklad - TextView, do kterého vložíme text, obrázek a tlačítko.

$textview = Gtk2::TextView->new;
$buffer = $textview->get_buffer();
$buffer->set_text("nejaky text");

$tlacitko = Gtk2::Button->new("tlacitko");

$anchor = Gtk2::TextChildAnchor->new;
$buffer->insert_child_anchor($buffer->get_start_iter, $anchor);
$textview->add_child_at_anchor($tlacitko, $anchor);

$buffer->insert_pixbuf($buffer->get_start_iter, Gtk2::Gdk::Pixbuf->new_from_file("./Ghost.png"));

Text pak můžeme samozřejmě libovolně editovat. Vložené objekty se chovají jako znaky.

TextView s widgetem a obrázkem

Příklad - zvýraznění textu pod kurzorem myši

Ukážeme si, jak lze zachytávat pozici myši a manipulovat s textem (popřípadě tagem) na jejím aktuálním místě.

Díky signálu motion_notify_event, který je emitován při změně pozice myši nad daným widgetem můžeme vyvolat akci. Ta bude například zvýrazňovat místo, kde je aktuálně myš.

$textview->signal_connect(motion_notify_event => \&akce);

Díky metodě window_to_buffer_coords zjistíme pixelové souřadnice. Ty nám metoda get_iter_at_location převede na pozici v textu, tj. objekt typu Gtk2::TextIter. Pak není nic jednoduššího, než s danou pozicí manipulovat.

Vytvoříme tedy tag, kterým budeme zvýrazňovat aktuální znak.

my $tag = $buffer->create_tag(undef, "foreground" => "white", "background" => "black");

Aplikujeme ho. Na to ovšem musíme mít dva TextItery (potřebujeme začátek i konec tagu). Vytvoříme si tedy kopii našeho TextIteru a posuneme ho o pozici vpřed. TextIter nemá vhodný konstruktor na kopírování objektů a poradíme si tak trochu oklikou.

my $textiter2 = $buffer->get_iter_at_offset($textiter->get_offset);
$textiter->forward_char;
$buffer->apply_tag($tag, $textiter2, $textiter); 

Ještě bychom měli uchovávat starý tag a mazat ho po opuštění pozice. Zavedeme si tedy proměnnou $kurzor_tag, která bude reprezentovat týž objekt jako $tag do doby, než $tag zapomeneme. Tag pak smažeme přes tabulku tagu, kterou získáme z bufferu.

my $table = $buffer->get_tag_table;
$table->remove($kurzor_tag) if defined $kurzor_tag;

Podívejme se na celý zdrojový kód naší akce.

sub akce {
    my($textview, $udalost) = @_;
    my $textiter = $textview->get_iter_at_location(
$textview->window_to_buffer_coords("widget",$udalost->x, $udalost->y));
    my $textiter2 = $buffer->get_iter_at_offset($textiter->get_offset);
    $textiter->forward_char;
    my $tag = $buffer->create_tag(undef, "foreground" => "white", "background" => "black");
    my $table = $buffer->get_tag_table;
    $table->remove($kurzor_tag) if defined $kurzor_tag;
    $buffer->apply_tag($tag, $textiter2, $textiter); 
    $kurzor_tag=$tag;
}

Vidíme, že na místě kurzoru se aplikoval náš tag

tag pod kurzorem myši

Verze pro tisk

pridej.cz

 

DISKUZE

Nejsou žádné diskuzní příspěvky u dané položky.



Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

14.11.2017 16:56 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tradičně první čtvrtek před třetím pátkem v měsíci: 16. listopadu od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.11.2017 11:06 /Redakce Linuxsoft.cz
PR: 4. ročník odborné IT konference na téma Datová centra pro business proběhne již ve čtvrtek 23. listopadu 2017 v konferenčním centru Vavruška, v paláci Charitas, Karlovo náměstí 5, Praha 2 (u metra Karlovo náměstí) od 9:00. Konference o návrhu, budování, správě a efektivním využívání datových center nabídne odpovědi na aktuální a často řešené otázky, např Jaké jsou aktuální trendy v oblasti datových center a jak je využít pro vlastní prospěch? Jak zajistit pro firmu či jinou organizaci odpovídající služby datových center? Podle jakých kritérií vybrat dodavatele služeb? Jak volit součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně spravovat datové centrum? Jak eliminovat možná rizika? apod.
Přidat komentář

13.9.2017 8:00 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tentokrát netradičně v pondělí: 18. září od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

3.9.2017 20:45 /Redakce Linuxsoft.cz
PR: Dne 21. září 2017 proběhne v Praze konference "Mobilní řešení pro business". Hlavní tématy konference budou: nejnovější trendy v oblasti mobilních řešení pro firmy, efektivní využití mobilních zařízení, bezpečnostní rizika a řešení pro jejich omezení, správa mobilních zařízení ve firmách a další.
Přidat komentář

15.5.2017 23:50 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt, který se bude konat ve čtvrtek 18. května od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.5.2017 16:42 /Honza Javorek
PyCon CZ, česká konference o programovacím jazyce Python, se po dvou úspěšných ročnících v Brně bude letos konat v Praze, a to 8. až 10. června. Na konferenci letos zavítá např. i Armin Ronacher, známý především jako autor frameworku Flask, šablon Jinja2/Twig, a dalších projektů. Těšit se můžete na přednášky o datové analytice, tvorbě webu, testování, tvorbě API, učení a mentorování programování, přednášky o rozvoji komunity, o použití Pythonu ve vědě nebo k ovládání nejrůznějších zařízení (MicroPython). Na vlastní prsty si můžete na workshopech vyzkoušet postavit Pythonem ovládaného robota, naučit se učit šestileté děti programovat, efektivně testovat nebo si v Pythonu pohrát s kartografickým materiálem. Kupujte lístky, dokud jsou.
Přidat komentář

2.5.2017 9:20 /Eva Rázgová
Putovní konference československé Drupal komunity "DrupalCamp Československo" se tentokrát koná 27. 5.2017 na VUT FIT v Brně. Můžete načerpat a vyměnit si zkušenosti z oblasti Drupalu 7 a 8, UX, SEO, managementu týmového vývoje, využití Dockeru pro Drupal a dalších. Vítáni jsou nováčci i experti. Akci pořádají Slovenská Drupal Asociácia a česká Asociace pro Drupal. Registrace na webu .
Přidat komentář

1.5.2017 20:31 /Pavel `Goldenfish' Kysilka
PR: 25.5.2017 proběhne v Praze konference na téma Firemní informační systémy. Hlavními tématy jsou: Informační systémy s vlastní inteligencí, efektivní práce s dokumenty, mobilní přístup k datům nebo využívání cloudu.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

5.12.2017 11:50 / Thomas
kitchen renovations

18.9.2017 14:37 / Rojas
high security vault

15.9.2017 7:33 / Wilson
new zealand childcare jobs

31.8.2017 12:11 / Jaromir Obr
Re: ukůládání dat ze souboru

30.7.2017 11:12 / Jaromir Obr
Národní znaky

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2017) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze