$$ \newcommand{\floor}[1]{\left\lfloor{#1}\right\rfloor} \newcommand{\ceil}[1]{\left\lceil{#1}\right\rceil} \renewcommand{\mod}{\,\mathrm{mod}\,} \renewcommand{\div}{\,\mathrm{div}\,} \newcommand{\metar}{\,\mathrm{m}} \newcommand{\cm}{\,\mathrm{cm}} \newcommand{\dm}{\,\mathrm{dm}} \newcommand{\litar}{\,\mathrm{l}} \newcommand{\km}{\,\mathrm{km}} \newcommand{\s}{\,\mathrm{s}} \newcommand{\h}{\,\mathrm{h}} \newcommand{\minut}{\,\mathrm{min}} \newcommand{\kmh}{\,\mathrm{\frac{km}{h}}} \newcommand{\ms}{\,\mathrm{\frac{m}{s}}} \newcommand{\mss}{\,\mathrm{\frac{m}{s^2}}} \newcommand{\mmin}{\,\mathrm{\frac{m}{min}}} \newcommand{\smin}{\,\mathrm{\frac{s}{min}}} $$

Prijavi problem


Obeleži sve kategorije koje odgovaraju problemu

Još detalja - opišite nam problem


Uspešno ste prijavili problem!
Status problema i sve dodatne informacije možete pratiti klikom na link.
Nažalost nismo trenutno u mogućnosti da obradimo vaš zahtev.
Molimo vas da pokušate kasnije.

Још неке контроле

До сада смо упознали неколико контрола које се често користе на формуларима:

  • лабела (Label)

  • оквир за груписање (Group box)

  • текстуално поље (Text box)

  • дугме (Button)

  • поље за потврду (Check box)

Видели смо како да можемо да очитавамо и мењамо својства контрола. Почетне вредности својстава контрола се могу постављати у време дизајнирања формулара из прозора Properties, а могу се мењати и из програма, за време његовог извршавања (као пример, мењали смо својство Enabled поља за потврду).

Сада ћемо упознати још неке контроле, њихову намену, најважнија својства и догађаје.

Нумеричко поље

Нумеричко поље служи за унос (најчешће целог) броја. Назив ове контроле на енглеском је NumericUpDown и она се такође налази у групи уобичајених контрола кутије за алат (Toolbox \(\to\) Common Controls).

Најважније својство нумеричког поља је Value и оно садржи вредност коју корисник задаје помоћу ове контроле. Још два важна својства карактеристична за нумеричко поље су Minimum и Maximum. Помоћу ових својстава ограничавамо опсег вредности које корисник може да зада у време извршавања прогрма. Својства Minimum и Maximum обично само постављамо у време дизајнирања формулара и касније их не мењамо.

Најважнији догађај нумеричког поља је догађај ValueChanged. Овај догађај се дешава при свакој промени својства Value нумеричког поља.

Следећи једноставан пример показује како се нумеричка поља могу користити у програмима.

Пример - боја позадине

Креирати Windows Forms апликацију, која помоћу три нумеричка поља омогућава кориснику да зада боју позадине формулара.

Као што је и тражено, поставићемо три нумеричка поља на формулар. Пољима ћемо дати имена (својство Name) nCrvena, nZelena и nPlava, јер се свака боја у рачунарској графици задаје одређеном количином црвене, зелене и плаве. Те количине су стандардно представљене вредностима од 0 до 255, па ћемо својство Maximum свих трију контрола поставити на 255 (својство Minimum је већ постављено на 0 и то нам одговара, па то својство нећемо мењати).

Поред сваког нумеричког поља поставићемо по једну лабелу са именом одговарајуће боје, да би корисник знао шта којим нумеричким пољем поставља. Уз уобичајена подешавања својстава формулара (својства Text, FormBorderStyle и MaximizeBox) фаза дизајнирања је готова. Ево како изгледа формулар:

../_images/BojaPozadine_Form.png

Поставимо сада функцију за контролу догађаја ValueChanged. Можемо користити исту функцију за све три контроле, као у примеру „Одреди децу”. Подсетимо се, потребно је пронаћи догађај у листе једне (било које) од ове три контроле, уписати име функције за обраду догађаја (рецимо PostaviBoju), а затим за остале две контроле бирати исту функцију у падајућој листи за тај догађај.

Функцију PostaviBoju можемо да напишемо овако:

private void PostaviBoju(object sender, EventArgs e)
{
    int r = (int)nCrvena.Value;
    int g = (int)nZelena.Value;
    int b = (int)nPlava.Value;
    BackColor = Color.FromArgb(r, g, b);
}

Ако желимо да својство Value нумеричких поља сместимо у целобројне променљиве, неопходна је експлицитна конверзија (cast), јер својство Value је типа decimal.

Након очитавања количине црвене, зелене и плаве коју је задао корисник потребно је још само поствавити вредност својству BackColor формулара, што је учињено последњом линијом кода. Својство BackColor је типа Color и представља боју позадине формулара. Променом вредности овог својства аутоматски се мења и боја (позадине) формулара.

Програм је готов и можемо да га испробамо.

Радио дугме

Радио дугме (енгл. Radio button) је још једна од врло често коришћених контрола. Она служи да се изабере једна од неколико понуђених могућности. Свака могућност се представља једним радио дугметом, па се оно не користи појединачно него се на формулар увек ставља неколико радио дугмета. Избор једног дугмета уједно поништава претходни избор, ако је постојао.

Занимљивост 🤓

Стари радио апарати су имали механичку дугмад за избор станице, или за избор врсте радио таласа (AM / FM). Притиском на једно дугме из групе, дугме које је претходно било притиснуто би „искочило”, тако да је у сваком тренутку само једно дугме из групе могло да буде притиснуто. Отуда име и овој софтверској контроли.

Радио дугме се налази на истом месту као и остале контроле које смо до сада користили - у групи уобичајених контрола кутије за алат (Toolbox \(\to\) Common Controls).

Најважније својство радио дугмета је својство Checked- Ово својство је логичког типа и оно говори да ли је дато дугме изабрано, односно „притиснуто”. У пару са тиме, најважнији догађај радио дугмета је догађај CheckedChanged и он се дешава када се дугмету промени вредност својства Checked. Овај догађај користимо само ако желимо да програм реагује одмах након избора корисника.

Следећи једноставан пример показује како се радио дугмад могу користити у програмима.

Пример - тест

Креирати Windows Forms апликацију која кориснику поставља једно питање са више понуђених одговора, прихвата дати одговор и даје коментар.

На формулар ћемо поставити лабелу која садржи питање, 4 радио дугмета са могућим одговорима и дугме на које корисник треба да кликне када заврши са бирањем одговора. Упишимо неко питање у својство Text лабеле и понуђене одговоре у својство Text радио дугмади, тако да формулар изгледа отприлике овако:

../_images/Test_Form.png

Поставимо имена радио дугмади (својство Name) редом на rbNekoliko, rbJedna, rbDaNe, rbRedosled. У овом примеру нећемо програмирати догађаје ових контрола, него само клик на дугме „Одговори”, коме смо у програму дали име btnOK. Када корисник кликне „Одговори”, желимо само да му саопошимо да ли је дао тачан одговор. То можемо да урадимо у додатном прозору са кратком поруком.

using System;
using System.Windows.Forms;

namespace Test
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            if (rbJedna.Checked) MessageBox.Show("Tako je.");
            else MessageBox.Show("Pokušaj ponovo.");
        }
    }
}

