Почему Tmediaplayer задерживает заголовок, изменяющийся на TPanel? -- delphi поле с участием media-player пол Связанный проблема

why does tmediaplayer delay a caption changing on a tpanel?


5
vote

проблема

русский

Я начинающий программист, поэтому извиняюсь, если это звучит очень простой для вас. У меня есть процедура, которая выглядит (по существу), как это:

 <код> procedure TForm1.BitBtn1Click(Sender: TObject); begin   panel1.caption:='This is a sentence';   with MediaPlayer1 do   begin     filename:='f:untitled.wma';     open;     wait:=true;     play;     close;   end; end;   

Проблема в том, что подпись на <код> panel1 не меняется до тех пор, пока медиаплайзер не сыграет звуковой файл; Мне нужна подпись, чтобы изменить, и игрок начать играть, одновременно. Как я могу это обеспечить это?

Я думал, что процедура выполнит каждую строку кода последовательно, что означает, что заголовок panel1 изменяется, а затем медиаплайвером, поднявшись в действие. Где я ошибся?

Английский оригинал

I am a novice programmer, so apologies if this sounds very basic to you all. I have a procedure which looks (essentially) like this:

procedure TForm1.BitBtn1Click(Sender: TObject); begin   panel1.caption:='This is a sentence';   with MediaPlayer1 do   begin     filename:='f:untitled.wma';     open;     wait:=true;     play;     close;   end; end; 

The problem is that the caption on panel1 doesn't change until the mediaplayer has played the sound file; I need the caption to change, and the player to start playing, simultaneously. How can I ensure this?

I thought that the procedure would execute each line of code sequentially, meaning that the caption of panel1 changes, followed by the mediaplayer springing into action. Where have I gone wrong?

</div
     

Список ответов

2
 
vote
vote
Лучший ответ
 

Добавить <код> 0.54 call после настройки заготовки, то есть.:

 <код> 0.55  
 

Add a Refresh call after setting the caption, i.e.:

panel1.caption:='This is a sentence';  Refresh; 
</div
 
 
     
     
10
 
vote

Объяснение:

компоненты VCL (например, <код> TPanel ), как правило, имеют внутренний метод, называемый <код> Invalidate() , который вызывается, когда свойство (например, <код> Caption ) меняется и что изменение требует перекраски часть управления (например, для начертить новый текст заголовка).

<Р> Этот метод только устанавливает флаг внутри элемента управления окна, но не вызывает сам метод перекрашивать. Причиной этого является избежать вызова <код> Repaint() метод несколько раз, если многие свойства изменяются сразу (последовательно, в течение короткого времени). <Р> <код> Repaint() метод фактически вызываются, когда компонент принимает сообщение перекрашивать через главный цикл обработки сообщений (перерабатываемый из главного потока приложения - графический интерфейс резьбы). <Р> То, как вы начинаете играть медиа-плеер блокирует, потому что вы установите <код> Wait свойство <код> True , который позволяет игроку блокировать вызывающую нить (опять же главная нить ), пока файл не будет воспроизводиться. <Р> Это не дает возможность в основной поток, чтобы обработать его в очередь сообщений и инициировать перерисовку.

Быстрое решение:

<Р> Быстрое исправление этой проблемы является либо один предложенный becsystems, или это один:
 <код> panel1.Caption := 'This is a sentence'; Application.ProcessMessages();   
<Р> Вызов <код> ProcessMessages() даст главному потоку возможность обработки очереди сообщений и выполнить обновление, перед началом воспроизведения файла. <Р> Это быстрое решение, так как основной поток по-прежнему будет заблокирован после начала игры, которая позволит предотвратить другие части окна перекрасить (например. Попробуйте переместить окно вокруг или минимизации и максимизации его во время игры). < / р> <Р> Код предложил becsystems аналогично, но вместо обработки очереди сообщений, просто вынуждает управление перекрашивать.

Правильное исправление:

<Р> Для того, чтобы правильно решить эту проблему, вы не должны использовать <код> Wait <код /> свойства и вместо того, чтобы обрабатывать <код> Invalidate()0 событие медиаплеера. <Р> Ниже приведен пример, адаптированный из Швейцарский Дельфи центр (< EM> не проверял, как я не Delphi установлен на данный момент ):
 <код> Invalidate()1  

