PDA

Просмотр полной версии : TextArea, ScrollEvent.SCROLL и вообще про события во Flex


lephik
15.03.2007, 06:29
Подскажите плз. почему когда листенишь ScrollEvent.SCROLL у TextArea то verticalScrollPosition показывает значение предыдущщего скроллинга, и какое событие нужно листенить чтобы после скролла получить реально значение verticalScrollPosition и других свойств
TextArea.
спасибо

etc
15.03.2007, 13:16
Кажется, там нужен validateNow выполнить. Не смотрел.

lephik
15.03.2007, 13:31
да, слышал про такую штуку :)
validateNow называется,
пробовал - не помогает.

etc
15.03.2007, 13:51
Собери нерабочий пример.

lephik
15.03.2007, 14:54
не буду приводить код полностью но в целом проблема сводится вот к такой:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
import mx.events.ScrollEvent;
private function ta_scroll(e:ScrollEvent) {
ta.validateNow();
trace("verticalScrollPosition: " + ta.verticalScrollPosition);
//trace(e.position);
}
]]>
</mx:Script>
<mx:TextArea id="ta" text="kykykykykykkyykykkykykykykykykykykykykykkykykyky"
width="100" height="50" scroll="ta_scroll(event);" >
</mx:TextArea>
</mx:Application>

ну так вот в этом примере ta.verticalScrollPosition выдаёт неправильное значене.

etc
15.03.2007, 15:37
Заглянул в сорцы TextArea и увидел там любопытные строчки:

override protected function scrollHandler(event:Event):void
{
// TextField.scroll bubbles so you might see it here
if (event is ScrollEvent)
{
if (!liveScrolling &&
ScrollEvent(event).detail == ScrollEventDetail.THUMB_TRACK)
{
return;
}

super.scrollHandler(event);

textField.scrollH = horizontalScrollPosition;
textField.scrollV = verticalScrollPosition + 1;

_vScrollPosition = textField.scrollV - 1;
_hScrollPosition = textField.scrollH;
}
}

А внутри ScrollControlBase:

protected function scrollHandler(event:Event):void
{
// TextField.scroll bubbles so you might see it here
if (event is ScrollEvent)
{
var scrollBar:ScrollBar = ScrollBar(event.target);

var pos:Number = scrollBar.scrollPosition;

var prop:QName;
if (scrollBar == verticalScrollBar)
prop = new QName(mx_internal, "_verticalScrollPosition");
else if (scrollBar == horizontalScrollBar)
prop = new QName(mx_internal, "_horizontalScrollPosition");

dispatchEvent(event);

if (prop)
this[prop] = pos;
}
}


Т.е. событие для скролла вызывается до того, как свойство изменилось в самом TextArea. Как это обходить, я не знаю, жди спецов по флексу.

Кстати, event.position выдает верное значение. Что мешает его использовать?