Пример - тест и помоћ

Поменули смо да је најважнији догађај радио дугмета догађај CheckedChanged. Да смо додали реакцију на овај догађај, програм би исписивао поруку одмах по клику корисника на радио дугме и не би пружио прилику кориснику да се предомишља.

Уместо контролисања догађаја CheckedChanged овде ћемо (само ради разноврсности примера) испрограмирати један знатно ређе коришћен догађај а то је померање миша преко контроле (догађај MouseHover).

Изменити пример „Тест” тако да програм наговештава кориснику да ли је одговор који се спрема да изабере исправан.

Додаћемо још једну лабелу у којој ће се налазити сугестија, и назваћемо ту лабелу lblHint. Можемо и да подесимо својство Font нове лабеле тако да њен текст буде нешто крупнији.

Задајмо и контролу новог догађаја. Када кликнемо на радио дугме са тачним одговором а затим на „муњу”, у листи догађаја треба да нађемо MouseHover. У поље поред имена овог догађаја уписујемо „IznadTacnog” као име будуће функције која ће контролисати овај догађај.

../_images/TestPomoc_MouseHover.png

На овај догађај приказујемо у лабели lblHint неки текст који наговештава кориснику да је на добром месту.

private void IznadTacnog(object sender, EventArgs e)
{
    lblHint.Text = "😉";
}

Слично овоме, за остала три радио дугмета постављамо заједничку функцију за обраду догађаја MouseHover. Функцију називамо IznadPogresnog и у њу уписујемо наредбу за приказивање супротне сугестије.

private void IznadPogresnog(object sender, EventArgs e)
{
    lblHint.Text = "😟";
}

Испробајте овај програм тако што ћете зауставити миша код сваког радио дугмета и сачекати без клика.

Бирач датума и времена

После примера „Старост” смо поменули да би било боље да кориснику за задавање датума понудимо контролу специјализовану за то. Таква контрола се на енглеском зове DateTimePicker и такође се налази у групи уобичајених контрола кутије за алат (Toolbox \(\to\) Common Controls).

