Рассылка закрыта
При закрытии подписчики были переданы в рассылку "Как создать свой сайт и заработать?" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
Программирование с нуля - это совсем просто! 35) Наконец-то! Или первая программа с графическим интерфейс
Информационный Канал Subscribe.Ru |
Программирование с нуля - это совсем просто!35) Наконец-то! Или первая программа с графическим интерфейсомЧтобы программа стала делать нужные нам вещи, надо сформировать в ней так называемый обработчик события "Нажатие на кнопку " Бросок кубика". Все пользовательские действия с программой вызывают в ней те или иные события. Это фундаментальный механизм работы Windows. Любые щелчки мыши, нажатие на кнопки, выборы пунктов меню, изменение состояний переключателей и множество других самых разных происшествий, которые человек может выполнить в ходе общения с программой, вызывают внутри нее соответствующие события. Причем одни события можно вообще не анализировать, а какие-то другие - внимательно проверять. Например, человек нажимает на кнопку - и Windows посылает внутрь программы сообщение "нажата такая-то кнопка". Другое дело, что программа может либо реагировать на это сообщение, либо его игнорировать. Такое игнорирование пока и происходит с нашим прототипом. Поэтому задача программиста - определить, что будет происходить при возникновении в программе тех или иных событий. Перед тем, как мы приступим к такой конкретизации работы программы, еще раз отметим фундаментальный принцип построения Windows-программ, который достаточно сильно отличается от той практики, которую мы получили, создавая консольные приложения. Процесс создания программ для Windows заключается в проектировании пользовательского интерфейса и в последующем программировании реакций приложения на события, которые могут возникать, когда пользователь общается с программой посредством этого интерфейса. Привязку различных возможных действий пользователя к событиям и способам их обработки в исходном тексте программы среда разработки выполняет автоматически. В нашем случае мы подготовили всего один элемент управления, на который человек может воздействовать - это кнопка. При нажатии на кнопку программа должна сгенерировать случайное число от одного до шести и показать его в поле-надписи. Для того, чтобы оболочка Delphi сформировала программный код, представляющий собой обработчик нажатия на кнопку, достаточно дважды щелкнуть мышкой на нашей кнопке в дизайнере. Оболочка наконец переключится из дизайнера в редактор, где появится автоматически сгенерированный текст.
procedure TForm1.Button1Click(Sender: TObject);
end;
Его смысл и структуру мы разберем более подробно далее - для этого потребуется не один урок, и хотя в методологическом плане вернее было бы начать с теории, многие, подозреваю, практики тогда не дождутся. Сейчас в отношении этого автоматически сгенерированного кода отметим одно - внутри пары begin / end нам просто надо записать програмный код, который будет содержать действия по обработке нажатия на клавишу - и все. Компилятор соберет код в работающую программу сам. Как нам генерировать случайные значения? Для этого в стандартной библиотеке System есть подходящая стандартная функция Random(), возвращающая случайное целое число (тип Integer), лежащее в диапазоне от нуля до значения, заданного параметром функции, минус единица. Так, Random( 6 ) выдаст случайное число в диапазоне от 0 до 5. Таким образом мы научились (теоретически) формировать случайное значение, лежащее в нужном нам диапазоне. Теперь остается понять, как это выражение можно показывать в окне программы. Для этого мы будем пользоваться компонентом поле-надпись Label. У этого компонента есть упоминавшееся свойство Caption, которое имеет тип String (строка) и позволяет записывать в него текстовые значения и получать их обратно - как обычная переменная. Поэтому мы можем получать и изменять его значение с помощью обычного оператора присваивания. Обращение к свойствам некоторого объекта записываются так: сначала указывается имя этого объекта, затем следует точка, а затем - название конкретного свойства этого объекта. Но ведь Label - это не название реального объекта, а всего лишь название одного из стандартных компонентов с палитры компонентов, который мы не можем использовать в программе напрямую. С другой стороны, мы уже разместили на форме экземпляр этого компонента и, видимо, можем к нему из программы обращаться. Но как определить, какое у этого этого объекта имя (в виде переменной) внутри нашей программы? Ведь оно было сгенерировано автоматически. По умолчанию имя такого объекта совпадает с его названием, которое показывается в дизайнере форм сразу после того, как мы разместили на проектированной форме соответствующий элемент. В нашем случае после размещения на форме поля-надписи в ней было показано название Label1. Именно через такое название - имя переменной! - мы можем обращаться к этому объекту. В программе он уже существует - описание всех элементов, подготовленных в дизайнере, включается оболочкой Delphi в текст программы, в автоматически сгенерированный раздел! Но пользоваться такими стандартными идентификаторами далеко не всегда удобно. Как нам изменить название Label1 на более подходящее? Выберем в дизайнере форм поле-надпись Label1 и переключимся на инспектор объектов. В окне свойств для данного объекта Label1 найдем свойство Name. Именно оно и представляет собой название данного объекта, которое представлено в программном коде как переменная. Важно не путать значение данного свойства - имя переменной - с другими свойствами, хранящими значения полей объекта. Значение свойства name не является значением некоторой переменной в программном смысле (в отличие от остальных свойств). Оно всего лишь определяет название идентификатора, который будет использоваться в программном тексте для связи с этим объектом. Сменим это название например на MyLabel. При этом все места в исходном тексте, где имелось обращение к данному объекту через его старое название Label1, будут автоматически исправлены системой Delphi на новое название MyLabel, введенное нами в поле Name. В подготовленном нами тексте на самом деле пока нет ни одного обращения к этому объекту, но они имеются в блоке, автоматически сгенерированном дизайнером форм. И в будущем при изменении подобных важных свойств Delphi самостоятельно будет вносить соответствующие корректировки в исходный текст программы. Итак, практический результат всех этих сложных рассуждений очень прост :) На форме есть несколько объектов - поле-надпись и кнопка. Кроме того, есть и сама форма как объект. К каждому из них мы можем обращаться как к переменной (только не простой, хранящей целое число или строку, а сложно устроенной, хранящей целый объект со всеми его свойствами), а имя этой переменной - значение поля Name в инспекторе объектов. У нас в программе уже есть (создана автоматически в момент размещения в дизайнере объекта на форме) переменная поля-надписи MyLabel, переменная кнопки (по умолчанию - Button1), а также сама форма (переменная Form1). Но эти переменные хитро устроены, хранят, как уже говорилось, не одно значение, а целую структуру, объект, то и обращаться к полям, свойствам соответствующего объекта надо через точку-разделитель.
Свойство Caption многих стандартных объектов позволяет изменить написанный на них текст. ДЛя доступа к нему надо сначала указать имя соответствующей переменной (например, MyLabel), затем точку и - название свойства: MyLabel.Caption Свойство - уже имеет конкретный изученный нами тип данных (если только оно само - не составное). Тип свойства Caption - строка (String). В нашем случае при нажатии на кнопку можем записать в поле-надпись строку "Привет тебе!" :
procedure TForm1.Button1Click(Sender: TObject);
MyLabel.Caption := ' Привет тебе! ' ;
end; Запустите программу и посмотрите, что получилось, понажимайте на кнопку. Заодно сделайте сами изменение и надписи на кнопке (через то же свойство Caption; а имя переменной с кнопкой - Button1, если вы его не изменили). Но нам требуется заносить в это свойство не строку-константу, а значение, возвращаемое функцией random(6). Это значение имеет тип Integer (целое число), а тип свойства Caption - String (строка). Можно ли присваивать строковой переменной числовое значение? В некоторых языках (Бейсике например) это возможно (в ситуациях, когда смысл такого преобразования достаточно очевиден и нагляден), хотя делать так все же не рекомендуется - лучше пользоваться стандартными функциями преобразования типов. Две популярные функции Delphi, преобразовывающие число в строку, и строку в число, из библиотеки SysUtils:
IntToStr() - задаем число, получаем строку;
IntToStr(6) = '6'
StrToInt() - задаем строку, получаем число;
StrToInt( '123' ) = 123
Если указать неверный параметр, то конечно возникнет ошибка в
StrToInt( ' abc ' ) - ошибка! параметр не представляет собой запись С учетом такой возможности запишем наконец:
procedure TForm1.Button1Click(Sender: TObject); random(6)+1 взято, чтобы результат выдавался в привычном виде, от 1 до 6, а не с 0 до 5. А если мы хотим добавить свои переменные, для расчета? Их можно объявить,по аналогии с консолью, непосредственно перед ключевым словом begin :
procedure TForm1.Button1Click(Sender: TObject);
var n: Integer;
begin
n := random(6)+1;
MyLabel.Caption := IntToStr( n );
end; Этими переменными (переменная n в нашем случае) можно пользоваться только в пределах данного обработчика! Если добавить еще одну кнопку, и создать второй обработчик нажатия, то внутри него переменная n уже не будет доступна. Это связано с важным принципом так называемой видимости или области действия переменных. Считается, что переменные можно использовать внутри того блока begin / end, в котором они были объявлены, и ни в каких внешних по отношению к нему. А называются такие переменные локальные. Можно объявить и глобальные переменные, которые будут видимы во всех обработчиках любых событий в программе. Например, переменные MyLabel и Button1 - глобальные, мы даже не видим в обработчике, где они декларированы, а пользоваться ими можно. Как это сделать для своих переменных, мы изучим, однако такой прием не всегда отвечает принципам структурного программирования, идея которого - минимизация взаимосвязей между модулями, каждый блок кода максимально независим от других (полностью ответственен за свое поведение :) - на этой основе создана даже методология целая, "ответственные объекты" называется!). Скомпилируем программу, запустим ее и нажмем на кнопку "Бросок кубика". В поле-надписи появится число 1 (на самом деле это строка "1", полученная преобразованием из числа 1). Если нажать на кнопку во второй раз, то эта цифра снова сменится на 1, после третьего нажатия - на 6, после четвертого и пятого будет показан одинаковый результат 2, затем - 5, и так далее. Все выпадающие значения лежат в нужном нам диапазоне 1-6, а предсказать следующий вариант практически невозможно, как и полагается случайному процессу. Но откуда я знаю, что у вас выпадет, если генератор - случайный? Об этом в следующий раз. Не могу не упомянуть еще один компонент - Edit (текстовое поле ввода). Он сразу идет на панели компонентов следом за Label. У него есть замечательное свойство Text, строка, содержимое которой пользователь может вводить вручную! Замечательно это свойство тем, что после его изучения вы теперь можете создавать программы с графическим интерфейсом. Ввод значений выполняется через объекты Edit по команде нажатия на кнопку, а вывод - через объекты Label. Кроме того, нормальный русский шрифт (кодировка) поддерживается! Тип свойства Text компонента Edit - String! (строка). То есть даже если вы введете число, оно все равно будет храниться как строка, и преобразовать его в число надо с помощью функции StrToInt(). Например. Мы хотим вводить сумму в долларах, нажимать кнопку и получать эквивалент в рублях. Добавим на форму компонент Edit (он получит название Edit1, и обращаться к нему в программе надо будет как?). В обработчике нажатия на кнопку запишем что-то следующее:
procedure TForm1.Button1Click(Sender: TObject);
var n: Integer;
begin
n := StrToInt( Edit1.Text ); // сумма в уе
MyLabel.Caption := IntToStr( n * 28 );
end; Запускаете, указываете сумму, жмете кнопку и получаете результат. Курс пересчета задан в коде (28 рублей за доллар), что неправильно - добавьте на форму еще одно поле ввода, в котором указывается текущий курс. Пока мы работаем только с целыми! Строку в дробное число преобразовывает функция StrToFloat( строка ), а дробное в строку - функция FloatToStr(). Соответственно, попробуйте изменить программу-валютный калькулятор так, чтобы она работала с дробными. А следом попробуйте теперь консольные наработки перенести сюда, в графику (называется GUI, графический интерфейс пользователя). Оформить все можно красиво, картиночки подложить итд :) Ура! Бейсик. Visual Studio.NET. И поле-надпись, и кнопка на панели инструментов так же называются - Label и Button. Только в.NET нет свойства Caption, а есть универсальное Text (как в поле ввода Edit в Delphi). Название в программе (имя переменной) -также Name. После двойного щелчка на кнопке сгенерируется следующий код:
private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
' здесь вставлять код обработки!
end Sub Имя переменной - MyLabel, свойство - Text. Вот как строка запишется при нажатии на кнопку:
private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
MyLabel.Text = "Привет тебе!"
end Sub Преобразование строки в число - функция Val(). Преобразование числа в строку - функция Str(). А вот со случайными посложнее. Для этого воспользуемся библиотекой Math. Самая подходящая на данном этапе - функция Rnd(), возвращающая случайное дробное число (тип Single), лежащее в диапазоне от нуля до единицы (точнее, оно может быть равным или большим нуля, но всегда меньше единицы). Теперь нам требуется преобразовать такую случайную величину в целое число, укладывающееся в диапазон от одного до шести. Достаточно для этого просто умножить значение, выдаваемое данной функцией, на шесть и затем взять целую часть от получившегося числа. В этом поможет стандартная функция Int(). Чтобы выделить целую часть некоторого значения, можно воспользоваться следующей записью: Int( Rnd() * 6 ) Правда, все получаемые таким образом значения будут лежать не в диапазоне от одного до шести, а в диапазоне от нуля до пяти. Ведь если в качестве случайного значения будет сгенерированно, например, число 0,1, то после умножения на шесть оно превратится в число 0,6 и будет все равно меньше единицы. А если выпадет одно из самых больших случайных значений функции Rnd() (это может быть например 0,99999, но обязательно немного меньше единицы), то после умножения на шесть и взятия дробной целой части все равно будет получено не шесть а пять. Поэтому в подготовленную нами формулу остается прибавить единицу, чтобы формируемое значение укладывалось в нужный нам диапазон: Int( Rnd() * 6 ) + 1 У каждого свои недостатки :) MyLabel.Text = Str(Int(Rnd() * 6) + 1) Как уже говорилось, в случае Бейсика можно обойтись без функции Str(), число в строку автоматически преобразуется. Поле ввода - компонент TextBox (аналог Edit в Delphi). Тоже через свойство Text получаем содержимое. Вот эквивалент валютного калькулятора на Бейсике (на форму добавлен компонент TextBox, значение свойства Name - TextBox1). В обработчике достаточно указать один оператор: MyLabel.Text = Str(Val(TextBox1.Text) * 28) Собственные переменные, если надо, свободно объявляем в начале обработчика:
private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Dim n As Integer
MyLabel.Text = Str(n)
end Sub Я сторонник именно такого подхода - детализировать сложные выражения по кусочкам. Возможно, потому, что учился программированию на Паскале (точнее, на Алголе 68 :), где такой подход приветствуется. А вот Си-программисты обычно исповедуют максимальную компактность :) Borland C++Builder, C++. Это среда, аналогичная Delphi, только язык в ней не Паскаль, а Си++. После двойного щелчка на кнопке спроектированной формы получим такой код:
void __fastcall TForm1::Button1Click(TObject *Sender) Комментарии, это я написал, не среда :) Остальное все почти то же, только вместо точки, связывающей объект и свойство, используется комбинация "->" (стрелочка такая из двух символов).
void __fastcall TForm1::Button1Click(TObject *Sender) Функции преобразования и случайной генерации - такие же, как и в Дельфи:
void __fastcall TForm1::Button1Click(TObject *Sender) Только не забывайте, что в Си/Си++ различаются слова, набранные на разных регистрах. Если написано random(), то Random() будет неправильной записью. Переменные в пределах данного обработчика (локальные) объявляются в его начале. Дополним форму полем ввода и напишем валютный калькулятор:
void __fastcall TForm1::Button1Click(TObject *Sender) Этот урок был очень важен! Разберетесь в нем - считайте, почти профи :) Что делать, если вы что-то не поняли? Спрашивать правильно надо так - читаете текст рассылки (медленно!), определяете фразу и слово, на котором ваше понимание прекратилось, пытаетесь три раза :) понять трудное место самостоятельно, и если не выходит, пишете мне. При этом указываете строчку и слово, после которого ваше понимание пропало. (c) 2004 Сергей Бобровский bobrovsky@russianenterprisesolutions.com
Школа программирования с нуля
Все предыдущие выпуски базового курса тут:
|
http://subscribe.ru/
http://subscribe.ru/feedback/ |
Подписан адрес: Код этой рассылки: comp.soft.prog.prognull |
Отписаться |
В избранное | ||