<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="http://wiki2.linuxformat.ru/skins/common/feed.css?97"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title>LXF93:GTK+ - История изменений</title>
		<link>http://wiki2.linuxformat.ru/index.php?title=LXF93:GTK%2B&amp;action=history</link>
		<description>История изменений этой страницы в вики</description>
		<language>ru</language>
		<generator>MediaWiki 1.11.1</generator>
		<lastBuildDate>Thu, 14 May 2026 01:19:13 GMT</lastBuildDate>
		<item>
			<title>Crazy Rebel в 11:37, 26 ноября 2008</title>
			<link>http://wiki2.linuxformat.ru/index.php?title=LXF93:GTK%2B&amp;diff=5627&amp;oldid=prev</link>
			<description>&lt;p&gt;&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Предыдущая&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Версия 11:37, 26 ноября 2008&lt;/td&gt;
			&lt;/tr&gt;
		&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Строка 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;-&lt;/td&gt;&lt;td style=&quot;background: #ffa; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;[[Категория:&lt;del style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;Учбники&lt;/del&gt;]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;background: #cfc; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;[[Категория:&lt;ins style=&quot;color: red; font-weight: bold; text-decoration: none;&quot;&gt;Учебники&lt;/ins&gt;]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;: '''GTK+''' Разработка переносимых приложений с графическим интерфейсом пользователя&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background: #eee; color:black; font-size: smaller;&quot;&gt;&lt;div&gt;: '''GTK+''' Разработка переносимых приложений с графическим интерфейсом пользователя&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</description>
			<pubDate>Wed, 26 Nov 2008 11:37:42 GMT</pubDate>			<dc:creator>Crazy Rebel</dc:creator>			<comments>http://wiki2.linuxformat.ru/index.php/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:LXF93:GTK%2B</comments>		</item>
		<item>
			<title>Yaleks: «LXF93:Anjuta» переименована в «LXF93:GTK+»: унификация</title>
			<link>http://wiki2.linuxformat.ru/index.php?title=LXF93:GTK%2B&amp;diff=5576&amp;oldid=prev</link>
			<description>&lt;p&gt;«&lt;a href=&quot;/index.php/LXF93:Anjuta&quot; title=&quot;LXF93:Anjuta&quot;&gt;LXF93:Anjuta»&lt;/a&gt; переименована в «&lt;a href=&quot;/index.php/LXF93:GTK%2B&quot; title=&quot;LXF93:GTK+&quot;&gt;LXF93:GTK+»&lt;/a&gt;: унификация&lt;/p&gt;

			&lt;table style=&quot;background-color: white; color:black;&quot;&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;col class='diff-marker' /&gt;
			&lt;col class='diff-content' /&gt;
			&lt;tr&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;← Предыдущая&lt;/td&gt;
				&lt;td colspan='2' style=&quot;background-color: white; color:black;&quot;&gt;Версия 20:54, 24 ноября 2008&lt;/td&gt;
			&lt;/tr&gt;
		&lt;/table&gt;</description>
			<pubDate>Mon, 24 Nov 2008 20:54:30 GMT</pubDate>			<dc:creator>Yaleks</dc:creator>			<comments>http://wiki2.linuxformat.ru/index.php/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:LXF93:GTK%2B</comments>		</item>
		<item>
			<title>Crazy Rebel: викификация, оформление</title>
			<link>http://wiki2.linuxformat.ru/index.php?title=LXF93:GTK%2B&amp;diff=5565&amp;oldid=prev</link>
			<description>&lt;p&gt;викификация, оформление&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Новая статья&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Категория:Учбники]]&lt;br /&gt;