Боковые примечания:

<Р> Существует краткое объяснение цикла VCL сообщений (часть Руководства разработчика Delphi) опубликовано здесь:
<Р> Анатомия системы сообщений: VCL < / р>
<Р> Кроме того, не имеет отношения к этой проблеме, но взгляните на Delphi Coding Guide Стиль . Это просто приятно, когда код Размещенное отформатированный.
 

Explanation:

VCL components (like TPanel) usually have an internal method called Invalidate() that is called when a property (like Caption) changes and that change requires repainting part of the control (eg. to draw the new caption text).

This method only sets a flag inside the window control, but does not invoke the repaint method itself. The reason for that is to avoid calling the Repaint() method multiple times, if many properties are changed at once (sequentially, in short time).

The Repaint() method is actually called when the component receives a message to repaint via the main message loop (processed from the main thread of the application - the GUI thread).

The way you start playing the media player is blocking, because you set the Wait property to True, which makes the player block the calling thread (again the main thread) until the file has been played.

This does not give a chance to the main thread to process it's message queue and initiate the repaint.

Quick fix:

A quick fix to the problem is either the one suggested by becsystems, or this one:

panel1.Caption := 'This is a sentence'; Application.ProcessMessages(); 

Calling ProcessMessages() will give the main thread the opportunity to process the message queue and perform the update, just before starting to play the file.

This is a quick fix, as the main thread will still be blocked after starting to play, which will prevent other portions of the window to repaint (eg. Try moving the window around or minimizing and maximizing it while playing).

The code suggested by becsystems is similar, but instead of processing the message queue, just forces the control to repaint.

Proper fix:

To properly fix the problem you should not use the Wait property and instead handle the OnNotify event of the media player.

Here is an example, adapted from Swiss Delphi Center (not tested as I do not have Delphi installed at the moment):

procedure TForm1.BitBtn1Click(Sender: TObject); begin   panel1.Caption := 'This is a sentence';   with MediaPlayer1 do   begin     Notify := True;     OnNotify := NotifyProc;     Filename := 'f:untitled.wma';     Open;     Play;   end; end;  procedure TForm1.NotifyProc(Sender: TObject); begin   with Sender as TMediaPlayer do    begin     case Mode of       mpStopped: {do something here};     end;      // Set to true to enable next-time notification     Notify := True;   end; end; 

Side notes:

There is a short explanation of the VCL message loop (part of Delphi Developer's Guide) published here:

Anatomy of a Message System: VCL

Also, not related to the problem, but take a look at Delphi Coding Style Guide. It's just nice when code posted is formatted.

</div
 
 
   
   

Связанный проблема

3  Как обнаружить прекращение программы в Android?  ( How to detect the termination of a program in android ) 
Когда программа Windows заканчивает ее, вызывает обработчики событий, такие как наклонная, ондеровская и разрушитель разрушитель. Когда я хочу сохранить некот...

1  ЮНА-Mapping Delphi Функция  ( Jna mapping delphi function ) 
<Р> Как я отобразить эту функцию с ЮНА: <Р> Delphi код: <код> function getData(InData1: PChar; InData2: PChar; Data: TAr...

3  Прошедшая первая база с пунктами TortoiseSVN  ( Getting past first base with tortoisesvn ) 
Хорошо, я был убежден, что SVN - это способ пойти в предыдущая публикация , но я еще не видел эпопания. Я не уверен, как я устанавливаю подрыв для моей среды...

16  С каким кодом Delphi я должен заменить мои звонки в устаревший метод Thhread Suspend?  ( With what delphi code should i replace my calls to deprecated tthread method sus ) 
Это спросило раньше, но Без полного ответа . Это связано с так называемой известной «роковой резьбой»! ». Мне нужно заменить этот вызов tthread.suspend с ч...

0  Delphi: Показать назначенный кадр к узлу вида дерева  ( Delphi show assigned frame to node of tree view ) 
У меня нет опыта с кадрами. Как использовать вид дерева с кадрами? Мне нужно переключиться среди кивок вида дерева и показать назначенный кадр на выбранный ...

0  Delphi VCL: Элементы формы не указаны на пользовательской процедуре / функции  ( Delphi vcl form elements undeclared on custom procedure function ) 
У меня есть это: <код> procedure Welcome(user: string; accesslevel: integer); begin if accesslevel>= 10 then btCustomers.Text = 'Customer overview'; end...

0  Delphi FMX Hanvas Alpha Channel Дает неправильную прозрачность  ( Delphi fmx canvas alpha channel give wrong transparency ) 
Я хочу добавить прозрачные и частично прозрачные области на изображении .bitmap. Я обнаружил, что регионы прозрачности не влияют, как и ожидалось: Части RGB т...

1  Delphi: Воспроизвести файл MP4 с помощью DSPack  ( Delphi play mp4 file using dspack ) 
Я играю вокруг с dspack, он может играть в файлы AVI и WMV, но он не играет файлов MP4. Я установил FFDShow Codec, но все же он не будет играть любой другой ф...

5  Delphi - пытаясь получить Stacktrace для исключения  ( Delphi trying to get stacktrace for an exception ) 
У меня есть регистратор исключения, который регистрирует все исключения в файл журнала: <код> class function TLogger.LogException (ACaller: String; E: Excep...

2  Сервер отдыха, Delphi и Web Services - необходимо совет  ( Rest server delphi and web services advice needed ) 
Я смотрю на совет о том, как лучше подходить к новому проекту, мне нужно развивать. С самого начала я должен добавить, у меня есть 0 опыт работы с веб-разрабо...

5  Delphi Удалить Форма Тень  ( Delphi remove form shadow ) 
Я использую Delphi Berlin, у меня есть основная форма, и я открываю другие формы из главного меню в моей основной форме, я не использую Forms MDI Я хочу отк...

2  Не может выполнить эту операцию на закрытом наборе данных  ( Cannot perform this operation on a closed dataset ) 
Я просто пытаюсь выполнить оператор SQL Selection SQL с помощью компонента TADOQUERY, но когда запись «Open» TaDoQuery выполняется, я получаю последую ошибки:...

35  Насколько тяжело мигрировать проект из Delphi 7 в Delphi Xe?  ( How hard is it to migrate a project from delphi 7 to delphi xe ) 
У нашей компании есть программное обеспечение, которое было в разработке более 10 лет, поэтому там есть некоторые действительно встречающиеся там. Это все еще ...

11  Не могу удалить элементы управления в Delphi Xe7  ( Cant delete controls in delphi xe7 ) 
Просто установил delphi xe7. Открыл проект, разработанный с XE7. Боковая заметка, но моя первая озабоченность заключается в том, что все заставляет IDE вешать...

117  Узнайте, какой процесс зарегистрировал глобальную горячую клавишу? (Windows API)  ( Find out what process registered a global hotkey windows api ) 
Насколько мне удалось выяснить, Windows не предлагает функцию API, чтобы сказать, какое приложение зарегистрировало глобальную горячую клавишу (через Register...

Связанный проблема

3  Как обнаружить прекращение программы в Android? 
1  ЮНА-Mapping Delphi Функция 
3  Прошедшая первая база с пунктами TortoiseSVN 
16  С каким кодом Delphi я должен заменить мои звонки в устаревший метод Thhread Suspend? 
0  Delphi: Показать назначенный кадр к узлу вида дерева 
0  Delphi VCL: Элементы формы не указаны на пользовательской процедуре / функции 
0  Delphi FMX Hanvas Alpha Channel Дает неправильную прозрачность 
1  Delphi: Воспроизвести файл MP4 с помощью DSPack 
5  Delphi - пытаясь получить Stacktrace для исключения 
2  Сервер отдыха, Delphi и Web Services - необходимо совет 
5  Delphi Удалить Форма Тень 
2  Не может выполнить эту операцию на закрытом наборе данных 
35  Насколько тяжело мигрировать проект из Delphi 7 в Delphi Xe? 
11  Не могу удалить элементы управления в Delphi Xe7 
117  Узнайте, какой процесс зарегистрировал глобальную горячую клавишу? (Windows API)