PureBasic - форум

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Обновление строки состояния


Обновление строки состояния

Сообщений 1 страница 6 из 6

1

Ранее в некоторых программах у меня при нажатии на кнопку начинался процесс обработки данных, а окно зависало и я не мог понять как от этого избавиться, и также для обновления строки состояния я делал операцию в отдельном потоке, при этом для Linux это не работало. Хотя тот же AutoIt3 не имел такой проблемы, окно не висло и строка состояния обновлялась.
В итоге попал на тему "Window not responding after a few seconds" - "Окно не отвечает через несколько секунд":
https://www.purebasic.fr/english/viewtopic.php?t=81399
где Фред предлагает просто вызвать WindowEvent(). То есть функция позволит окну получить системные события. Я ещё не тестировал, но я сразу понял смысл этого сообщения, то есть в тех местах где необходимо вставить функцию обновления строки состояния надо вызвать WindowEvent(), то есть не получая событий окно обновит все свои состояния (мышь, калбэки и т.д.)
При этом если функция выполняется долго, где то через минуту окно будет показывать что оно зависло, то ориентируясь по времени можно в выполняемой функции вызвать WindowEvent(), чтобы не дать окну зависнуть. При этом в отличии от WaitWindowEvent() фунцкия WindowEvent() не будет вставлять задержки делая цикл медленным (в вызванной процедуре по кнопке)

Но ведь нигде в примерах справки раздела "StatusBar" этого нет. То есть фактически нет примера нормальной работы длительной операции с выводом результатов в строку состояния.

0

2

AZJIO написал(а):

при нажатии на кнопку начинался процесс обработки данных, а окно зависало и я не мог понять как от этого избавиться

Если обработка занимает много времени, целесообразно вынести код в отдельный поток. Тогда окно виснуть не будет.

AZJIO написал(а):

я делал операцию в отдельном потоке, при этом для Linux это не работало.

В Linux нормально работают потоки, главное не вызывать из них функции взаимодействия с GUI. Если это нужно, можно функцией PostMessage отправить сообщение основному потоку.

AZJIO написал(а):

Фред предлагает просто вызвать WindowEvent().

Нужно не только ее вызывать, но и обрабатывать все события что возвращает функция, иначе они будут потеряны.
И нужно следить чтобы в процессе вызова WindowEvent() не была рекурсивно вызвана та же процедура из которой вызывается WindowEvent().

AZJIO написал(а):

Но ведь нигде в примерах справки раздела "StatusBar" этого нет.

Потому что это не имеет прямого отношения к строке состояния. Нужно обрабатывать события окна, а строка состояния это часть окна так же как меню, гаджеты и т. д.

0

3

Пётр

Потому что это не имеет прямого отношения к строке состояния

Хорошо, попробую PostEvent() использовать. Но примеры в разделе справки "StatusBar" липовые, они не показывают как действительно сообщать пользователю о состоянии работающего процесса вычисления. В текстовых редакторах есть инфа в ком-строке и даже избыточная, но часто она не интересна, а вот следить за прогрессом некой длительной обработки файлов вполне полезно.

0

4

AZJIO
У вас, как обычно, представления о том как работают операционные системы и программы в них ЛИПОВЫЕ. Большинство вопросов возникает именно по этой причине.
В примерах ни кто не ставил задачи отображать что то, что происходит в другом потоке. Для того, кто понимает как всё устроено попытка из другого потка вызывать чужие GUI-шные функции равносильно бреду. Для этого есть куча способов передачи информации в поток отвечающий за пользовательский интерфейс.

0

5

useful
Вы как всегда после драки начинаете кулаками махать. Вы просто присоединяетесь к уже ответившим специалистам, но сами решения никогда не даете. Так и я умею, но не хочу. Я уже понял вашу позицию, когда-то где то вы ответили на форуме, что бесплатно даже не сдвинетесь даже пальцем не пошевелите, тогда как специалисты спокойно выкладывают на ходу готовые примеры написаные прямо сейчас и дают ссылки на свои модули, то есть спокойно шевелятся бесплатно.

0

6

AZJIO написал(а):

Но примеры в разделе справки "StatusBar" липовые, они не показывают как действительно сообщать пользователю о состоянии работающего процесса вычисления.

Если посмотреть пример в справке переведенной на русский, то да, окно виснет на время пока события не обрабатываются

Код:
If OpenWindow(0, 0, 0, 340, 50, "StatusBarProgress", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  If CreateStatusBar(0, WindowID(0))
    AddStatusBarField(170)
    AddStatusBarField(170)
  EndIf
  
  StatusBarText(0, 0, "Поступление 100 000$!")
  For q=5 To 90
    StatusBarProgress(0, 1, q)
    Delay(30)
  Next q
  StatusBarText(0, 0, "Ошибка связи!")
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

Если его переделать под использование таймера

Код:
Procedure Timer()
  Static q=5
  StatusBarProgress(0, 1, q)
  q+1
  If q>90
    StatusBarText(0, 0, "Ошибка связи!")
    RemoveWindowTimer(0, 0)
    UnbindEvent(#PB_Event_Timer, @Timer(), 0, 0)
  EndIf
EndProcedure

If OpenWindow(0, 0, 0, 340, 50, "StatusBarProgress", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  If CreateStatusBar(0, WindowID(0))
    AddStatusBarField(170)
    AddStatusBarField(170)
  EndIf
  
  StatusBarText(0, 0, "Поступление 100 000$!")
  AddWindowTimer(0, 0, 30)
  BindEvent(#PB_Event_Timer, @Timer(), 0, 0)
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIff

или поток

Код:
CompilerIf #PB_Compiler_Thread=0
  CompilerError "Включите поддержку многопоточности"
CompilerEndIf

Enumeration #PB_Event_FirstCustomValue
  #Event_Thread
EndEnumeration

Enumeration
  #Type_Pos
  #Type_Err
EndEnumeration

Procedure Thread(x)
  For q=5 To 90
    PostEvent(#Event_Thread, 0, #Type_Pos, 0, q)
    Delay(30)
  Next q
  PostEvent(#Event_Thread, 0, #Type_Err)
EndProcedure

Procedure ThreadEvent()
  Select EventGadget()
    Case #Type_Pos
      StatusBarProgress(0, 1, EventData())
    Case #Type_Err
      StatusBarText(0, 0, "Ошибка связи!")
  EndSelect
EndProcedure

If OpenWindow(0, 0, 0, 340, 50, "StatusBarProgress", #PB_Window_SystemMenu | #PB_Window_ScreenCentered | #PB_Window_SizeGadget)
  If CreateStatusBar(0, WindowID(0))
    AddStatusBarField(170)
    AddStatusBarField(170)
  EndIf
  
  StatusBarText(0, 0, "Поступление 100 000$!")
  BindEvent(#Event_Thread, @ThreadEvent(), 0)
  CreateThread(@Thread(), 0)
  
  Repeat
  Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

тогда ничего не виснет и нормально работает в том числе в Linux.

0


Вы здесь » PureBasic - форум » Вопросы по PureBasic » Обновление строки состояния