lephik
16.03.2007, 07:42
Дело в том что я пытаюсь добавить смайлы в этот самый TextArea,
для этого экстендю TextArea, и делаю внутренний TextField публичным.
У TextField есть метод - getCharBoundaries, который возвращает Rectangle в котором находится определённая буква ( в моём случае - смайл ).
Так вот после скролла этот метод getCharBoundaries внетреннегно текстфилда тоже выдаёт неправильное значение :(
Спасибо большое за ответ, думаю теперь я разберусь.

etc
16.03.2007, 12:14
Тебе нужно отложить выполнение до следующего кадра хотя бы. Или на некоторое кол-во миллисекунд. Или переписать scrollHandler.

john
16.03.2007, 12:56
удобно таком случае пользоваться callLater -

callLater(function():void
{
....
});

etc
16.03.2007, 13:00
Примерчик заодно:
http://livedocs.macromedia.com/flex/2/docs/00001438.html

Хотя, раз наследуемся от TextArea, то можно и переписать scrollHandler. Не знаю, правда, может это к глюкам каким-нибудь привести или нет…

lephik
16.03.2007, 13:20
в своём классе наследующем TextArea делаю примерно так:

override protected function scrollHandler(event:Event) : void {
super.scrollHandler(event);
dispatchEvent(new Event("afterScroll",false,false));
}

всё вроде работает, verticalScrollPosition пашет, всё остальное тоже, но теперь другая беда - когда текст вмещается в TextArea полностью, почемуто всёравно появляется скролл и естественно всё портит :(

etc
16.03.2007, 13:28
А что с scrollPolicy?

lephik
16.03.2007, 14:34
verticalScrollPolicy поменял на on - ничего не изменилось. :)

etc
16.03.2007, 14:35
На auto надо.

lephik
16.03.2007, 14:54
так по умолчанию итак auto.
фишка в том что возникает ситуация когда verticalScrollPosition меняется а положение текста - нет.

etc
16.03.2007, 15:05
Это как-нибудь связано с тем, что ты переписал scrollHandler или нет?

lephik
16.03.2007, 15:22
нет... это всегда такое поведение у TextArea.
из хелпа:
Line number of the top row of characters that is currently displayed. The default value is 0.
на самом деле это не так, легко увидеть если просто в TextArea вбить текст который помещается в неё - скролл будет, будет меняться verticalScrollPosition, но текст , а соответственно и номер верхней строки будут оставаться на месте.

etc
16.03.2007, 15:25
Ну опять же, ты можешь переписать любую часть TextArea так, как нужно.

__i
16.03.2007, 20:36
Ну опять же, ты можешь переписать любую часть TextArea так, как нужно.
Еще раз подтвердив любовь Адоба к разработчикам

etc
17.03.2007, 00:45
Ну как есть, я уже начинаю радоваться, что я не работаю с компонентами постоянно, а только вот в таких случаях :D
Ковыряться в чужих классах и искать косяки занятие не очень благодарное :D

lephik
19.03.2007, 14:30
проблема решилась использованием scrollV внутреннего текстфилда TextArea вместо verticalScrollPosition.
Теперь решаем другую - не срабатывает событие скролла если скролить
колесом - будем думать :)

etc
19.03.2007, 14:33
Вот они, флексовые компоненты :D
Ну я могу лишь посоветовать подписать scrollHandler. Хотя он вообще-то работает при скролле. Видимо, ты где-то что-то переопределил.

lephik
20.03.2007, 12:11
помогите разобратся плз. похоже я не допонимаю чего-то :)
TextArea наследуется от ScrollControlBase, при этом в конструкторе ScrollControlBase приписывается листенер для MouseEvent.MOUSE_WHEEL,
mouseWheelHandler:

protected function mouseWheelHandler(event:MouseEvent):void
{
// If this Container has a vertical scrollbar,
// then handle the event and prevent further bubbling.
if (verticalScrollBar)
{
event.stopPropagation();

var scrollDirection:int = event.delta <= 0 ? 1 : -1;

// Make sure we scroll by at least one line
var scrollAmount:Number = Math.max(Math.abs(event.delta),
verticalScrollBar.lineScrollSize);

// Multiply by 3 to make scrolling a little faster
var oldPosition:Number = verticalScrollPosition;
verticalScrollPosition += 3 * scrollAmount * scrollDirection;

var scrollEvent:ScrollEvent = new ScrollEvent(ScrollEvent.SCROLL);
scrollEvent.direction = ScrollEventDirection.VERTICAL;
scrollEvent.position = verticalScrollPosition;
scrollEvent.delta = verticalScrollPosition - oldPosition;
dispatchEvent(scrollEvent);
}
}

в классе TextArea он переопределяется:

override protected function mouseWheelHandler(event:MouseEvent) : void {
event.stopPropagation();
}

Вопрос - каким образом TextArea реагирует на Wheel если mouseWheelHandler переопределён и ничего не делает ?

__i
20.03.2007, 12:30
реагирует текстовое поле которое находиться в текст арии, а текст ария слушает это событие у этого текстового поля (это я так предположил :D)

etc
20.03.2007, 13:38
lephik, но TextField-у не прикажешь, он крутится же)

lephik
20.03.2007, 14:43
а... блин панял спасибо чуваки ;)
похоже всётаки не зря адобы в SDK сорсы фреймворка запхали....

__i
20.03.2007, 14:57
похоже всётаки не зря адобы в SDK сорсы фреймворка запхали....

Если бы они этого не сделали то была бы нам полная Ж! И вообще фиг бы кто повелся програмить на флекс