LXF91:Mono
(викификация, оформление) |
(→Mono: Создаем ''GTK''-приложение=: викификация, оформление) |
||
Строка 5: | Строка 5: | ||
{{Цикл/Mono}} | {{Цикл/Mono}} | ||
− | =Mono: Создаем ''GTK''-приложение | + | =Mono: Создаем ''GTK''-приложение= |
: При вашем знании ''Mono'' обычные текстовые программы писать уже скучно. '''Пол Хадсон''' поможет разобраться с новым проектом, использующим графический интерфейс. | : При вашем знании ''Mono'' обычные текстовые программы писать уже скучно. '''Пол Хадсон''' поможет разобраться с новым проектом, использующим графический интерфейс. | ||
+ | |||
+ | Мы дошли всего до пятого урока, а мне уже не терпится показать вам магию ''GTK#''... Вообще-то я бы и погодил с | ||
+ | показом, но столько читателей просили меня об этом – не | ||
+ | игнорировать же народные массы! Надеюсь, вам понравились эксперименты с ''Mono'' – ведь это очень весело. Но, по моему мнению, стоит влезть в библиотеку ''GTK'', как начнутся первые проблемы. Видите ли, | ||
+ | ''GTK'' писали люди, не любившие принципы объектно-ориентированного программирования, но попытавшиеся реализовать их на ''С''. Да еще он безнадежно усложнен и почти непознаваем для новичка. Но вам | ||
+ | повезло: я рядом! | ||
+ | |||
+ | На первых четырех уроках вы создали программы '''Hello World''', | ||
+ | утилиту для поиска файлов, RSS-агрегатор и простой интерфейс для | ||
+ | ''Beagle''. На этом уроке, чтобы целиком сконцентрироваться на ''GTK'', мы | ||
+ | возьмем готовый код из RSS-проекта и создадим графический RSS-агрегатор, который я назову ''Chomp''. ''GTK'' не столько сложен, сколько муторен – если вы что-то не вполне поняли, вернитесь назад на пару | ||
+ | абзацев: нить рассуждений потерять очень легко. | ||
+ | |||
+ | ==Удар от Stetic== | ||
+ | |||
+ | Как я уже сказал, ''GTK'' написан на ''С'', но к нему существует интерфейс ''Mono/C#'', вполне предсказуемо названный ''GTK#''. Это очень тонкая обертка вокруг кода ''С'', а значит, работать с ней довольно нудно. Но одну часть нудной никак не назовешь: это ''Stetic'' – инструмент для построения графических интерфейсов пользователя в стиле | ||
+ | '''Drag&Drop''', входящий в состав ''MonoDevelop''. Если вы помните первый | ||
+ | урок данной серии, мой дистрибутив – Fedora Core 6, и те, кто тоже | ||
+ | его установил, уже могут использовать ''MonoDevelop'' со ''Stetic''. Если | ||
+ | у вас другой дистрибутив, убедитесь, что ''MonoDevelop'' в нем версии | ||
+ | 0.12 или старше. | ||
+ | |||
+ | {{Врезка | ||
+ | |Заголовок=Stetic против Glade | ||
+ | |Содержание=''Stetic'' и ''Glade'' очень похожи: оба поддерживают '''drag&drop''' для создания пользовательских интерфейсов на ''GTK''. Но ''Stetic'' интегрирован в ''MonoDevelop'', то есть может генерировать код, связывая виджеты с | ||
+ | переменными. При желании можно использовать в ''Mono'' и ''Glade'', но рекомендуется все-таки ''Stetic''. | ||
+ | |Ширина=200px | ||
+ | }} | ||
+ | |||
+ | Первым делом нарисуем наш интерфейс с помощью ''Stetic''. Никакой | ||
+ | функциональности это не даст, зато даст представление о том, как | ||
+ | будет выглядеть готовое приложение, а я всегда считал, что это позволяет шагнуть далеко вперед. Другая причина, почему стоит сначала | ||
+ | спроектировать интерфейс – вы сразу же увидите, будет ли ваш проект | ||
+ | неуклюж или невразумителен, и, в случае чего, заранее примете меры | ||
+ | по редизайну интерфейса. Помните, что у лучших проектов интерфейс | ||
+ | пользователя разрабатывается очень тщательно – не зацикливайтесь | ||
+ | исключительно на написании кода в надежде, что GUI сложится само | ||
+ | собой! | ||
+ | |||
+ | Прежде чем приступать, полностью обновите версию Fedora, потому что ''Stetic'' – сравнительно молодой инструмент, и лучше использовать свежую версию ''MonoDevelop'' для минимизации числа возможных | ||
+ | отказов. Да почаще сохраняйте результаты, поскольку ''Stetic'' не страдает излишней стабильностью. | ||
+ | |||
+ | Итак, аккуратно выполните инструкции по работе в ''MonoDevelop'', | ||
+ | приведенные далее и продолжите чтение. | ||
+ | |||
+ | ==Часть 1 Создание интерфейса пользователя== | ||
+ | |||
+ | [[Изображение:LXF92_momo01.png|Шаг 1]] | ||
+ | |||
+ | '''1 Создайте новый проект''' | ||
+ | Выберите проект ''С#'' из области шаблонов, а | ||
+ | затем – '''Gtk# 2.0 Project''', справа. Назовите его | ||
+ | ''chomp'', снимите галочку с '''Create Separate Solution Subdirectory''' и нажмите '''New'''. | ||
+ | |||
+ | [[Изображение:LXF92_momo02.png|Шаг 2]] | ||
+ | |||
+ | '''2 Откройте MainWindow''' | ||
+ | Откройте дерево пользовательского интерфейса в | ||
+ | панели '''Solution''' и дважды щелкните на '''MainWindow'''. | ||
+ | Откроется '''MainWindow.cs''' в режиме '''Designer'''. | ||
+ | |||
+ | [[Изображение:LXF92_momo03.png|Шаг 3]] | ||
+ | |||
+ | '''3 Добавьте четыре области''' | ||
+ | В палитре '''Widgets''' пройдите до '''Containers''' и перетащите '''VBox''' на окно. Щелкните на нем правой кнопкой и выберите '''Vbox1 > Insert Before для четырех областей'''. | ||
+ | |||
+ | [[Изображение:LXF92_momo04.png|Шаг 4]] | ||
+ | |||
+ | '''4 Преобразуйте области''' | ||
+ | Перетащите главное меню, панель инструментов, | ||
+ | '''Hpaned '''и строку состояния во все четыре области, | ||
+ | начиная с верхней. Разделите '''Hpaned''' на две примерно равные части, как показано на рисунке. | ||
+ | |||
+ | [[Изображение:LXF92_momo05.png|Шаг 5]] | ||
+ | |||
+ | '''5 Новый Notebook''' | ||
+ | Перетащите '''VBox''' в левую часть '''Hpaned'''. Нажмите | ||
+ | на ней и выберите '''Delete'''. Перетащите '''Notebook''' и | ||
+ | '''Button''' на верхнюю и нижнюю стороны '''VBox'''. | ||
+ | |||
+ | [[Изображение:LXF92_momo06.png|Шаг 6]] | ||
+ | |||
+ | '''6 TreeView и Calendar''' | ||
+ | Перетащите '''Tree View''' на вкладку '''Page1''' компонента | ||
+ | '''Notebook'''. Щелкните на нем правой кнопкой, выберите '''Notebook1''', затем '''Insert Page After'''. На вкладке | ||
+ | '''Page2''' вставьте '''Calendar'''. | ||
+ | |||
+ | [[Изображение:LXF92_momo07.png|Шаг 7]] | ||
+ | |||
+ | '''7 Добавьте полосы прокрутки''' | ||
+ | В большом пространстве справа от элемента | ||
+ | '''Hpaned''' вставьте '''Scrolled Window''', затем поместите | ||
+ | в него '''Text View'''. Пользователи смогут прокручивать текст. | ||
+ | |||
+ | [[Изображение:LXF92_momo08.png|Шаг 8]] | ||
+ | |||
+ | '''8 Организуйте меню''' | ||
+ | Дважды щелкните на пустом меню, наберите '''/‘File’''', затем нажмите '''Enter'''. Таким образом, вы создадите | ||
+ | подменю – наберите в нем '''‘Quit’'''. Создайте меню | ||
+ | '''Help''' с подменю '''About'''. | ||
+ | |||
+ | [[Изображение:LXF92_momo09.png|Шаг 9]] | ||
+ | |||
+ | '''9 Кнопки панели инструментов''' | ||
+ | Дважды щелкните по панели инструментов, выберите '''Select Icon''', затем '''gtk-new'''. Добавьте две другие | ||
+ | кнопки: одну с '''gtk-refresh''', другую с '''gtk-delete'''. | ||
+ | |||
+ | ==Часть 2 Реализуем функционал программы== | ||
+ | |||
+ | Создание интерфейса позади, но для готового GUI еще кое-чего нехватает. Нужно сделать три вещи. Во-первых, назначить нормальные имена виджетам: пока что они называются '''button1''', '''textview2''' и т.д. Во-вторых, связать виджеты с полями: тогда мы сможем обращаться к ним из кода на ''C#''. И в-третьих, изменить свойства виджетов, чтобы они | ||
+ | выглядели как надо и делали то, что мы хотим. | ||
+ | |||
+ | {{Врезка | ||
+ | |Заголовок=Скорая помощь | ||
+ | |Содержание=Проверьте, что файл '''sitelist.txt''' содержит адреса URL лент, по одному на строке, и что он находится там же, | ||
+ | где и файл '''chomp.exe'''. Обычно это каталог '''bin/Debug''' или '''bin/Release''', если вы сделали релиз-версию. | ||
+ | |Ширина=200px | ||
+ | }} | ||
+ | |||
+ | Имя виджета – это просто одно из свойств, поэтому задачи 1 и 3 | ||
+ | выполняются через панель '''Widget Properties''', находящейся в правом | ||
+ | нижнем углу окна '''MonoDevelop'''. Вы увидите кнопку '''Bind To Field''' в верху | ||
+ | окна, которое только создали – я вам скажу, когда она понадобится. | ||
+ | |||
+ | Вот список требуемых изменений: | ||
+ | * Нажмите на кнопку '''New''' на панели инструментов '''toolbar''' (не на самой панели!) и измените ее имя на '''btnNew'''. | ||
+ | * Измените имя кнопки '''Refresh''' на '''btnRefresh'''. | ||
+ | * Измените имя кнопки '''Delete''' на '''btnDelete'''. | ||
+ | * Измените имя '''Tree View''' на '''tvFeeds'''. Нажмите '''Bind To Field'''. | ||
+ | * Снимите галочку с '''Show Day Names''' для '''Calendar''' (это его немного уменьшит). Нажмите '''Bind To Field'''. | ||
+ | * Измените имя '''Text View''' на '''txtFeed'''. Нажмите '''Bind To Field'''. Измените '''Hight Request''' на 300, а '''Width Request''' на 400 (теперь '''Text View''' не будет занимать весь экран). | ||
+ | * Измените имя кнопки под компонентом '''notebook''' на '''btnRefreshAll'''. | ||
+ | * Измените текст для страниц компонента '''notebook''' на '''By Feed''' для вкладки с '''Tree View''' и на '''By Date''' для вкладки с '''Calendar'''. | ||
+ | |||
+ | ==Добавим реализацию== | ||
+ | |||
+ | Вот и все – с интерфейсом пользователя покончено, можно сфокусироваться на реализации методов. Наберем кое-какой код прямо в | ||
+ | файле '''MainWindow.cs''', а также установим обработчики сигналов для | ||
+ | '''MainWindow.cs''' в ''Stetic''. Сигналы – это внутренние ''GTK''-сообщения, | ||
+ | которые посылаются, когда что-нибудь происходит: например, пользователь нажимает кнопку или клавишу. По умолчанию, большая часть | ||
+ | сигналов ничего не делает, но мы можем на них подписаться, назначив каждому обработчик с помощью ''Stetic'' – он даже создаст за нас базовый метод! | ||
+ | |||
+ | {{Врезка | ||
+ | |Заголовок=Скорая помощь | ||
+ | |Содержание=''GTK'' предусматривает масштабирование компонентов интерфейса при изменении размера окна, а также их сжатие и растяжение при переводе надписей на другие языки, смене шрифта и других параметров среды выполнения. Вот почему мы используем '''VBox''' и '''HBox'', а не размещаем компоненты вручную. | ||
+ | |Ширина=200px | ||
+ | }} | ||
+ | |||
+ | Прежде всего обработаем событие, возникающее, когда пользователь выделяет что-то в '''Tree View''' нашей программы. Этот компонент будет использоваться для отображения списка RSS-лент, на которые | ||
+ | подписан пользователь, поэтому при выборе пользователем ленты из | ||
+ | списка ''Chomp'' надо скачать последнюю версию RSS-файла и отобразить его в '''Text View''' справа. Щелчки пользователя можно обработать, отлавливая сигнал '''RowActivated''' – щелкните на '''Tree View''', затем на | ||
+ | панели '''Widget Properties''' перейдите на вкладку '''Signals'''. Найдите сигнал | ||
+ | '''RowActivated''' и дважды щелкните там, где написано '''Click Here To Add A New Handler'''. Назовите его '''OnRowActivated''' и нажмите '''Enter'''. Щелкнув | ||
+ | на кнопке '''Source Code''', расположенной ниже окна дизайна формы, вы | ||
+ | увидите, что ''Stetic'' создал следующий метод: | ||
+ | |||
+ | <source lang=csharp> | ||
+ | protected virtual void OnRowActivated(object o, Gtk. | ||
+ | RowActivatedArgs args) | ||
+ | { | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Вроде неплохо, но тут вы и подошли к первому недостатку ''GTK''. | ||
+ | А именно: получить данные из '''Tree View''' гораздо сложнее, чем вы | ||
+ | думаете! | ||
+ | |||
+ | ''Chomp ''требуется работать с лентами двумя способами. Если мы | ||
+ | находимся на вкладке '''By Feed''', то двойной щелчок на одной из лент | ||
+ | в '''Tree View''' должен загрузить эту самую ленту. Если мы находимся | ||
+ | на вкладке '''By Date''', при двойном щелчке на дате в календаре следует | ||
+ | загрузить все ленты, но показать новости только за указанную дату. | ||
+ | Чтобы как-то унифицировать наш код, создадим метод '''ReadFeed()''', | ||
+ | который загружает URL, а затем фильтрует их по дате. При загрузке всех записей данной ленты мы передадим специальный аргумент | ||
+ | '''DateTime.MinValue''', обозначающий «игнорировать дату». | ||
+ | |||
+ | Вот код, который надо поместить в '''OnRowActivated''': | ||
+ | |||
+ | <source lang=csharp> | ||
+ | TreeSelection select = tvFeeds.Selection; | ||
+ | TreeIter iter; | ||
+ | TreeModel model; | ||
+ | select.GetSelected(out model, out iter); | ||
+ | string val = (string)model.GetValue(iter, 0); | ||
+ | txtFeed.Buffer.Clear(); | ||
+ | ReadFeed(val, DateTime.MinValue); | ||
+ | </source> | ||
+ | |||
+ | Первые пять строк иллюстрируют мои слова о занудстве ''GTK'': таким | ||
+ | манером мы извлекаем значения из компонента '''Tree View'''. Весьма запутанно, но зато годится для любого возможного способа использования '''Tree View'''. | ||
+ | |||
+ | Когда выбранное значение попадет в переменную '''val''', мы очищаем | ||
+ | буфер '''Text View''' и вызываем '''ReadFeed()''', чтобы загрузить и отобразить | ||
+ | RSS. Но давайте сначала разберемся с календарем. Для этого найдите | ||
+ | сигнал '''DaySelectedDoubleClick''' и назначьте ему обработчик '''DayClicked'''. | ||
+ | В режиме '''Source Code''' среды ''MonoDevelop'' должен появиться пустой | ||
+ | метод '''DayClicked()''', который выглядит так: | ||
+ | |||
+ | <source lang=csharp> | ||
+ | protected virtual void DayClicked(object sender, System. | ||
+ | EventArgs e) | ||
+ | { | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Этот метод отлавливает двойные щелчки на календаре, а получить | ||
+ | выбранную дату из компонента '''Calendar''' очень просто. | ||
+ | |||
+ | Но не спешите хвалить ''GTK'': вот я вам сейчас покажу, как перебрать | ||
+ | все элементы в '''Tree View'''. В '''DayClicked()''' надо поместить следующий | ||
+ | код: | ||
+ | |||
+ | <source lang=csharp> | ||
+ | txtFeed.Buffer.Clear(); | ||
+ | tvFeeds.Model.Foreach(FeedByDate); | ||
+ | </source> | ||
+ | |||
+ | Здесь мы очищаем текстовый буфер для входящих лент, а затем | ||
+ | вызываем метод '''Foreach()''' модели данных '''Tree View'''. Метод '''FeedByDate()''' | ||
+ | (его я еще не показывал – не гоните коней!) вызывается для каждого | ||
+ | элемента в '''Tree View'''. А так как метод '''FeedByDate()''' вызывается методом | ||
+ | '''Foreach()''', он должен соответствовать конкретной функции-прототипу, | ||
+ | то есть принимать определенный список параметров. Иначе он работать не будет. | ||
+ | |||
+ | Мы хотим, чтобы функция '''FeedByDate()''' читала каждую ленту, которую ей передают, затем посылала ее в '''ReadFeed()''' вместе с датой, определенной на компоненте '''Calendar'''. Это довольно просто: | ||
+ | |||
+ | <source lang=csharp> | ||
+ | bool FeedByDate(TreeModel model, TreePath path, TreeIter iter) | ||
+ | { | ||
+ | string url = (string)model.GetValue(iter, 0); | ||
+ | ReadFeed(url, new DateTime(calendar.Year, calendar.Month + 1, | ||
+ | calendar.Day)); | ||
+ | return false; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Первая строка выцарапывает URL ленты из '''Tree View''', после чего | ||
+ | он передается методу '''ReadFeed()''' вместе с годом, месяцем и днем, | ||
+ | выбранными в календаре. Но вы заметили '''calendar.Month + 1'''? ''GTK'' | ||
+ | ведет отсчет месяцев с нуля. Зато дни и года он считает с 1. Я тоже не | ||
+ | знаю, почему! | ||
+ | |||
+ | Пару выпусков назад мы рассматривали код, необходимый для | ||
+ | чтения RSS-лент. На сей раз мы его используем, но с небольшими | ||
+ | изменениями: | ||
+ | |||
+ | * Вывод будет происходить в текстовый буфер, а не в консоль. | ||
+ | * GUID’ы кэшироваться не будут – мы хотим, чтобы ''Chomp'' загружала все записи каждой ленты, а не записи, которые мы не видели. | ||
+ | * Если для времени указано '''DateTime.MinValue''', имеется в виду «по дате фильтровать не надо». | ||
+ | * Иначе, получить дату публикации каждой новости и преобразовать ее в объект '''DateTime'''. | ||
+ | * Затем сравнить каждый объект '''DateTime''' с указанной датой и вывести только те записи, которые ей соответствуют. | ||
+ | |||
+ | Тут есть мелкий просчет: одни ленты, включая '''Linux Format''', предоставляют дату публикации в формате '''Wed, 24 Jan 2007 11:02:43 +0000''', а другие вместо '''‘+0000’''' ставят '''‘GMT’'''. '''.NET''' понимает оба формата, но в ''Mono'' – возможно, по недосмотру – поддерживается только последний. В качестве обходного пути мы будем обрезать всю подстроку, начиная с символа '''+'''. | ||
+ | |||
+ | ==Время писать код== | ||
+ | |||
+ | {{Врезка | ||
+ | |Заголовок=Скорая помощь | ||
+ | |Содержание=Когда вы будете читать этот материал, уже, возможно, выйдет ''MonoDevelop'' версии 1.0, хотя бы в виде | ||
+ | бета-версии. ''Stetic'' – одна из активно разрабатываемых и быстро меняющихся областей, поэтому в новом релизе будут | ||
+ | исправлены многие ошибки и даже добавлены новые... возможности. Стоит проверить! | ||
+ | |Ширина=200px | ||
+ | }} | ||
+ | |||
+ | Вот и код. Если вы читали [[LXF89:Mono|LXF89]], то должны узнать его части! | ||
+ | |||
+ | <source lang=csharp> | ||
+ | protected virtual void ReadFeed(string feed, DateTime filter) { | ||
+ | XmlDocument doc = new XmlDocument(); | ||
+ | doc.Load(feed); | ||
+ | TextBuffer text = txtFeed.Buffer; | ||
+ | XmlNodeList items = doc.SelectNodes(“//item”); | ||
+ | foreach (XmlNode item in items) { | ||
+ | if (filter == DateTime.MinValue) { | ||
+ | text.Text += (item.SelectSingleNode(“title”).InnerText) + “\n”; | ||
+ | text.Text += (“ “ + item.SelectSingleNode(“description”). | ||
+ | InnerText) + “\n\n”; | ||
+ | } else { | ||
+ | string time = item.SelectSingleNode(“pubDate”).InnerText; | ||
+ | if (time.Contains(“+”)) time = time.Substring(0, time. | ||
+ | IndexOf(“+”)); | ||
+ | DateTime thisdate = DateTime.Parse(time); | ||
+ | if (filter.Day == thisdate.Day && filter.Month == thisdate.Month | ||
+ | && filter.Year == thisdate.Year) { | ||
+ | text.Text += (item.SelectSingleNode(“title”).InnerText) + “\n”; | ||
+ | text.Text += (“ “ + item.SelectSingleNode(“description”). | ||
+ | InnerText) + “\n\n”; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Две строки могут вызвать затруднение: | ||
+ | |||
+ | <source lang=csharp> | ||
+ | if (time.Contains(“+”)) time = time.Substring(0, time.IndexOf(“+”)); | ||
+ | DateTime thisdate = DateTime.Parse(time); | ||
+ | </source> | ||
+ | |||
+ | Первая означает «если строка содержит '''+''', просьба записать в переменную time все от начала строки (от символа с номером ноль) до знака '''+'''»: таким образом отсекается часть '''+0000'''. Вторая строка означает | ||
+ | «возьми строку '''time'' и преобразуй ее в тип '''DateTime'''.» Хранить дату как | ||
+ | '''DateTime''' удобнее, потому что можно работать с днем, месяцем и годом | ||
+ | как с числами, а не разбирать строку вручную. | ||
+ | |||
+ | ==Финишная прямая== | ||
+ | |||
+ | Первая версия ''Chomp'' почти завершена, но в ней кое-чего не хватает. | ||
+ | Двойной щелчок по лентам загружает все ленты. Двойной щелчок по | ||
+ | дате загружает все ленты и фильтрует записи по выбранной дате. Но в | ||
+ | какой момент мы загружаем ленты в программу? Ответ: а ни в какой! | ||
+ | |||
+ | Наш предыдущий XML-считыватель тоже загружал список лент, | ||
+ | поэтому можно просто взять и модифицировать его для нашего интерфейса на ''GTK''. А именно, давайте поместим каждый URL в '''Tree View''', | ||
+ | чтобы пользователи могли нажимать на них. Здесь опять проявится | ||
+ | занудство ''GTK'', поэтому возьмите себя в руки: | ||
+ | |||
+ | <source lang=csharp> | ||
+ | string[] sitelist; | ||
+ | if (File.Exists(“sitelist.txt”)) { | ||
+ | sitelist = File.ReadAllLines(“sitelist.txt”); | ||
+ | } else { | ||
+ | sitelist = new string[0]; | ||
+ | } | ||
+ | // это значит, что мы хотим сохранить строку в строке Tree View, но в | ||
+ | действительности нам нужен только URL! | ||
+ | TreeStore store = new TreeStore (typeof(string), typeof(string)); | ||
+ | foreach(string site in sitelist) { | ||
+ | // “Foo” это место размещения | ||
+ | store.AppendValues(site, “Foo”); | ||
+ | } | ||
+ | tvFeeds.Model = store; | ||
+ | tvFeeds.AppendColumn(“URLs”, new CellRendererText(), “text”,0); | ||
+ | </source> | ||
+ | |||
+ | Чтобы показать данные, Tree View нужен по крайней мере один | ||
+ | столбец. Смело отключайте заголовки в свойствах компонента ''Stetic'', в | ||
+ | них нет нужды. Теперь создайте файл '''sitelist.txt''' в вашем рабочем каталоге программы (наподобие '''/путь/до/проекта/bin/Debug'''), заполните его URL-адресами лент, и пусть поработает! | ||
+ | |||
+ | Весь код этого учебника, даже с некоторыми дополнительными | ||
+ | возможностями (см. врезку Chomp 0.2), включен на диск. Но чтобы проект созрел для помещения на '''SourceForge''', не мешает его усовершенствовать. Оставляю ''Chomp'' в ваших умелых руках... '''LXF''' | ||
+ | |||
+ | ==Chomp 0.2== | ||
+ | |||
+ | Версия Chomp на диске базируется на том, что | ||
+ | мы сделали, и позволяет пользователям временно добавлять новые ленты, но вы можете | ||
+ | сделать еще кое-что: | ||
+ | * Заставить работать функцию удаления ленты. | ||
+ | * Кэшировать ленты и GUID, чтобы при отображении они загружались из памяти, а не скачивались каждый раз из Сети. | ||
+ | * Реализовать поиск в кэшированных лентах. | ||
+ | * Добавить '''Refresh''' и '''RefreshAll'''. | ||
+ | * Поместить что-нибудь в строку состояния! | ||
+ | * Заполнить меню осмысленными действиями. | ||
+ | * Добавлять пользовательские ленты в файл '''sitelist.txt'''. | ||
+ | |||
+ | Целью этого урока было научить вас использовать ''Stetic'', и я думаю, мы справились неплохо. Дальнейшая работа будет в основном писа ниной кода: обвешаем интерфейс всякими крутыми штуками. Почаще сохраняйте результат, и все будет в порядке – резвитесь! |
Текущая версия на 10:43, 28 ноября 2008
|
|
|
- Mono-Maния Программирование на современной платформе для начинающих
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Содержание |
[править] Mono: Создаем GTK-приложение
- При вашем знании Mono обычные текстовые программы писать уже скучно. Пол Хадсон поможет разобраться с новым проектом, использующим графический интерфейс.
Мы дошли всего до пятого урока, а мне уже не терпится показать вам магию GTK#... Вообще-то я бы и погодил с показом, но столько читателей просили меня об этом – не игнорировать же народные массы! Надеюсь, вам понравились эксперименты с Mono – ведь это очень весело. Но, по моему мнению, стоит влезть в библиотеку GTK, как начнутся первые проблемы. Видите ли, GTK писали люди, не любившие принципы объектно-ориентированного программирования, но попытавшиеся реализовать их на С. Да еще он безнадежно усложнен и почти непознаваем для новичка. Но вам повезло: я рядом!
На первых четырех уроках вы создали программы Hello World, утилиту для поиска файлов, RSS-агрегатор и простой интерфейс для Beagle. На этом уроке, чтобы целиком сконцентрироваться на GTK, мы возьмем готовый код из RSS-проекта и создадим графический RSS-агрегатор, который я назову Chomp. GTK не столько сложен, сколько муторен – если вы что-то не вполне поняли, вернитесь назад на пару абзацев: нить рассуждений потерять очень легко.
[править] Удар от Stetic
Как я уже сказал, GTK написан на С, но к нему существует интерфейс Mono/C#, вполне предсказуемо названный GTK#. Это очень тонкая обертка вокруг кода С, а значит, работать с ней довольно нудно. Но одну часть нудной никак не назовешь: это Stetic – инструмент для построения графических интерфейсов пользователя в стиле Drag&Drop, входящий в состав MonoDevelop. Если вы помните первый урок данной серии, мой дистрибутив – Fedora Core 6, и те, кто тоже его установил, уже могут использовать MonoDevelop со Stetic. Если у вас другой дистрибутив, убедитесь, что MonoDevelop в нем версии 0.12 или старше.
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Первым делом нарисуем наш интерфейс с помощью Stetic. Никакой функциональности это не даст, зато даст представление о том, как будет выглядеть готовое приложение, а я всегда считал, что это позволяет шагнуть далеко вперед. Другая причина, почему стоит сначала спроектировать интерфейс – вы сразу же увидите, будет ли ваш проект неуклюж или невразумителен, и, в случае чего, заранее примете меры по редизайну интерфейса. Помните, что у лучших проектов интерфейс пользователя разрабатывается очень тщательно – не зацикливайтесь исключительно на написании кода в надежде, что GUI сложится само собой!
Прежде чем приступать, полностью обновите версию Fedora, потому что Stetic – сравнительно молодой инструмент, и лучше использовать свежую версию MonoDevelop для минимизации числа возможных отказов. Да почаще сохраняйте результаты, поскольку Stetic не страдает излишней стабильностью.
Итак, аккуратно выполните инструкции по работе в MonoDevelop, приведенные далее и продолжите чтение.
[править] Часть 1 Создание интерфейса пользователя
1 Создайте новый проект Выберите проект С# из области шаблонов, а затем – Gtk# 2.0 Project, справа. Назовите его chomp, снимите галочку с Create Separate Solution Subdirectory и нажмите New.
2 Откройте MainWindow Откройте дерево пользовательского интерфейса в панели Solution и дважды щелкните на MainWindow. Откроется MainWindow.cs в режиме Designer.
3 Добавьте четыре области В палитре Widgets пройдите до Containers и перетащите VBox на окно. Щелкните на нем правой кнопкой и выберите Vbox1 > Insert Before для четырех областей.
4 Преобразуйте области Перетащите главное меню, панель инструментов, Hpaned и строку состояния во все четыре области, начиная с верхней. Разделите Hpaned на две примерно равные части, как показано на рисунке.
5 Новый Notebook Перетащите VBox в левую часть Hpaned. Нажмите на ней и выберите Delete. Перетащите Notebook и Button на верхнюю и нижнюю стороны VBox.
6 TreeView и Calendar Перетащите Tree View на вкладку Page1 компонента Notebook. Щелкните на нем правой кнопкой, выберите Notebook1, затем Insert Page After. На вкладке Page2 вставьте Calendar.
7 Добавьте полосы прокрутки В большом пространстве справа от элемента Hpaned вставьте Scrolled Window, затем поместите в него Text View. Пользователи смогут прокручивать текст.
8 Организуйте меню Дважды щелкните на пустом меню, наберите /‘File’, затем нажмите Enter. Таким образом, вы создадите подменю – наберите в нем ‘Quit’. Создайте меню Help с подменю About.
9 Кнопки панели инструментов Дважды щелкните по панели инструментов, выберите Select Icon, затем gtk-new. Добавьте две другие кнопки: одну с gtk-refresh, другую с gtk-delete.
[править] Часть 2 Реализуем функционал программы
Создание интерфейса позади, но для готового GUI еще кое-чего нехватает. Нужно сделать три вещи. Во-первых, назначить нормальные имена виджетам: пока что они называются button1, textview2 и т.д. Во-вторых, связать виджеты с полями: тогда мы сможем обращаться к ним из кода на C#. И в-третьих, изменить свойства виджетов, чтобы они выглядели как надо и делали то, что мы хотим.
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Имя виджета – это просто одно из свойств, поэтому задачи 1 и 3 выполняются через панель Widget Properties, находящейся в правом нижнем углу окна MonoDevelop. Вы увидите кнопку Bind To Field в верху окна, которое только создали – я вам скажу, когда она понадобится.
Вот список требуемых изменений:
- Нажмите на кнопку New на панели инструментов toolbar (не на самой панели!) и измените ее имя на btnNew.
- Измените имя кнопки Refresh на btnRefresh.
- Измените имя кнопки Delete на btnDelete.
- Измените имя Tree View на tvFeeds. Нажмите Bind To Field.
- Снимите галочку с Show Day Names для Calendar (это его немного уменьшит). Нажмите Bind To Field.
- Измените имя Text View на txtFeed. Нажмите Bind To Field. Измените Hight Request на 300, а Width Request на 400 (теперь Text View не будет занимать весь экран).
- Измените имя кнопки под компонентом notebook на btnRefreshAll.
- Измените текст для страниц компонента notebook на By Feed для вкладки с Tree View и на By Date для вкладки с Calendar.
[править] Добавим реализацию
Вот и все – с интерфейсом пользователя покончено, можно сфокусироваться на реализации методов. Наберем кое-какой код прямо в файле MainWindow.cs, а также установим обработчики сигналов для MainWindow.cs в Stetic. Сигналы – это внутренние GTK-сообщения, которые посылаются, когда что-нибудь происходит: например, пользователь нажимает кнопку или клавишу. По умолчанию, большая часть сигналов ничего не делает, но мы можем на них подписаться, назначив каждому обработчик с помощью Stetic – он даже создаст за нас базовый метод!
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Прежде всего обработаем событие, возникающее, когда пользователь выделяет что-то в Tree View нашей программы. Этот компонент будет использоваться для отображения списка RSS-лент, на которые подписан пользователь, поэтому при выборе пользователем ленты из списка Chomp надо скачать последнюю версию RSS-файла и отобразить его в Text View справа. Щелчки пользователя можно обработать, отлавливая сигнал RowActivated – щелкните на Tree View, затем на панели Widget Properties перейдите на вкладку Signals. Найдите сигнал RowActivated и дважды щелкните там, где написано Click Here To Add A New Handler. Назовите его OnRowActivated и нажмите Enter. Щелкнув на кнопке Source Code, расположенной ниже окна дизайна формы, вы увидите, что Stetic создал следующий метод:
protected virtual void OnRowActivated(object o, Gtk. RowActivatedArgs args) { }
Вроде неплохо, но тут вы и подошли к первому недостатку GTK. А именно: получить данные из Tree View гораздо сложнее, чем вы думаете!
Chomp требуется работать с лентами двумя способами. Если мы находимся на вкладке By Feed, то двойной щелчок на одной из лент в Tree View должен загрузить эту самую ленту. Если мы находимся на вкладке By Date, при двойном щелчке на дате в календаре следует загрузить все ленты, но показать новости только за указанную дату. Чтобы как-то унифицировать наш код, создадим метод ReadFeed(), который загружает URL, а затем фильтрует их по дате. При загрузке всех записей данной ленты мы передадим специальный аргумент DateTime.MinValue, обозначающий «игнорировать дату».
Вот код, который надо поместить в OnRowActivated:
TreeSelection select = tvFeeds.Selection; TreeIter iter; TreeModel model; select.GetSelected(out model, out iter); string val = (string)model.GetValue(iter, 0); txtFeed.Buffer.Clear(); ReadFeed(val, DateTime.MinValue);
Первые пять строк иллюстрируют мои слова о занудстве GTK: таким манером мы извлекаем значения из компонента Tree View. Весьма запутанно, но зато годится для любого возможного способа использования Tree View.
Когда выбранное значение попадет в переменную val, мы очищаем буфер Text View и вызываем ReadFeed(), чтобы загрузить и отобразить RSS. Но давайте сначала разберемся с календарем. Для этого найдите сигнал DaySelectedDoubleClick и назначьте ему обработчик DayClicked. В режиме Source Code среды MonoDevelop должен появиться пустой метод DayClicked(), который выглядит так:
protected virtual void DayClicked(object sender, System. EventArgs e) { }
Этот метод отлавливает двойные щелчки на календаре, а получить выбранную дату из компонента Calendar очень просто.
Но не спешите хвалить GTK: вот я вам сейчас покажу, как перебрать все элементы в Tree View. В DayClicked() надо поместить следующий код:
txtFeed.Buffer.Clear(); tvFeeds.Model.Foreach(FeedByDate);
Здесь мы очищаем текстовый буфер для входящих лент, а затем вызываем метод Foreach() модели данных Tree View. Метод FeedByDate() (его я еще не показывал – не гоните коней!) вызывается для каждого элемента в Tree View. А так как метод FeedByDate() вызывается методом Foreach(), он должен соответствовать конкретной функции-прототипу, то есть принимать определенный список параметров. Иначе он работать не будет.
Мы хотим, чтобы функция FeedByDate() читала каждую ленту, которую ей передают, затем посылала ее в ReadFeed() вместе с датой, определенной на компоненте Calendar. Это довольно просто:
bool FeedByDate(TreeModel model, TreePath path, TreeIter iter) { string url = (string)model.GetValue(iter, 0); ReadFeed(url, new DateTime(calendar.Year, calendar.Month + 1, calendar.Day)); return false; }
Первая строка выцарапывает URL ленты из Tree View, после чего он передается методу ReadFeed() вместе с годом, месяцем и днем, выбранными в календаре. Но вы заметили calendar.Month + 1? GTK ведет отсчет месяцев с нуля. Зато дни и года он считает с 1. Я тоже не знаю, почему!
Пару выпусков назад мы рассматривали код, необходимый для чтения RSS-лент. На сей раз мы его используем, но с небольшими изменениями:
- Вывод будет происходить в текстовый буфер, а не в консоль.
- GUID’ы кэшироваться не будут – мы хотим, чтобы Chomp загружала все записи каждой ленты, а не записи, которые мы не видели.
- Если для времени указано DateTime.MinValue, имеется в виду «по дате фильтровать не надо».
- Иначе, получить дату публикации каждой новости и преобразовать ее в объект DateTime.
- Затем сравнить каждый объект DateTime с указанной датой и вывести только те записи, которые ей соответствуют.
Тут есть мелкий просчет: одни ленты, включая Linux Format, предоставляют дату публикации в формате Wed, 24 Jan 2007 11:02:43 +0000, а другие вместо ‘+0000’ ставят ‘GMT’. .NET понимает оба формата, но в Mono – возможно, по недосмотру – поддерживается только последний. В качестве обходного пути мы будем обрезать всю подстроку, начиная с символа +.
[править] Время писать код
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Вот и код. Если вы читали LXF89, то должны узнать его части!
protected virtual void ReadFeed(string feed, DateTime filter) { XmlDocument doc = new XmlDocument(); doc.Load(feed); TextBuffer text = txtFeed.Buffer; XmlNodeList items = doc.SelectNodes(“//item”); foreach (XmlNode item in items) { if (filter == DateTime.MinValue) { text.Text += (item.SelectSingleNode(“title”).InnerText) + “\n”; text.Text += (“ “ + item.SelectSingleNode(“description”). InnerText) + “\n\n”; } else { string time = item.SelectSingleNode(“pubDate”).InnerText; if (time.Contains(“+”)) time = time.Substring(0, time. IndexOf(“+”)); DateTime thisdate = DateTime.Parse(time); if (filter.Day == thisdate.Day && filter.Month == thisdate.Month && filter.Year == thisdate.Year) { text.Text += (item.SelectSingleNode(“title”).InnerText) + “\n”; text.Text += (“ “ + item.SelectSingleNode(“description”). InnerText) + “\n\n”; } } } }
Две строки могут вызвать затруднение:
if (time.Contains(“+”)) time = time.Substring(0, time.IndexOf(“+”)); DateTime thisdate = DateTime.Parse(time);
Первая означает «если строка содержит +, просьба записать в переменную time все от начала строки (от символа с номером ноль) до знака +»: таким образом отсекается часть +0000. Вторая строка означает «возьми строку time и преобразуй ее в тип DateTime'.» Хранить дату как DateTime удобнее, потому что можно работать с днем, месяцем и годом как с числами, а не разбирать строку вручную.
[править] Финишная прямая
Первая версия Chomp почти завершена, но в ней кое-чего не хватает. Двойной щелчок по лентам загружает все ленты. Двойной щелчок по дате загружает все ленты и фильтрует записи по выбранной дате. Но в какой момент мы загружаем ленты в программу? Ответ: а ни в какой!
Наш предыдущий XML-считыватель тоже загружал список лент, поэтому можно просто взять и модифицировать его для нашего интерфейса на GTK. А именно, давайте поместим каждый URL в Tree View, чтобы пользователи могли нажимать на них. Здесь опять проявится занудство GTK, поэтому возьмите себя в руки:
string[] sitelist; if (File.Exists(“sitelist.txt”)) { sitelist = File.ReadAllLines(“sitelist.txt”); } else { sitelist = new string[0]; } // это значит, что мы хотим сохранить строку в строке Tree View, но в действительности нам нужен только URL! TreeStore store = new TreeStore (typeof(string), typeof(string)); foreach(string site in sitelist) { // “Foo” это место размещения store.AppendValues(site, “Foo”); } tvFeeds.Model = store; tvFeeds.AppendColumn(“URLs”, new CellRendererText(), “text”,0);
Чтобы показать данные, Tree View нужен по крайней мере один столбец. Смело отключайте заголовки в свойствах компонента Stetic, в них нет нужды. Теперь создайте файл sitelist.txt в вашем рабочем каталоге программы (наподобие /путь/до/проекта/bin/Debug), заполните его URL-адресами лент, и пусть поработает!
Весь код этого учебника, даже с некоторыми дополнительными возможностями (см. врезку Chomp 0.2), включен на диск. Но чтобы проект созрел для помещения на SourceForge, не мешает его усовершенствовать. Оставляю Chomp в ваших умелых руках... LXF
[править] Chomp 0.2
Версия Chomp на диске базируется на том, что мы сделали, и позволяет пользователям временно добавлять новые ленты, но вы можете сделать еще кое-что:
- Заставить работать функцию удаления ленты.
- Кэшировать ленты и GUID, чтобы при отображении они загружались из памяти, а не скачивались каждый раз из Сети.
- Реализовать поиск в кэшированных лентах.
- Добавить Refresh и RefreshAll.
- Поместить что-нибудь в строку состояния!
- Заполнить меню осмысленными действиями.
- Добавлять пользовательские ленты в файл sitelist.txt.
Целью этого урока было научить вас использовать Stetic, и я думаю, мы справились неплохо. Дальнейшая работа будет в основном писа ниной кода: обвешаем интерфейс всякими крутыми штуками. Почаще сохраняйте результат, и все будет в порядке – резвитесь!