#c# #animation #png #sprite #picturebox
#c# #Анимация #png #спрайт #picturebox
Вопрос:
Я пытаюсь создать событие щелчка, которое запускает анимацию. Я нарисовал все кадры и сохранил их в виде отдельных файлов PNG (все они имеют длину 38 пикселей и ширину 56 пикселей), но я не могу понять, как запустить их через PictureBox.
Я просмотрел множество сообщений (здесь и в других местах), где люди говорят о таймерах, но я не смог понять, как вызвать любой из этих длинных примеров из моего события click. В качестве альтернативы я экспортировал кадры как один анимированный GIF, но GIF-файлы всегда зацикливаются, и я хочу, чтобы анимация воспроизводилась только один раз.
Вот что у меня есть:
private void btnStart_Click(object sender, EventArgs e)
{
int delay = 100;
box1.Image = Project.Properties.Resources.frame1;
System.Threading.Thread.Sleep(delay);
box1.Image = Project.Properties.Resources.frame2;
System.Threading.Thread.Sleep(delay);
box1.Image = Project.Properties.Resources.frame3;
System.Threading.Thread.Sleep(delay);
box1.Image = Project.Properties.Resources.frame4;
System.Threading.Thread.Sleep(delay);
box1.Image = Project.Properties.Resources.frame5;
System.Threading.Thread.Sleep(delay);
box1.Image = Project.Properties.Resources.frame6;
System.Threading.Thread.Sleep(delay);
box1.Image = Project.Properties.Resources.frame7;
System.Threading.Thread.Sleep(delay);
box1.Image = Project.Properties.Resources.frame8;
//(and so on)
}
Это ожидает около секунды, а затем резко переключается на последний кадр (frame8 в этом примере), независимо от того, какова переменная задержки.
Вероятно, я подхожу к этому совершенно неправильно. Что вы, ребята, думаете?
Ответ №1:
Обработчик событий блокирует основной поток. Пользовательский интерфейс обновляется в основном потоке.
Итак, вы нажимаете на кнопку, обработчик событий блокирует поток и выполняется, и все, что вы изменяете, не будет затронуто в пользовательском интерфейсе до тех пор, пока обработчик событий не завершит работу — это именно то, что вы испытываете.
Итак, в вашем обработчике событий нажатия кнопки вам нужно инициировать процесс, но сам процесс должен быть в отдельном потоке. Самый простой способ, если вы используете покадровую анимацию, — это использовать таймеры.
Вам нужно установить интервал в таймере, а в случае отметки таймера вам нужно загрузить новое изображение в поле изображения. Вам нужно отслеживать текущий индекс кадра с помощью отдельной переменной. Если внутри события tick вы понимаете, что это было последнее изображение — установите таймер в положение disabled. Сбросьте таймер и переменную кадра в событии нажатия кнопки.
Комментарии:
1. В этом есть смысл. Однако я ничего не знаю о таймерах. Я просмотрел это — dotnetperls.com/timer — но я не знаю, что все это значит.
2. Я предполагаю, что вы используете winforms, поэтому все, что вам нужно, это добавить компонент Timer в свою форму, а затем дважды щелкнуть по нему, чтобы создать обработчик таймера. Затем вам нужно создать переменную класса для обработки индекса фрейма.
3. Все в порядке. Я вставил все команды Image и delay в новое событие timer1_Tick и поместил «timer1_Tick ();» в событие click. Он подчеркнул эту ссылку, как будто ему нужны какие-то входные переменные.
4. Вы не должны звонить
timer_Tick
напрямую, вы должны сделать его активным ИЛИ неактивным. Когда таймер активен (его свойствоEnabled
равноTrue
), он генерируетtimer_Tick
событие по его ссылке черезInterval
в ms (что является еще одним свойством таймера). Таким образом, таймер должен быть отключен по умолчанию, при нажатии кнопки вам нужно включить его, а при последнем тике таймера вам нужно снова отключить таймер.5. Извините, что я не ответил раньше, мне нужно было идти спать. Я помещаю «timer1.Start ();» в событие щелчка и «timer1.Stop ();» после всего, что было раньше. Он все еще останавливается на секунду и переходит к последнему кадру. Что я делаю не так?
Ответ №2:
Что я в конечном итоге сделал, так это поискал в Google подсказку «сам процесс должен быть в отдельном потоке» в первом ответе и последовал этому видеоуроку. То, что я сделал, было помещено
using System.Threading;
в начале моего кода поместите
Thread animationThread;
перед всеми основными событиями поставьте
animationThread = new Thread(back2front_card1);
animationThread.Start();
в событии щелчка и поместите все команды box1.Image и delay в это:
public void back2front_card1()
{
}
Это отлично запускает анимацию!