Код бирача датума и времена најважније својство је својство Value, које садржи изабрани датум и време. Вредност је типа DateTime који смо већ помињали. Овде се не можемо упуштати у описивање овог врло корисног типа и његових својстава, али свакако подстичемо заинтересованог читаоца да се детаљније упозна са њим.

Пример - старост са избором датума

Креирати Windows Forms апликацију, која омогућава кориснику да унесе име и датум рођења, а затим исписује његову старост у данима.

Текст је потпуно исти као у када смо први пут решавали овај задатак. Сада ћемо уместо текстуалних поља користити специјализовану контролу.

На формулар ставимо једно тексуално поље за име и испред тог поља лабелу са текстом „Име”, као што смо и први пут урадили.

Испод текстуалног поља ставимо бирач датума (DateTimePicker), а испред њега лабелу са текстом „Датум рођења”.

Испод ових контрола ставимо и дугме за крај уноса.

Имена текстуалног поља, бирача датума и дугмета нека буду редом tbIme, dtDatumRodjenja, и btnOK. Дизајниран формулар изгледа овако:

../_images/StarostDT_Form.png

И овај пут ћемо програмирати само дугме. Функција која обрађује клик на дугме је сада нешто краћа него први пут:

private void btnOK_Click(object sender, EventArgs e)
{
    DateTime danas = DateTime.Now;
    TimeSpan starost = danas.Subtract(dtDatumRodjenja.Value);
    string poruka = string.Format("{0} danas ima {1} dana",
        tbIme.Text, (int)starost.TotalDays);
    MessageBox.Show(poruka);
}

Комбиновано поље

Комбиновано поље (engl. ComboBox) је контрола која може да се употреби на више начина, што се може закључити и из имена контроле. Једна од функција комбинованог поља је избор ставке из фиксиране или падајуће листе. Осим тога, зависно од подешавања, коминовано поље може да се користи и за задавање нових избора (који нису били у понуди), памћење тих нових избора и њихово уврштавање у понуду. У многим едиторима тражење текста је остварено помоћу комбинованог поља - можемо да задамо текст који тражимо, или да изаберемо неки од текстова које смо претходно тражили.

Стил комбинованог поља се подешава помоћу својства DropDownStyle. Ово својство може да има вредност Simple, DropDown или DropDownList и вредност овог својства се најчешће подешава само током дизајнирања формулара (у прозору Properties).

../_images/ComboBoxStyles.png
  • Задавањем вредности Simple добијамо листу која се у сваком тренутку види цела на формулару. Могу се бирати само понуђене вредности.

  • Задавањем вредности DropDown добијамо комбинацију текстуалног поља и листе (отуда назив контроле - комбиновано поље). Листа се отвара кликом на стрелицу на десном крају контроле.

  • Задавањем вредности DropDownList добијамо листу која се отвара кликом на стрелицу (није могућ унос нових избора).

Својство Items је колекција стрингова који представљају ставке наведене у комбинованом пољу. Ово својство се може попунити из прозора Properties током дизајнирања формулара, а може и програмски у току извршавања апликације (на пример из базе података).

Пример - резервација

У овом примеру ћемо поред комбинованог поља искористити и већину контрола које смо до сада упознали.

Креирати Windows Forms апликацију која симулира резервисање хотелског смештаја.

Пошто у овом задатку планирамо да ставимо велики број контрола на формулар, биће лакше описивати замисао и пратити опис ако прво прикажемо слику дизајнираног формулара.

../_images/RezervacijaHotela_Form.png

Пре описа употребљених контрола редом, прокоментарисаћемо један детаљ који није само естетски. Видимо да су радио дугмад за избор типа смештаја и за избор категорије хотела лепо раздвојене. У ту сврху употребили смо два оквира за груписање (контрола GroupBox која је поменута у првом примеру „Старост”, налази се у групи Containers кутије за алат). На формулар прво ставимо ове оквире за груписање а затим у оквире ставимо радио дугмад. У овом примеру оквири нису само украс, него омогућавају да корисник изабере два радио дугмета у исто време: једно за тип смештаја, а друго за категорију хотела. Да нисмо користили оквире за груписање, свих осам радио дугмета би било једна група и само једно од свих осам би могло да се изабере!

