window mit gadgets und windowedscreen

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

window mit gadgets und windowedscreen

Beitrag von #NULL »

das problem: window mit gadgets und einem windowedscreen --> die gui bzw die eventbearbeitung hakt.

aufgrund dieses forum-threads:
http://www.purebasic.fr/german/viewtopi ... highlight=
habe ich mal probiert geöhnliche pb-gadgets aus dem hauptprogramm in einen thread auszulagern. dabei scheint die gui ganz gut zu reagieren.
zum testen mit last werden einfach ein paar sprites pro frame angezeigt. bzw man kann auf 'recreate buttons' clicken um die buttons neu zu erstellen, was auch recht gut geht (ohne thread müsste man meist zugucken wie die einzelnen buttons langsam nacheinander erscheinen)

ich war überrascht das es so einfach ist und funktioniert, deshalb poste ich es hier. ist natürlich nur ein test. vielleicht sieht es in wirklicher anwendung schon wieder anders aus, zumal ca. 40 buttons und ein paar sprites anzeigen nicht viel ist. auch bin ich nicht sehr erfahren mit threads; vielleicht hat da jemand noch ideen.

Code: Alles auswählen

EnableExplicit

Global ww,wh,quit,gui_ready
Define n


Procedure gui_thread(param)
  Protected style,hwin,i,k,event,em,eg
  ww=800
  wh=600
  style | #PB_Window_ScreenCentered
  style | #PB_Window_SystemMenu
  style | #PB_Window_MinimizeGadget
  hWin=OpenWindow(0, 50,100,ww+200,wh, "",style) :: AddKeyboardShortcut(0,#PB_Shortcut_Escape,10)
  OpenWindowedScreen( hWin, 200,0,ww,wh, 0,0,0)
  Dim butt(1,22)
  For i=0 To 1
    For k=0 To 22
      butt(i,k) = ButtonGadget(#PB_Any, 5+i*100, 5+k*25, 90,20, "Button "+Str(i)+","+Str(k) )
    Next
  Next
  ButtonGadget(0, 5, 5+k*25, 190,20, "recreate buttons")
  
  gui_ready = #True
  
  Repeat
    event=WaitWindowEvent(30)
    em=EventMenu()
    eg=EventGadget()
    Select event
      Case #PB_Event_CloseWindow
        quit=1
      Case #PB_Event_Menu
        Select em
        Case 10
          quit=1
        EndSelect
      Case #PB_Event_Gadget
        Select eg
          Case 0 ; recreate buttons
            For i=0 To 1
              For k=0 To 22
                FreeGadget(butt(i,k))
                butt(i,k) = ButtonGadget(#PB_Any, 5+i*100, 5+k*25, 90,20, "Button "+Str(i)+","+Str(k) )
              Next
            Next
            ButtonGadget(0, 5, 5+k*25, 190,20, "recreate buttons")
          Default
            For i=0 To 1
              For k=0 To 22
                If eg = butt(i,k)
                  MessageRequester("gadget event","Button "+Str(i)+","+Str(k)+" clicked")
                EndIf
              Next
            Next
        EndSelect
    EndSelect
  Until quit
EndProcedure

InitSprite()

CreateThread(@gui_thread(),0)
While Not gui_ready
  Delay(10)
wend

LoadSprite(0,#PB_Compiler_Home+"Examples\Sources\Data\GeeBee2.bmp")
TransparentSpriteColor(0,$ff00ff)

Repeat
  For n=0 To 200
    DisplayTransparentSprite(0,Random(ww),Random(wh))
  Next
  FlipBuffers()
  ClearScreen($333333)
Until quit
my pb stuff..
Bild..jedenfalls war das mal so.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

> das problem: window mit gadgets und einem windowedscreen --> die gui bzw die eventbearbeitung hakt.

tschuldigung, Kollege, diese These möchte ich doch erstmal hinterfragen.
wie sieht denn deine GUI-Event-Bearbeitung aus, dass die hakt?
ist jetzt das erste Mal dass ich von so einem Problem höre...

das selbe Window in verschiedenen Threads zu beackern ist immer eine Einladung an Schwierigkeiten,
deswegen würde ich darauf soweit als möglich verzichten wollen.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

ich konnte mich bisher einfach noch nicht damit anfreunden in einem frame alle window-events in einer zusätzlichen (geschachtelten) schleife abzuarbeiten weil ich befürchtete das die belastung dieses codeteil zu stark variieren könnte (zum beispiel beim erstellen neuer gadgets) und somit die hauptschleife weniger flüsig läuft wenn viele events auf einmal eintreffen.

vielleicht liege ich da aber auch falsch.

>> das selbe Window in verschiedenen Threads zu beackern

das geht glaube ich gar nicht direkt. man sollte dann außerhalb des threads nur auf informationen/variablen reagieren, die man im thread selbst setzt und andersherum. dabei gilt natürlich die generelle vorsicht beim verwenden mit threads.
my pb stuff..
Bild..jedenfalls war das mal so.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

> ich konnte mich bisher einfach noch nicht damit anfreunden in einem frame
> alle window-events in einer zusätzlichen (geschachtelten) schleife abzuarbeiten

dann probier es einfach mal.
mir war die Vorstellung zuerst auch gruselig, aber die Funktionalität ist überzeugend.

Code: Alles auswählen

InitSprite()
;InitMouse()
InitKeyboard()

Enumeration 
  #But_Close
  #Str_Input
  #But_Input
  #But_Erase
  #Frame_Screen
EndEnumeration

; **********************

OpenWindow( 0, 0,0, 800,600, "Gadget by Screen Demo" )
  OpenWindowedScreen( WindowID(0), 160, 120, 480, 360, 0, 160, 120 )
  ButtonGadget( #But_Close,   8,   8,  64,  44, "Zua" )
  StringGadget( #Str_Input, 648, 128, 144,  32, "Data" )
  ButtonGadget( #But_Input, 648, 168, 144,  32, "Input" )
  ButtonGadget( #But_Erase, 648, 208, 144,  32, "Erase" )
  Frame3DGadget( #Frame_Screen, 159, 119, 482, 362, "", #PB_Frame3D_Double )

; **********************

CreateSprite( 0, 63, 63 )
StartDrawing( SpriteOutput( 0 ) )
  Line( 30,  0,  0, 63, $0FF0FF )
  Line( 32,  0,  0, 63, $0FF0FF )
  Line(  0, 30, 63,  0, $0FF0FF )
  Line(  0, 32, 63,  0, $0FF0FF )
  DrawingMode( #PB_2DDrawing_Outlined )
  Circle( 31, 31, 31, $0FF0FF )
StopDrawing()

; **********************

Repeat
  Repeat
    Event = WaitWindowEvent(10)
    EvGad = EventGadget()
    Select Event
      Case #PB_Event_CloseWindow
        EXIT = 1
      Case #PB_Event_Gadget
        Select EvGad
          Case #But_Input
            Text$ = GetGadgetText( #Str_Input )
            TextFlag = 1
          Case #But_Erase
            TextFlag = 0
          Case #But_Close
            EXIT = 1
        EndSelect
    EndSelect
  Until Event = #Null

  MX = WindowMouseX( 0 )
  MY = WindowMouseY( 0 )

  ClearScreen( $201008 )
    If TextFlag
      StartDrawing( ScreenOutput() )
        DrawingMode( #PB_2DDrawing_Transparent )
        DrawText( 16, 16, Text$, $0AA0AA )
      StopDrawing()
    EndIf
    DisplayTransparentSprite( 0, MX * 480 / 800 - 31, MY * 360 / 600 - 31 )
  FlipBuffers( #PB_Screen_SmartSynchronization )
Until EXIT
> das geht glaube ich gar nicht direkt. man sollte dann außerhalb des threads
> nur auf informationen/variablen reagieren, die man im thread selbst setzt und andersherum.
> dabei gilt natürlich die generelle vorsicht beim verwenden mit threads.

wie willst du das denn dann überhaupt lösen?
DX Commands sollten auch nicht inerhalb von Threads benutzt werden...
Den WindowedScreen musst du ja aber wohl im selben Thread erstellen wie das Fenster, oder?
oder kann man den außerhalb erstellen und das Fenster innerhalb?

ehrlich gesagt, die idee ist mir um Aonen gruseliger als zwei geschachtelte Schleifen...
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

bist dabei mich zu überzeugen :D

dein beispiel hakt bei mir auch zwar fürchterlich (der cursor bewegt sich nur im sekunden takt), aber das liegt lediglich am WaitWindowEvent(10). mit einem wert von 0 oder mit WindowEvent() läuft es ganz flüssig.
ich hatte das gleiche parallel auch gerade bei meinem code probiert und es funzt:

Code: Alles auswählen

EnableExplicit

Define ww,wh,quit,gui_ready
Define n


InitSprite()

Define  style,hwin,i,k,event,em,eg
ww=800
wh=600
style | #PB_Window_ScreenCentered
style | #PB_Window_SystemMenu
style | #PB_Window_MinimizeGadget
hWin=OpenWindow(0, 50,100,ww+200,wh, "",style) :: AddKeyboardShortcut(0,#PB_Shortcut_Escape,10)
OpenWindowedScreen( hWin, 200,0,ww,wh, 0,0,0)
Dim butt(1,22)
For i=0 To 1
  For k=0 To 22
    butt(i,k) = ButtonGadget(#PB_Any, 5+i*100, 5+k*25, 90,20, "Button "+Str(i)+","+Str(k) )
  Next
Next
ButtonGadget(0, 5, 5+k*25, 190,20, "recreate buttons")



LoadSprite(0,#PB_Compiler_Home+"Examples\Sources\Data\GeeBee2.bmp")
TransparentSpriteColor(0,$ff00ff)

Repeat
  
  Repeat
    event=WindowEvent()
    em=EventMenu()
    eg=EventGadget()
    Select event
      Case #PB_Event_CloseWindow
        quit=1
      Case #PB_Event_Menu
        Select em
        Case 10
          quit=1
        EndSelect
      Case #PB_Event_Gadget
        Select eg
          Case 0 ; recreate buttons
            For i=0 To 1
              For k=0 To 22
                FreeGadget(butt(i,k))
                butt(i,k) = ButtonGadget(#PB_Any, 5+i*100, 5+k*25, 90,20, "Button "+Str(i)+","+Str(k) )
              Next
            Next
            ButtonGadget(0, 5, 5+k*25, 190,20, "recreate buttons")
          Default
            For i=0 To 1
              For k=0 To 22
                If eg = butt(i,k)
                  MessageRequester("gadget event","Button "+Str(i)+","+Str(k)+" clicked")
                EndIf
              Next
            Next
        EndSelect
    EndSelect
  Until Not event
  
  
  ClearScreen($333333)
  
  For n=0 To 200
    DisplayTransparentSprite(0,Random(ww),Random(wh))
  Next
  FlipBuffers()
Until quit
my pb stuff..
Bild..jedenfalls war das mal so.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

das ist wirklich sehr merkwürdig, denn WaitWindowEvent(10) kann kein hakeln verursachen:
wenn ein Event anliegt, wird nicht gewartet.

wie alt ist denn deine Maschine?

ich hab gestern die Erfahrung gemacht, auf einem 800MHz mit einer MatroxMillennium (old old grafix),
dass ein Autostretchter WindowedScreen das Verschieben des Fensters extrem schwammig macht.
bei 1:1 geht es gerade noch so.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

>> wie alt ist denn deine Maschine?

etwa 3 jahre vielleicht, weiß nicht genau.
<Win> + <Pause> hat geschrieben:AMD Athlon 64
3000+
2.01GHz, 960 MB RAM
>> wenn ein Event anliegt, wird nicht gewartet.

richtig, aber immer im sozusagen letzten durchlauf der event schleife, bei dem sich Event am ende als 0 heraustellen wird, wartet WaitWindowEvent() um den timeout-wert, eben weil kein event in der queue war. der event-teil der hauptschleife (also die event-schleife samt allen durchgängen) wird also immer mindestens diesen timeout dauern.
versuch mal mit einem timeout von 100 oder höher, vielleicht geht das dann auch bei dir so.
my pb stuff..
Bild..jedenfalls war das mal so.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

aye, du hast ja recht Bild

... aber bei deinem Beispiel komme ich bei einer Messung über 1000 Frames trotzdem nur auf einen Schnitt von 16ms...
schätze mal, dass das an meinen 60Hz liegt.

diese 60Hz sind praktisch in stein gemeißelt, solange ich nicht irgendwas kalkuliere, was ab und zu mal frei refreshs frisst.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
#NULL
Beiträge: 2238
Registriert: 20.04.2006 09:50

Beitrag von #NULL »

versteh ich nicht ganz. probier mal so:

Code: Alles auswählen

;..
OpenWindowedScreen( hWin, 200,0,ww,wh, 0,0,0)
SetFrameRate(999)
;..

  ;..
  ;ClearScreen($333333)
 
  For n=0 To 200
    ;DisplayTransparentSprite(0,Random(ww),Random(wh))
  Next
  FlipBuffers(0)
  ;..
my pb stuff..
Bild..jedenfalls war das mal so.
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

interessant...
das NoSync alleine nützt nichts, er bleibt trotzdem bei 60Hz,
aber wenn ich 1000 vorgebe, flitzt er wirklich so schnell er kann...

wußte ich auch noch nicht, ich dachte, NoSync alleine würde es schon raushaun...

wenn ich das SetFrameRate auskommentiere, komme ich auf ø16.5

Code: Alles auswählen

EnableExplicit

Define ww,wh,quit,gui_ready
Define n, Timer, Count, Count2
Define Mess.d

InitSprite()

Define  style,hwin,i,k,event,em,eg
ww=800
wh=600
style | #PB_Window_ScreenCentered
style | #PB_Window_SystemMenu
style | #PB_Window_MinimizeGadget
hWin=OpenWindow(0, 50,100,ww+200,wh, "",style) :: AddKeyboardShortcut(0,#PB_Shortcut_Escape,10)
OpenWindowedScreen( hWin, 200,0,ww,wh, 0,0,0)
Dim butt(1,22)
For i=0 To 1
  For k=0 To 22
    butt(i,k) = ButtonGadget(#PB_Any, 5+i*100, 5+k*25, 90,20, "Button "+Str(i)+","+Str(k) )
  Next
Next
ButtonGadget(0, 5, 5+k*25, 190,20, "recreate buttons")



LoadSprite(0,#PB_Compiler_Home+"Examples\Sources\Data\GeeBee2.bmp")
TransparentSpriteColor(0,$ff00ff)

SetFrameRate(1000)
Timer = ElapsedMilliseconds()

Repeat
 
  Repeat
    event=WindowEvent()
    em=EventMenu()
    eg=EventGadget()
    Select event
      Case #PB_Event_CloseWindow
        quit=1
      Case #PB_Event_Menu
        Select em
        Case 10
          quit=1
        EndSelect
      Case #PB_Event_Gadget
        Select eg
          Case 0 ; recreate buttons
            For i=0 To 1
              For k=0 To 22
                FreeGadget(butt(i,k))
                butt(i,k) = ButtonGadget(#PB_Any, 5+i*100, 5+k*25, 90,20, "Button "+Str(i)+","+Str(k) )
              Next
            Next
            ButtonGadget(0, 5, 5+k*25, 190,20, "recreate buttons")
          Default
            For i=0 To 1
              For k=0 To 22
                If eg = butt(i,k)
                  MessageRequester("gadget event","Button "+Str(i)+","+Str(k)+" clicked")
                EndIf
              Next
            Next
        EndSelect
    EndSelect
  Until Not event

  ClearScreen($333333)

  For n=0 To 200
    DisplayTransparentSprite(0,Random(ww),Random(wh))
  Next
  FlipBuffers(0)

  Count +1
  If Count = 1000
    Count  = 0
    Count2 +1
    Mess = - ( Timer - ElapsedMilliseconds() ) / 1000
    SetWindowTitle( 0, Str(Count2) +" : "+ StrD(Mess,3) )
    Timer = ElapsedMilliseconds()
  EndIf
Until quit
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Antworten