Рефакторинг
Преди да продължим с избирането (указването) на обект от изображението нека направим малко рефакторинг. Ще променим кода на програмата с цел по-лесното ѝ развитие в бъдеще без да променяме нейното поведение.
В класовете „MyRectangle“ и „MyEllipse“ имаме повтарящ се код. Той ще става все повече в бъдеще. Затова е добре да го изнесем в общ родителски клас, който да бъде наследен от всички класове описващи фигури. Нека този клас се казва „CommonPrimitive“. Към него ще прибавим поле „selected“, което ще показва дали фигурата е избрана.
Класовете „MyRectangle“ и „MyEllipse“ наследяват „CommonPrimitive“. В тях остава само методът „draw“, като в него достъпът до частното поле „color“ вече става с публичния метод „getColor“. В конструкторите им просто викаме конструкторът на наследения (супер) клас.
Остава да добавим (някои от) методите към интерфейса, за да можем да ги използваме там където имаме обекти от тип „Primitive“.
Можем също да премахнем дублираният код за рисуване на фигури при влачене на мишката от метода „jPanelCanvasMouseDragged“. Този код се намира в метода „draw“ на всеки обект и е най-добре да си остане капсулиран там. За целта при всяко преместване на мишката вместо да рисуваме фигура ще създаваме нов обект и ще викаме метода му „draw“. Разбира се това е по-неефективен вариант, но по-добър от проектантска гледна точка.
В метода „GlobalVars.drawFigures()“ ще изчистваме цялото платно за рисуване (без очертанието му). За целта трябва да знаем неговия размер. В „GlobalVars“ добавяме полето „canvasSize“ и го използваме при изчистването.
Размера ще задаваме при неговата промяна.
За сега приключваме с рефакторинга.
Избиране
Трябва по някакъв начин да различаваме избраните обекти. За целта нека (в „CommonPrimitive“) рисуваме около тях пунктирана рамка.
„drawBorder“ извикваме от метода „draw“ на фигурите.
Преди да продължим с реализацията на избирането, нека да уточним какво поведение ще очакваме.
При натиснат бутон „Избиране“ и щракване върху фигура тя ще става избрана. Ако зад нея има други фигури те няма да се избират.
При натиснат бутон „Избиране“ и маркиране на област с мишката, всички обекти, които попадат в тази област ще бъдат избрани, включително тези, които са частично или изцяло зад най-предните фигури.
Натискането и задържането на бутона „Ctrl“ ще ни позволява да избираме повече от една фигура.
При създаването на нова фигура тя автоматично ще става избрана.
И така, при глобалните променливи добавяме още една, булева - „ctrlPressed“. Тя ще бъде истина, когато е настинат клавишът „Ctrl“.
Продължаваме с метода „deselectAll“ в „GlobalVars“, който ще прави неизбрани всички обекти.
Методът „GlobalVars.select()“ приема, като параметър правоъгълна област, проверява дали в нея се съдържат фигури и ако има такива ги отбелязва, като избрани. Ако правоъгълната област е с размер по-малък от 2x2 пиксела се проверява дали областта или точката принадлежат към най-предната (в тази област) фигура и ако е така, тя се избира. Всички други фигури стават неизбрани освен ако не е натиснат клавишът „Ctrl“.
Тъй като при щракването върху фигура обхождането на масива с фигури се прекратява при първата срещната, към която принадлежи точката на щракване, трябва предварително да се отбележат като неизбрани всички фигури (при условие, че клавишът „Ctrl“ не натиснат ).
Метода „select“ ще викаме при пускане на мишката (в „jPanelCanvasMouseReleased“), ако е натиснат бутона „Избиране“.
Ако пък се създава нова фигура то тя се отбелязва, като избрана.
Остава да прихващаме събитията натискане и пускане на клавиш, за да проверяваме дали той е „Ctrl“ и да променяме полето „GlobalVars.ctrlPressed“. Ще правим това с компонента „jPanelCanvas“ - платното ни за рисуване.
Когато прихващаме събития свързани с клавиатурата от компоненти, които не са текстови полета, те предварително трябва да са получили фокус. Затова при натискане на бутона „Избиране“ (т.е. в „jToggleButtonSelectActionPerformed“), ще фокусираме платното за рисуване - „jPanelCanvas“.
С метода „jPanelCanvasKeyPressed“ обработваме събитието натискане на клавиш. Ако кодът на клавиша съвпада с кода на „Ctrl“ правим глобалната променлива ctrlPressed истина.
При пускане на клавиш (jPanelCanvasKeyReleased) я правим лъжа.
Ако забелязахте от кода или от тестване на програмата, при щракване върху фигура, под която има друга такава, избрана става задната, а не както очакваме - предната. Нарочно съм ви оставил удоволствието да програмирате това сами. Става много лесно ако сте разбрали как работи кодът до тук :)
Промяна на цвета
Нека да добавим възможност за промяна на цвета на избран(ата|ите) фигури.
За целта добавяме надпис и панел, както направихме за текущия цвят. Нека името на панела да бъде „jPanelObjectColor“. (Припомням ви, че името се задава в секцията „Code“ или чрез щракване с десния бутон върху компонента.)
При щракване върху панела за промяна на цвят отваряме диалогов прозорец за избор с начален цвят - този от панела. Когато прозорецът се затвори променяме цвета на всички избрани обекти.
Казахме, че когато създадем нов обект, той автоматично ще става избран. Тогава в „jPanelCanvasMouseReleased“ трябва да променяме и цвета на новия панел.
Остава да сменяме цвета на панела, когато изберем обект/и. Тъй като те се избират в метода „select“ от класа „GlobalVars“ ни трябва достъп до панела от там. За целта ще създадем поле „jPanelObjectColor“.
Него ще насочваме към панела в конструктора на формата, след инициализацията на компонентите.
Ето и използването му при избиране на обект („GlobalVars.select()“).
Вече програмата ни започва да прилича на приложение за работа с векторна графика.
Оставям на вас да я тествате.
Ето го кода до тук: Trayangle-5.zip
А ето го и компилиран: Trayangle-5.jar
Можете да го стартирате от командния ред:
.../jdk1.6.0_22/jre/bin/java -jar Trayangle-5.jar
<< 4 - Цветове, изобразяване | 6 - Преместване, завъртане >> |
Коментари
Въпрос
Искам да питам за нещо не толкова свързано с този урок... Някой да знае как да си направя бутоните с изображение,а не с текст. От 30 мин. се опитвам да открия начин, но нещо не ми се получава.
Благодаря предварително!
Пишете на кирилица
Друг път пиши на кирилица, за да не се налага да редактирам съобщението ти.
Ако нямш кирилица и си под windwos погледни тук -> Гювечи от Инжинера. Или ползвай някой онлайн преобразувател: Кирилчо, kirilica.net, http://5ko.free.fr/bg/cyr.html
Съжалявам за кирилицата
Съжалявам, за кирилицата. А иначе някаква идея за въпроса ми по-горе как става?
Добре, ето как става
Добре, ето как става:
Пишеш в http://google.com „swing image on button“;
Щракаш на втория резултат;
И там виждаш:
:)
Добавяне на картинка с NetBeans
За да добавим картинка в Java програма чрез NetBeans, правим нов пакет „kartinki“.
Избираме бутона, (или друг компонент) върху който искаме да се покаже изображението (картинката) и в настройките му щракаме на трите точки вдясно от „icon“.
В появилия се прозорец щракаме върху бутона „Import to Project…“ и избираме файла (в случая картинка).
След това избираме пакета, в който искаме да се добави файлът - „kartinki“.
Щракаме на Finish, после на OK и сме готови.
В настройките на бутона от „horizontalTextPosition“ можем, да подравняваме текста спрямо изображението.
Благодаря много
Благодаря много за подробното обяснение! : )
Малък проблем...
,който забелязах преди малко.Нали идеята когато начертаем няколко фигури на екрана и примерно сме начертали,така че няколко фигури се засичат...когато тръгнем да селектираме би трябвало да се селектира този, който сме начертали последно..но тук се получава точно обратното, селектира се първата фигура.Опитах се да го оправя това, но ми е малко сложно когато "бъркам" в кода, който някой друг е писал....Ени хелп?
Малко решение...
Цитат от по-горе:
Ако нещо не ти е ясно по кода, питай.
Ако ти е трудно да бъркаш в чужд код най-добре си напиши свой :)
Ноу мор хелп абаут дис
Пириъд
Проблем със селектирането?
Съжалявам,че толкова те тормозя с въпроси и т.н. но току що забелязах пак една подробност с програмката, като си селектирал някаква произволна зона със селект бутона и ако в тази област има повече от една фигура, не винаги всичките се селектират, независимо каква част от тях попадат в тази избраната от нас област. Това пак ли е направено нарочно или не си го забелязал?
При мен няма проблем
Не е направено нарочно. Когато цялата фигура попада в маркираната област трябва да става избрана и при мен се получава. Ако обаче фигурата е завъртяна областта трябва да е малко по-голяма. Ако я маркираш точно по краищата може и да не се избере.
Ако можеш прати снимки на екрана за да видим какво точно се получава при теб.
Ясно
Не трябва ли принципно даден елемент да се селектира дори само малка част от него да попада в избраната от нас област.Или ти си го направил да се избира само ако целата фигура попадне в дадената област, тогава да се селектира.И ако може да ми разясниш малко как точно ти бачка метода за селектирането на една фигура,че нещо ми се губи как работи ще съм ти много благодарен! : )
Поздрави.
Избира се цялата фигура
Много по-логично е цялата фигура да попада в областта, за да бъде избрана. Така работят повечето програми. Ако искаш да избереш фигура чрез маркиране само на малка част от нея е по-добре направо да щракнеш в тази част.
Методът за избиране е обяснен по-горе. Задай конкретен въпрос. Какво точно не ти е ясно?
Не знам докъде си стигнал, но в следващата статия 6 - Преместване, завъртане методът „select“ е доста променен.
Хммм
Това, което ми трябва на мен е да направя така,че когато има две застъпени фигури да се селектира тази по-горе,а не долната, но не виждам къде става това.
Благодаря,че се занимаваш с нас! : )
Това става…
Когато имаш застъпени фигури и щракнеш върху тях променливата „area“ е „лъжа“, защото щракваш, а не маркираш област следователно се изпълнява кодът в „else“ блока. Там става избирането на най-горната/долната фигура.
Публикувай нов коментар