Осим поменутих оквира за груписање, на овом формулару користимо следеће „активне” контроле (све за налазе у групи Common Controls кутије за алат):

  • комбиновано поље cbOdrediste за избор града у који се путује

  • бирач датума dtOd за избор датума доласка

  • бирач датума dtDo за избор датума одласка

  • радио дугмад за избор типа смештаја - rbSve за све укључено (all inclusive), rbPun за пун пансион, rbPolu за полупансион и rbNocDor за ноћење са доручком

  • радио дугмад за избор категорије хотела - rbNekategorisan за некатегорисан хотел, rbTriZvezdice за хотел са три звездице, rbCetiriZvezdice, за хотел са четири звездице и rbPetZvezdica за хотел са пет звездица

  • нумеричко поље nBrOdraslih за број одраслих гостију

  • нумеричко поље nBrDece за број деце

  • лабела lblCena за приказивање вредности резервације

  • дугме btnRezervisi за потврђивање уноса података и резервацију

Испред неких од ових контрола стављамо и лабелу која појашњава кориснику намену контроле.

Комбиновано поље cbOdrediste ћемо додатно подесити тако да својство DropDownStyle има вредност DropDownList, а у својство Items ћемо уписати неколико одредишта. Кликом на мало дугме са три тачке десно од својства Items отвара се нови прозор за уношење ставки листе.

../_images/RezervacijaHotela_Items.png

Не желимо да омогућимо да се резервација врши само за децу, па захтевамо да број одраслих буде најмање 1. То значи да за нумеричко поље nBrOdraslih постављамо својство Minimum на 1. Поставимо и остале границе за број особа на неке разумне вредности, на пример својство Minimum за број деце поставимо на 0 (одрасли могу да путују и без деце), а својство Maximum на 30 за одрасле и на 10 за децу.

Лабели lblCena (и лабели са текстом „Цена” испред ње) можемо да повећамо фонт, јер је ово најважнији податак на формулару.

Остале контроле ћемо користити такве какве су у свом почетном стању (нећемо их додатно подешавати).

Јасно је да свака од активних контрола (тј. оних помоћу којих корисник нешто бира), утиче на цену услуге. Због тога је најједноставније да догађај промене избора на контроли за све контроле повежемо са једном истом функцијом за обраду догађаја. Функцију за обраду ћемо назвати IzracunajCenu а у прозору Properties ћемо је повезати:

  • са догађајем SelectedIndexChanged комбинованог поља cbOdrediste

  • са догађајем ValueChanged бирача датума dtOd и dtDo

  • са догађајем CheckedChanged сваког радио дугмета

  • са догађајем ValueChanged нумеричких поља nBrOdraslih и nBrDece

У стварној употреби бисмо начин рачунања добили од онога ко наручује програм. У нашем примеру ћемо се поиграти и осмислити неки импровизован начин рачунања. Уводимо коефицијенте за одредиште (већи коефицијент значи скупљи град), за категорију хотела и тип смештаја. За децу рачунамо 70% цене коју рачунамо за одрасле. Функција IzracunajCenu би могла да изгледа овако:

private void IzracunajCenu(object sender, EventArgs e)
{
    double koefGrad = 0;
    switch (cbOdrediste.SelectedIndex)
    {
        case 0: koefGrad = 1.9; break; // Atina
        case 1: koefGrad = 1.5; break; // Barselona
        case 2: koefGrad = 1.4; break; // Kairo
        case 3: koefGrad = 1.6; break; // Lisabon
        case 4: koefGrad = 1.7; break; // Madrid
        case 5: koefGrad = 2.1; break; // Venecija
    }

    TimeSpan ts = dtDo.Value - dtOd.Value;
    double brNocenja = Math.Max(0, Math.Round(ts.TotalDays));

    double koefKategorija = 0;
    if (rbNekategorisan.Checked) koefKategorija = 1;
    else if (rbTriZvezdice.Checked) koefKategorija = 1.2;
    else if (rbCetiriZvezdice.Checked) koefKategorija = 1.3;
    else if (rbPetZvezdica.Checked) koefKategorija = 1.4;

    double koefTip = 0;
    if (rbSve.Checked) koefTip = 2.0;
    else if (rbPun.Checked) koefTip = 1.5;
    else if (rbPolu.Checked) koefTip = 1.4;
    else if (rbNocDor.Checked) koefTip = 1.0;

    double brOsoba = (double)nBrOdraslih.Value + 0.7 * (double)nBrDece.Value;

    double osnovnaCena = 15;
    double cena = osnovnaCena * brNocenja * brOsoba * koefKategorija * koefTip * koefGrad;
    lblCena.Text = string.Format("{0:0.00}", cena);
}

За комплетирање ове апликације за „резервисање” смештаја недостаје још функција за обраду клика на дугме. Пошто не можемо да изведемо никакву стварну акцију, у ову функцију ћемо ставити само једноставно приказивање поруке.

private void btnRezervisi_Click(object sender, EventArgs e)
{
    if (lblCena.Text == "" || double.Parse(lblCena.Text) == 0)
        MessageBox.Show("Prvo izaberite sve parametre");
    else
        MessageBox.Show("Izvršili ste rezervaciju");
}