&lt;br /&gt;
: '''GTK+''' Разработка переносимых приложений с графическим интерфейсом пользователя&lt;br /&gt;
&lt;br /&gt;
==Anjuta: Создаем текстовый редактор==&lt;br /&gt;
&lt;br /&gt;
{{Цикл/GTK+}}&lt;br /&gt;
&lt;br /&gt;
'''ЧАСТЬ 7''' Калькулятор, самая необходимая деталь рабочего стола, у нас уже есть – теперь настало время подумать и о текстовом редакторе. Берегись, Блокнот – '''Андрей Боровский''' запускает ''Anjuta''!&lt;br /&gt;
&lt;br /&gt;
:::''– Разве имя должно что-то значить? – проговорила Алиса с сомнением.''&lt;br /&gt;
:::''– Конечно, должно, – ответил Шалтай-Болтай и фыркнул. – Возьмем, к примеру, мое имя – оно выражает мою суть!&lt;br /&gt;
::::::''Льюис Кэрролл, Алиса в Зазеркалье''&lt;br /&gt;
&lt;br /&gt;
В прошлой статье мы научились создавать программы GNOME своими руками, начиная, как говорится, с пустого файла. На этот раз мы автоматизируем процесс создания «заготовки» для нашей&lt;br /&gt;
программы с помощью среды разработки ''Anjuta'' (в русском переводе,&lt;br /&gt;
естественно, Анюта). Вот что написано о происхождении этого имени&lt;br /&gt;
на сайте разработчиков ''Anjuta'' (http://anjuta.sourceforge.net): «[Это имя] не&lt;br /&gt;
обозначает ничего, Наба Кумар (Naba Kumar) начал работу над проектом&lt;br /&gt;
''Anjuta'' и назвал его в честь своей девушки, так как программа посвящена&lt;br /&gt;
именно ей». Для полного прояснения вопроса осталось узнать, что имели в виду родители, когда назвали свою дочь Anjuta...&lt;br /&gt;
&lt;br /&gt;
Интегрированную среду ''Anjuta'' можно рассматривать как аналог&lt;br /&gt;
''KDevelop'' для ''GTK+''. Помимо приложений ''GTK+'' и GNOME, ''Anjuta'' позволяет генерировать заготовки простых консольных программ, программ ''wxWindows'' (так это название пишется в настройках программы;&lt;br /&gt;
ныне данный инструментарий называется ''wxWidgets''), а также проекты «чистых» приложений X-Window, использующих для построения&lt;br /&gt;
интерфейса только ''Xlib''. В качестве языка программирования можно&lt;br /&gt;
выбрать ''C'' или ''C++''. Как и ''KDevelop'', ''Anjuta'' не обладает собственными&lt;br /&gt;
средствами визуального программирования – для этих целей используется уже знакомый нам ''Glade''.&lt;br /&gt;
&lt;br /&gt;
В этой статье мы детально исследуем процесс написания простенького текстового редактора GNOME средствами тандема ''Anjuta'' и ''Glade''.&lt;br /&gt;
Запустите программу ''Anjuta''. По умолчанию, она открывает диалоговое&lt;br /&gt;
окно (Рис. 1), в котором мы можем выбрать режим работы с ''Anjuta''.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:LXF93_anjuta1.jpg|Рис. 1]]&lt;br /&gt;
&lt;br /&gt;
'''Рис. 1. Окно выбора режима работы ''Anjuta''.'''&lt;br /&gt;
&lt;br /&gt;
Щелкните по кнопке '''Мастер приложений'''. Перед нами предстает первое окно '''Мастера приложений''' ''Anjuta''.&lt;br /&gt;
&lt;br /&gt;
Запустить '''Мастер приложений''' можно также с помощью команды&lt;br /&gt;
меню '''Файл–&amp;gt;Новый проект...''' (команда '''Новый проект...''' расположена,&lt;br /&gt;
почему-то в меню '''Файл''', а не в меню '''Проект''). В '''Мастере приложений'''&lt;br /&gt;
нажмите кнопку '''Далее''' – вы перейдете к окну, в котором предлагается&lt;br /&gt;
указать тип проекта (Рис. 2). Выберите проект GNOME 2.0. В ответ на&lt;br /&gt;
щелчок по кнопке '''Далее''' открывается окно, в котором следует ввести&lt;br /&gt;
название нового проекта, версию, имя автора и язык разработки (здесь&lt;br /&gt;
следует выбрать '''C''': если указать '''C++''', вы лишитесь функции автоматической генерации кода с помощью ''Glade'').&lt;br /&gt;
&lt;br /&gt;
[[Изображение:LXF93_anjuta2.jpg|Рис. 2]]&lt;br /&gt;
&lt;br /&gt;
'''Рис. 2. Окно выбора типа проекта Anjuta.'''&lt;br /&gt;
&lt;br /&gt;
Еще одно важное окно '''Мастера приложений''' (Рис. 3) позволяет&lt;br /&gt;
нам определить дополнительные параметры нового проекта – нужно&lt;br /&gt;
ли добавлять текст лицензии GPL во все файлы исходных текстов и&lt;br /&gt;
добавлять ли код, предназначенный для работы с '''gettext'''. Даже если вы&lt;br /&gt;
не собираетесь выполнять интернационализацию своего приложения в&lt;br /&gt;
обозримом будущем, ее поддержку все равно стоит включить, просто&lt;br /&gt;
на всякий случай. Окно дополнительных параметров проекта позволит&lt;br /&gt;
вам активировать режим генерации исходных текстов с помощью ''Glade''&lt;br /&gt;
(в ''Glade 2.x'' это все еще возможно), что и следует сделать. В этом же&lt;br /&gt;
окне '''Мастера приложений''' можно выбрать пиктограмму для нового&lt;br /&gt;
приложения и указать, нуждается ли оно для своей работы в открытом&lt;br /&gt;
окне консоли. На этом генерация нового проекта заканчивается.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:LXF93_anjuta3.jpg|Рис. 3]]&lt;br /&gt;
&lt;br /&gt;
'''Рис. 3. Окно дополнительных параметров проекта.'''&lt;br /&gt;
&lt;br /&gt;
В левой части главного окна ''Anjuta'' расположено окно менеджера&lt;br /&gt;
проектов. На вкладке '''«Проект»''' этого окна перечислены файлы исходных текстов приложения. Помимо файла '''main.c''' мы видим здесь файлы '''callbacks.c, callbacks.h, interface.c, interface.h, support.c''' и '''support.h'''.&lt;br /&gt;
Если имена этих файлов показались вам знакомыми, интуиция вас не&lt;br /&gt;
подвела – это файлы проекта ''Glade'' (мы недаром установили флажок&lt;br /&gt;
'''Generate source code using Glade or Glademm''' в '''Мастере приложений''').&lt;br /&gt;
Теперь можно приступать к созданию интерфейса нашей программы.&lt;br /&gt;
&lt;br /&gt;
===Макет интерфейса===&lt;br /&gt;
&lt;br /&gt;
Команда меню '''Проект–&amp;gt;Редактировать''' графический интерфейс приложения... запускает экземпляр '''Glade''' для нашего проекта. При совместном использовании ''Anjuta'' и ''Glade'' следует учитывать, что эти программы слабо взаимодействуют между собой. Для того чтобы изменения,&lt;br /&gt;
внесенные в проект с помощью ''Glade'', стали известны ''Anjuta'', нужно&lt;br /&gt;
выполнить сохранение проекта в ''Glade'' (и не забывайте нажать кнопку&lt;br /&gt;
Построить, чтобы ''Glade'' мог отразить в исходном коде изменения, внесенные в визуальном редакторе). Фактически, при работе с ''Glade'' нам почти всегда придется сохранять проект по два раза – один раз в ''Glade'',&lt;br /&gt;
другой раз – в ''Anjuta''.&lt;br /&gt;
&lt;br /&gt;
Получив доступ к окну визуального редактора ''Glade'', мы можем&lt;br /&gt;
воспользоваться нашими навыками проектирования интерфейсов&lt;br /&gt;
''GTK+''. Откройте форму главного окна приложения (для этого, напомню, нужно дважды щелкнуть мышью по имени объекта-окна в главном&lt;br /&gt;
окне ''Glade''). Перейдите в редактор свойств ''Glade'' и назначьте свойству&lt;br /&gt;
'''«Заголовок»''' объекта '''window1''' строку '''«Текстовый редактор»'''. Прежде&lt;br /&gt;
чем добавлять в форму окна приложения GNOME какие-либо элементы&lt;br /&gt;
управления, в нем следует разместить объект-контейнер. Мы воспользуемся контейнером типа '''«вертикальный бокс»''' с двумя строками. В&lt;br /&gt;
верхнюю строку контейнера поместим визуальный элемент '''«Главное меню»''' (объект '''menubar1''' класса '''GtkMenuBar'''). В нижнюю строку помещаем визуальный элемент '''«Просмотр текста»''' (объект '''textview1''' класса '''GtkTextView'''). Теперь форма главного окна выглядит как настоящее&lt;br /&gt;
окно текстового редактора (Рис. 4). Обратите внимание на то, что главное меню уже заполнено стандартными командами, такими как открытие и сохранение файла, копирование и вставка из буфера обмена и т.п.&lt;br /&gt;
После добавления главного меню в форму окна приложения в файле&lt;br /&gt;
'''callbacks.c''' появятся заготовки для обработчиков всех сигналов, генерируемых стандартными командами меню. Имена обработчиков сигналов команд меню создаются по шаблону '''on_menuitem_activate()''', где&lt;br /&gt;
'''menuitem''' – имя объекта, представляющего команду меню.&lt;br /&gt;
&lt;br /&gt;
[[Изображение:LXF93_anjuta4.jpg|Рис. 4]]&lt;br /&gt;
&lt;br /&gt;
'''Рис. 4. Форма главного окна приложения.'''&lt;br /&gt;
&lt;br /&gt;
===Выход здесь===&lt;br /&gt;
&lt;br /&gt;
Заполнение заготовки программы кодом мы начинаем, как и всегда,&lt;br /&gt;
с кода завершения приложения. С помощью редактора свойств '''Glade'''&lt;br /&gt;
назначьте обработчик сигналу '''destroy''' объекта '''window1''' и добавьте в него вызов функции '''gtkmain_quit()''' (мы проделывали эту операцию уже много раз, так что останавливаться на ней подробно&lt;br /&gt;
не будем). Приступим теперь к написанию обработчиков стандартных команд меню. Найдите обработчик '''on_quit1_activate()''' в файле&lt;br /&gt;
'''callbacks.c'''. Он реагирует на сигнал, посылаемый командой меню&lt;br /&gt;
'''Файл | Выход'''. Мы можем просто добавить в этот обработчик вызов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
on_window1_destroy():&lt;br /&gt;
 void on_quit1_activate(GtkMenuItem *menuitem, gpointer user_data)&lt;br /&gt;
 {&lt;br /&gt;
   on_window1_destroy(NULL, NULL);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь вызов команды меню '''Файл | Выход''' приводит к завершению работы программы. Почему мы просто не добавили в обработчик '''on_quit1_activate()''' вызов функции '''gtkmain_quit()'''? Дело в том, что&lt;br /&gt;
приложение GNOME (как и любое оконное приложение) может быть&lt;br /&gt;
завершено несколькими разными командами. Удобно сделать так, что-бы при завершении работы приложения всегда вызвалась одна и та же&lt;br /&gt;
функция (мы возлагаем эту роль на функцию '''on_window1_destroy()'''). В&lt;br /&gt;
результате, если при завершении программы нам понадобится выполнять какие-то специальные действия (например, сохранять несохраненные данные), соответствующий код нужно будет добавить только&lt;br /&gt;
в функцию '''on_window1_destroy()''. Вместо непосредственного вызова&lt;br /&gt;
функции '''on_window1_destroy()''' мы могли бы вызвать функцию '''gtk_widget_destroy()''', передав ей в качестве аргумента указатель на объект&lt;br /&gt;
'''window1'''. В следующей статье этой серии мы подробнее обсудим методы корректного завершения работы программы-редактора (в процессе&lt;br /&gt;
вызова функции '''gtk_widget_destroy()''' генерируется сигнал '''destroy''' для&lt;br /&gt;
соответствующего визуального элемента).&lt;br /&gt;
&lt;br /&gt;
Теперь мы можем скомпилировать программу (сделайте это с помощью команды меню ''Anjuta'' '''Сборка–&amp;gt;Сборка'''). Перед тем, как выполнять&lt;br /&gt;
компиляцию, следует сохранить все изменения, сделанные в исходном&lt;br /&gt;
коде. Полные исходные тексты приложения-примера к этой статье вы&lt;br /&gt;
найдете на диске. В процессе подготовки дистрибутива из него были&lt;br /&gt;
удалены файлы сценариев сборки (не только make-файл, но и сценарий '''configure'''). При попытке выполнить команду сборки для этого дистрибутива вам будет сообщено об отсутствии make-файла. Для того,&lt;br /&gt;
чтобы собрать программу из пакета, в котором отсутствуют файлы&lt;br /&gt;
сценариев сборки, нужно сначала скомандовать '''Сборка–&amp;gt;Подготовить файлы для сборки...'''.&lt;br /&gt;
&lt;br /&gt;
Скажем несколько слов о редакторе исходных текстов ''Anjuta''. В&lt;br /&gt;
случае возникновения ошибки во время сборки редактор ''Anjuta'' выделяет подчеркиванием строку исходного текста, вызвавшую проблемы.&lt;br /&gt;
В редакторе также присутствует рудиментарная функция автоматического завершения кода. В процессе ввода идентификатора, являющегося параметром функции, появляется список всех идентификаторов&lt;br /&gt;
с подходящими именами, однако контекст при этом не учитывается,&lt;br /&gt;
так что в списке идентификаторов, начинающихся на букву '''m''', может&lt;br /&gt;
оказаться функция '''main()'''. Если в текст программы добавляется вызов&lt;br /&gt;
функции, определенной в файле проекта, редактор выводит подсказку со списком ее аргументов (к сожалению, она не работает для API-функций ''GTK+''/GNOME). Во всем остальном редактор исходных текстов&lt;br /&gt;
''Anjuta'' похож на ''KWrite''.&lt;br /&gt;
&lt;br /&gt;
===Объекты GtkTextView и GtkTextBuffer===&lt;br /&gt;
&lt;br /&gt;
Теперь, когда мы научили программу корректно завершать свою работу, давайте заполним остальные обработчики сигналов меню. Начнем&lt;br /&gt;
с обработчика сигнала, посылаемого командой '''Файл | Новый'' (функция '''on_new1_activate()'''). Прежде чем описывать команды, манипулирующие текстом, необходимо разобраться, как работает объект&lt;br /&gt;
'''GtkTextView''', который является основой нашего текстового редактора.&lt;br /&gt;
Объект '''GtkTextView''' и связанный с ним объект '''GtkTextBuffer''' представляют собой чрезвычайно мощные средства, позволяющие создавать&lt;br /&gt;
полноценные текстовые редакторы, поддерживающие разметку текста,&lt;br /&gt;
вставку изображений, гиперссылок, сложную навигацию по тексту и&lt;br /&gt;
т.п. В нашей программе мы воспользуемся лишь незначительной частью их возможностей. Заинтересованные читатели смогут узнать о них&lt;br /&gt;
больше из справочной системы ''GTK+''.&lt;br /&gt;
&lt;br /&gt;
Всю сложную механику работы с текстом выполняет класс&lt;br /&gt;
'''GtkTextBuffer'''. Объекты '''GtkTextBuffer''' содержат текст и вспомогательную&lt;br /&gt;
информацию, необходимую для его отображения. Функции, работающие с '''GtkTextBuffer''', позволяют выполнять различные операции с текстом. Объекты '''GtkTextView''' играют вспомогательную роль и служат, в&lt;br /&gt;
основном, для отображения содержимого '''GtkTextBuffer''' на экране. Когда&lt;br /&gt;
мы создаем экземпляр объекта '''GtkTextView''', по умолчанию создается и&lt;br /&gt;
экземпляр '''GtkTextBuffer'''. Однако текстовый буфер может существовать&lt;br /&gt;
и отдельно от конкретного объекта '''GtkTextView'''. Один текстовый буфер&lt;br /&gt;
может принадлежать нескольким объектам '''GtkTextView'''. В сложной&lt;br /&gt;
программе, предназначенной для манипулирования текстом, вы можете даже создать несколько текстовых буферов для одного визуального&lt;br /&gt;
элемента '''GtkTextView''' (несколько буферов можно использовать, например, для хранения промежуточных результатов редактирования текста)&lt;br /&gt;
и делать их видимыми по мере необходимости.&lt;br /&gt;
&lt;br /&gt;
Таким образом, для того, чтобы работать с текстом в нашем&lt;br /&gt;
редакторе, мы должны получить доступ к текстовому буферу&lt;br /&gt;
объекта '''GtkTextView'''. Вот как можно сделать это в обработчике&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
on_new1_activate():&lt;br /&gt;
 void on_new1_activate (GtkMenuItem * menuitem, gpointer user_data)&lt;br /&gt;
 {&lt;br /&gt;
    GtkTextView * textview1 = lookup_widget(menuitem, “textview1”);&lt;br /&gt;
    GtkTextBuffer * textbuffer = gtk_text_view_get_buffer(textview1);&lt;br /&gt;
    gtk_text_buffer_set_text(textbuffer, “”, 0);&lt;br /&gt;
    filename[0] = 0;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью знакомой нам функции '''lookup_widget()''' (напомню, что&lt;br /&gt;
ее, для нашего удобства, генерирует ''Glade'') мы получаем указатель на&lt;br /&gt;
объект '''GtkTextView''', заданный своим именем. Далее мы получаем указатель на объект '''GtkTextBuffer''' с помощью функции '''gtk_text_view_get_buffer()'''. Задача нашего обработчика – очистить текстовый буфер. Для&lt;br /&gt;
этого мы вызываем функцию '''gtk_text_buffer_set_text()'''. Эта функция,&lt;br /&gt;
вообще говоря, предназначена для записи в буфер текста. Ее первым&lt;br /&gt;
аргументом является указатель на объект '''GtkTextBuffer''', второй аргумент представляет собой строку текста в кодировке UTF-8 (единственная кодировка, которую «признает» объект '''GtkTextBuffer'''). Третьим&lt;br /&gt;
аргументом функции '''gtk_text_buffer_set_text()''' должна быть длина&lt;br /&gt;
строки (в байтах, а не в символах). Мы записываем в буфер строку&lt;br /&gt;
нулевой длины, что эквивалентно его очистке. Переменная '''filename'''&lt;br /&gt;
объявлена глобально в файле '''callbacks.c''' как&lt;br /&gt;
&lt;br /&gt;
 static char filename[256];&lt;br /&gt;
&lt;br /&gt;
и содержит текущее имя файла. В обработчике '''on_new1_activate()''' мы&lt;br /&gt;
сбрасываем имя файла (если таковое было установлено). Следует отметить, что перед очисткой текстового буфера наш простой редактор не&lt;br /&gt;
проверяет, содержит ли он несохраненные данные. Реализация такой&lt;br /&gt;
проверки оставляется читателю в качестве домашнего упражнения.&lt;br /&gt;
&lt;br /&gt;
В обработчике '''on_open1_activate()''', который вызывается в ответ&lt;br /&gt;
на сигнал, сгенерированный командой меню '''«Файл|Открыть»''', мы&lt;br /&gt;
используем диалоговое окно '''GtkFileChooserDialog''' для выбора файла&lt;br /&gt;
точно так же, как мы делали это в [[LXF90:GTK+|LXF90]]. Останавливаться подробно&lt;br /&gt;
на коде этого обработчика мы не будем. Фактическая загрузка данных&lt;br /&gt;
из выбранного файла выполняется с помощью определенной нами&lt;br /&gt;
функции '''open_file()''', которая, напротив, заслуживает более внимательного рассмотрения.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
 void open_file(GtkWidget * parentwindow, char * file_name)&lt;br /&gt;
 {&lt;br /&gt;
             int fd, len;&lt;br /&gt;
             char * buf[1024];&lt;br /&gt;
             GtkTextView * textview1 = lookup_widget(parentwindow,&lt;br /&gt;
“textview1”);&lt;br /&gt;
             GtkTextBuffer * textbuffer = gtk_text_view_get_&lt;br /&gt;
 buffer(textview1);&lt;br /&gt;
             if ((fd = open(file_name, O_RDONLY, 0)) &amp;lt; 0)&lt;br /&gt;
             {&lt;br /&gt;
                          GtkWidget * dialog;&lt;br /&gt;
                          dialog = gtk_message_dialog_new(parentwindow,&lt;br /&gt;
 GTK_DIALOG_DESTROY_WITH_PARENT,&lt;br /&gt;
 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,&lt;br /&gt;
“Невозможно открыть файл %s”, file_name);&lt;br /&gt;
                          gtk_dialog_run (GTK_DIALOG (dialog));&lt;br /&gt;
                          gtk_widget_destroy (dialog);&lt;br /&gt;
                          return;&lt;br /&gt;
             }&lt;br /&gt;
             strncpy(filename, file_name, 256);&lt;br /&gt;
             gtk_text_buffer_set_text(textbuffer, “”, 0);&lt;br /&gt;
             while((len = read(fd, buf, 1024)) != 0)&lt;br /&gt;
                          gtk_text_buffer_insert_at_cursor(textbuffer, buf,&lt;br /&gt;
 len);&lt;br /&gt;
             close(fd);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция '''open_file()''' принимает два параметра. В первом передается&lt;br /&gt;
указатель на объект, представляющий главное окно приложения. Он&lt;br /&gt;
нужен нам, во-первых, для того, чтобы найти объект '''textview1''', а во-&lt;br /&gt;
вторых – чтобы вывести предупреждающее диалоговое окно в случае&lt;br /&gt;
ошибки. Во втором параметре передается имя загружаемого файла.&lt;br /&gt;
&lt;br /&gt;
{{Врезка&lt;br /&gt;
|Заголовок=Еще раз о справке GTK+&lt;br /&gt;
|Содержание=Коль скоро речь зашла о справочной системе, нельзя не упомянуть о том,&lt;br /&gt;
что браузер справки ''Devhelp'' не очень удобен. Страницы справки ''GTK+''&lt;br /&gt;
обычно содержат довольно много текста, а в ''Devhelp'' (версии 0.1) отсутствует средство поиска текста на странице. Поскольку справка ''GTK+'' хранится в формате HTML, ее страницы можно читать непосредственно из&lt;br /&gt;
каталога '''/opt/gnome/share/gtk-doc/html''', однако при этом вы лишаетесь&lt;br /&gt;
удобной возможности глобального поиска. Получить новейшую версию&lt;br /&gt;
справки по '''GTK+''' можно на сайте http://developer.gnome.org/doc/API&lt;br /&gt;
|Ширина=200px&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
В функции '''open_file()''' мы получаем указатель на текстовый буфер&lt;br /&gt;
тем же способом, что и в функции '''on_new1_activate()'''. Далее мы пытаемся открыть файл, имя которого передано в параметре '''file_name''', для&lt;br /&gt;
чтения. Если открыть файл не удалось, выводится модальное диалоговое окно с информацией об ошибке.&lt;br /&gt;
&lt;br /&gt;
Для вывода информирующих и предупреждающих сообщений в&lt;br /&gt;
''GTK+'' используется диалоговое окно '''GtkMessageDialog'''. Мы создаем&lt;br /&gt;
экземпляр этого окна с помощью функции '''gtk_message_dialog_new()'''.&lt;br /&gt;
Флаг '''GTK_DIALOG_DESTROY_WITH_PARENT''' указывает, что в случае&lt;br /&gt;
уничтожения родительского визуального элемента диалоговое окно&lt;br /&gt;
должно быть уничтожено вместе с ним. Флаг '''GTK_MESSAGE_ERROR'''&lt;br /&gt;
указывает тип диалогового окна (окно с сообщением об ошибке).&lt;br /&gt;
Для создания диалоговых окон других типов можно использовать&lt;br /&gt;
флаги '''GTK_MESSAGE_INFO''' (нейтральное сообщение) '''GTK_MESSAGE_WARNING''' (предупреждение), '''GTK_MESSAGE_QUESTION''' (вопрос) и '''GTK_MESSAGE_OTHER''' (диалоговое окно неопределенного типа). Флаг '''GTK_BUTTONS_CLOSE''' указывает, что создаваемое диалоговое окно должно содержать одну кнопку, закрывающую окно. Если бы мы использовали флаг '''GTK_BUTTONS_NONE''', созданное нами диалоговое окно вообще&lt;br /&gt;
не содержало бы кнопок. Флаг '''GTK_BUTTONS_OK_CANCEL''' позволяет создать окно с кнопками '''OK''' и '''Cancel'''. В справочной системе ''GTK+''&lt;br /&gt;
можно найти константы и для других комбинаций кнопок диалогового окна. Следующим параметром функции '''gtk_message_dialog_new()'''&lt;br /&gt;
является строка форматирования текста, выводимого в диалоговом&lt;br /&gt;
окне. Она может содержать форматирующие символы, точно так же,&lt;br /&gt;
как и форматирующая строка функции '''printf()'''. Далее следуют аргументы, на которые ссылается форматирующая строка. Диалоговое окно&lt;br /&gt;
становится видимым сразу же после вызова функции '''gtk_message_dialog_new()'''. По умолчанию функция '''gtk_message_dialog_new()''' создает немодальное окно. Хотя модальное окно можно создать, установив&lt;br /&gt;
флаг '''GTK_DIALOG_MODAL''', здесь мы поступаем иначе. Для того чтобы окно стало модальным (то есть, блокировало работу программы),&lt;br /&gt;
мы вызываем функцию '''gtk_dialog_run()''', которая приостанавливает&lt;br /&gt;
выполнение программы до тех пор, пока не будет нажата одна из кнопок диалогового окна. Функция '''gtk_dialog_run()''' возвращает численное&lt;br /&gt;
значение, соответствующее нажатой кнопке (у нашего окна только одна&lt;br /&gt;
кнопка, так что значение, возвращенное '''gtk_dialog_run()''', нас не интересует). После того как окно закрыто, мы уничтожаем соответствующий&lt;br /&gt;
ему объект с помощью функции '''gtk_widget_destroy()'''. Если вы хотите&lt;br /&gt;
вывести на экран немодальное окно и при этом получить информацию&lt;br /&gt;
о том, какой кнопкой оно было закрыто, вы должны назначить обработчик сигнала response для объекта-окна.&lt;br /&gt;
&lt;br /&gt;
После того, как мы убедились, что файл открыт, мы опустошаем текстовый буфер и начинаем заполнять его данными из файла.&lt;br /&gt;
Функция '''gtk_text_buffer_insert_at_cursor()''' добавляет очередной блок&lt;br /&gt;
текста в позиции курсора (по умолчанию – в конец текста). Таким образом, мы можем добавлять текст в буфер небольшими порциями (этот&lt;br /&gt;
способ не самый изящный, но самый простой).&lt;br /&gt;
&lt;br /&gt;
Функция '''on_save_as1_activate()''' обрабатывает сигнал, который&lt;br /&gt;
создает команда меню '''Файл | Сохранить как'''. В этой функции мы также&lt;br /&gt;
используем диалоговое окно '''GtkFileChooserDialog''', только теперь оно&lt;br /&gt;
настроено на выбор имени файла для сохранения. Обратите внимание&lt;br /&gt;
на вызов функции '''gtk_file_chooser_set_do_overwrite_confirmation()'''.&lt;br /&gt;
Будучи вызвана с аргументом '''TRUE''', эта функция настраивает диалоговое окно выбора имени файла таким образом, что если файл с выбранным именем уже существует, программа спросит нас, действительно&lt;br /&gt;
ли мы хотим перезаписать его. Сохранение данных в файле на диске&lt;br /&gt;
выполняется с помощью функции '''save_file()'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=c&amp;gt;&lt;br /&gt;
 void save_file(GtkWidget * parentwindow, char * file_name)&lt;br /&gt;
 {&lt;br /&gt;
            int fd, len;&lt;br /&gt;
            GtkTextIter start, end;&lt;br /&gt;
            gchar * buf;&lt;br /&gt;
            GtkTextView * textview1 = lookup_widget(parentwindow,&lt;br /&gt;
“textview1”);&lt;br /&gt;
            GtkTextBuffer * textbuffer = gtk_text_view_get_&lt;br /&gt;
 buffer(textview1);&lt;br /&gt;
            if ((fd = open(file_name, O_WRONLY|O_CREAT|O_TRUNC,&lt;br /&gt;
 0666)) &amp;lt; 0)&lt;br /&gt;
            {&lt;br /&gt;
                         GtkWidget * dialog;&lt;br /&gt;
                         dialog = gtk_message_dialog_new(parentwindow,&lt;br /&gt;
 GTK_DIALOG_DESTROY_WITH_PARENT,&lt;br /&gt;
 GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,&lt;br /&gt;
“Невозможно открыть файл %s”, file_name);&lt;br /&gt;
                         gtk_dialog_run (GTK_DIALOG (dialog));&lt;br /&gt;
                         gtk_widget_destroy (dialog);&lt;br /&gt;
                         return;&lt;br /&gt;
            }&lt;br /&gt;
            gtk_text_buffer_get_start_iter(textbuffer, &amp;amp;start);&lt;br /&gt;
            gtk_text_buffer_get_end_iter(textbuffer, &amp;amp;end);&lt;br /&gt;
           buf = gtk_text_buffer_get_text(textbuffer, &amp;amp;start, &amp;amp;end,&lt;br /&gt;
 FALSE);&lt;br /&gt;
           write(fd, buf, strlen(buf));&lt;br /&gt;
           close(fd);&lt;br /&gt;
           g_free(buf);&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Список аргументов у этой функции такой же, как и у '''open_file()'''.&lt;br /&gt;
Открытие файла (теперь, естественно, для записи) и проверка результата этой операции, с выводом диалогового окна в случае ошибки,&lt;br /&gt;
выполняются практически так же, как и раньше. Самое интересное&lt;br /&gt;
начинается потом. Мы получаем доступ к текстовому буферу объекта&lt;br /&gt;
'''GtkTextView''' и должны извлечь из него текстовые данные для записи&lt;br /&gt;
в файл. Получение текста из текстового буфера – совсем не такое&lt;br /&gt;
простое дело, как может показаться на первый взгляд. Поскольку текстовый буфер '''GtkTextBuffer''' обладает чрезвычайно широкими возможностями в плане манипуляции текстом, он наделен довольно сложным&lt;br /&gt;
интерфейсом. Интерфейс '''GtkTextBuffer''' упрощает выполнение сложных&lt;br /&gt;
операций, но делает простые операции несколько более трудоемкими,&lt;br /&gt;
по сравнению с аналогичными операциями в менее функциональных&lt;br /&gt;
компонентах. Ключевую роль при обработке текста, содержащегося в&lt;br /&gt;
буфере '''GtkTextBuffer''', играет понятие итератора (их можно сравнить с&lt;br /&gt;
итераторами в библиотеке шаблонов ''C++''). Итератор текстового буфера ''GTK+'' представляет собой структуру типа '''GtkTextIter''', которая указывает на некоторую позицию в тексте. Итераторы могут перемещаться&lt;br /&gt;
по тексту в обоих направлениях в соответствии с заданным критерием.&lt;br /&gt;
Например, с помощью итератора можно перейти к последнему символу текущей строки, найти следующее вхождение определенного символа или подстроки и т.п. Итераторы играют важную роль в поиске и&lt;br /&gt;
навигации по тексту, но этим их функции не ограничиваются. Пара итераторов позволяет выделить фрагмент текста для дальнейших манипуляций с ним. Практически все функции текстового буфера, предназначенные для работы с фрагментами текста, используют итераторы.&lt;br /&gt;
&lt;br /&gt;
Для того чтобы скопировать текст из буфера, мы определяем два&lt;br /&gt;
итератора – '''start''' и '''end''', которые должны указывать, соответственно, на&lt;br /&gt;
начало и конец данных в буфере. Обратите внимание на то, что итераторы следует объявлять как переменные типа '''GtkTextIter''', а не как указатели на этот тип, хотя функциям, работающим с итераторами, передаются именно указатели на соответствующие переменные. Функция '''gtk_text_buffer_get_start_iter()''' устанавливает переданный ей итератор в начале текста, содержащегося в буфере, а функция '''gtk_text_buffer_get_end_iter()''' – соответственно, в конце текста. Получив два итератора, указывающих на некоторый фрагмент текста (в нашем случае – на&lt;br /&gt;
весь текст), мы можем скопировать его с помощью функции '''gtk_text_buffer_get_text()'''. Первым аргументом этой функции должен быть, как&lt;br /&gt;
всегда, указатель на объект '''GtkTextBuffer'''. Второй и третий аргументы&lt;br /&gt;
'''gtk_text_buffer_get_text()''' являются адресами переменных-итераторов,&lt;br /&gt;
выделяющих фрагмент, который должен быть скопирован. Последний&lt;br /&gt;
аргумент типа '''gboolean''' указывает, следует ли включать в копируемый&lt;br /&gt;
текст невидимые символы (в нашем простеньком редакторе таковые&lt;br /&gt;
отсутствуют). Функция '''gtk_text_buffer_get_text()''' возвращает строку с&lt;br /&gt;
нулевым конечным символом, в которой содержится скопированный&lt;br /&gt;
фрагмент текста. Для этой строки выделяется специальная область&lt;br /&gt;
памяти, и по окончании работы с фрагментом текста строку нужно удалить с помощью функции '''g_free()'''.&lt;br /&gt;
&lt;br /&gt;
Если вы внимательно изучите прилагаемые к статье исходные тексты, то увидите, что мы пропустили некоторые функции нашего текстового редактора (например, работу с буфером обмена). Ему, а также&lt;br /&gt;
другим интересным функциям ''GTK+'' и GNOME будет посвящена следующая статья. '''LXF'''&lt;/div&gt;</description>
			<pubDate>Mon, 24 Nov 2008 09:41:23 GMT</pubDate>			<dc:creator>Crazy Rebel</dc:creator>			<comments>http://wiki2.linuxformat.ru/index.php/%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5:LXF93:GTK%2B</comments>		</item>
	</channel>
</rss>