Ein Bug? [gelöst]

Für allgemeine Fragen zur Programmierung mit PureBasic.
es_91
Beiträge: 411
Registriert: 25.01.2011 04:48

Ein Bug? [gelöst]

Beitrag von es_91 »

Hi.

Uns lässt die PB-Hilfe in dem Glauben, die dynamische Gadget-Nummern-Zuweisung sei unique, also einzigartig - jeder Gadget, der dynamisch erstellt wird, habe eine eigene Nummer, die kein anderer Gadget haben kann.

Nun habe ich eben ein Programm geschrieben, in dem genau dieses Paradigma nicht erfüllt wird.

Aber zunächst zu dem Programm: Ich soll Begriffe in einer Netz- oder Baumstruktur ordnen. Dazu habe ich ein Programm geschrieben, dass ich unten gepostet habe. Dieses Programm stellt "Knoten" als Fenster auf dem Desktop dar. Jeder "Knoten" kann Begriffe beinhalten. Wird ein Begriff von mehreren Knoten gehalten, wird dies in allen betroffenen Knoten angezeigt.

Es gibt also eine dynamische Fensterverwaltung (alle Fenster sind "Knoten", bis auf den "Knotenmanager", die in der Struktur NODE in der Liste Nodes() gespeichert werden) und jedes Fenster kann ein "Add Window" aufrufen; ein Fenster, dass das Einbinden neuer Begriffe erlaubt. (Da diese Begriffe in einer csv-Datei gespeichert sind, habe ich Euch mal einen kleinen Ausschnitt der csv-Datei mitgeliefert.)

Im Programm macht sich der Fehler nur dadurch bemerkbar, dass beim Aufruf eines Buttons im Add Window plötzlich das Event eines anderen Buttons getriggert wird - ich dachte, ich sehe nicht richtig!

Hier erstmal das Programm:

Code: Alles auswählen

Structure ENTRY
  word$
  List alsoin$()
EndStructure

Structure NODE
  addwnd.i
  addwndbnone.i
  addwndbntwo.i
  addwndli.i
  bnone.i
  bntwo.i
  H.w
  li.i
  Name$
  Node.i
  ppm.i
  S.i
  wnd.i
  W.w
  X.w
  Y.w
  List Entries.ENTRY()
EndStructure

Global Manager
Global NewList Nodes.NODE()

Procedure FindAlsoIns()
  
  ForEach Nodes()
    
    ForEach Nodes()\Entries()
      
      CurrentNode = ListIndex(Nodes())
      CurrentEntry = ListIndex(Nodes()\Entries())
      ClearList(Nodes()\Entries()\alsoin$())
      Word$ = Nodes()\Entries()\word$
      AlsoIn$ = ""
      ForEach Nodes()
        
        If Not ListIndex(Nodes()) = CurrentNode
          
          ForEach Nodes()\Entries()
            If Nodes()\Entries()\word$ = Word$
              AlsoIn$ + Nodes()\Name$ + ";"
            EndIf
          Next
          
        EndIf
        
      Next
      SelectElement(Nodes(), CurrentNode)
      SelectElement(Nodes()\Entries(), CurrentEntry)
      
      For Index = 0 To CountString(AlsoIn$, ";")
        AddElement(Nodes()\Entries()\alsoin$())
        Nodes()\Entries()\alsoin$() = StringField(AlsoIn$, Index + 1, ";")
      Next
      
    Next
    
  Next
  
EndProcedure

Procedure CreateNewNode(*Node.NODE)
  
  *Node\wnd = OpenWindow(#PB_Any, *Node\X, *Node\Y, *Node\W, *Node\H, *Node\Name$, #PB_Window_MinimizeGadget|#PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_MaximizeGadget, WindowID(Manager))
  *Node\bnone = ButtonGadget(#PB_Any, 0, 0, 100, 20, "Hinzufügen...")
  *Node\bntwo = ButtonGadget(#PB_Any, 100, 0, 80, 20, "Entfernen")
  *Node\li = ListIconGadget(#PB_Any, 0, 20, 240, 300, "Begriff", 100, #PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_FullRowSelect)
  AddGadgetColumn(*Node\li, 1, "auch in", 115)
  
  *Node\ppm = CreatePopupMenu(#PB_Any)
  MenuItem(001, "Kopieren")
  
  ForEach *Node\Entries()
    
    AlsoIn$ = ""
    For Index = 1 To ListSize(*Node\Entries()\alsoin$())
      SelectElement(*Node\Entries()\alsoin$(), Index - 1)
      If AlsoIn$
        AlsoIn$ + "; " + *Node\Entries()\alsoin$()
      Else
        AlsoIn$ + *Node\Entries()\alsoin$()
      EndIf
    Next
    AddGadgetItem(*Node\li, #PB_Any, *Node\Entries()\word$ + Chr(10) + AlsoIn$)
    
  Next
  
  SetWindowState(*Node\wnd, *Node\S)
  
EndProcedure

Procedure AddWindow()
  
;   CurrentNode = ListIndex(Nodes())
;   ForEach Nodes()
;     If IsWindow(Nodes()\addwnd)
;       CloseWindow(Nodes()\addwnd)
;     EndIf
;   Next
;   SelectElement(Nodes(), CurrentNode)
  
  Nodes()\addwnd = OpenWindow(#PB_Any, 0, 0, 600, 360, "Add Window - " + Nodes()\Name$, #PB_Window_SystemMenu|#PB_Window_ScreenCentered|#PB_Window_SizeGadget|#PB_Window_MinimizeGadget|#PB_Window_MaximizeGadget, WindowID(Manager))
  Nodes()\addwndli = ListIconGadget(#PB_Any, 20, 40, 360, 180, "Begriff", 120, #PB_ListIcon_FullRowSelect|#PB_ListIcon_AlwaysShowSelection)
  AddGadgetColumn(Nodes()\addwndli, 1, "in Subkategorie", 120)
  AddGadgetColumn(Nodes()\addwndli, 2, "in Pattern", 120)
  AddGadgetColumn(Nodes()\addwndli, 3, "Zugeordnet", 100)
  Nodes()\addwndbnone = ButtonGadget(#PB_Any, 20, 10, 100, 20, "Liste laden (*.csv)...")
  Nodes()\addwndbntwo = ButtonGadget(#PB_Any, 300, 10, 80, 20, "Auswählen", #PB_Button_Default)
  
EndProcedure

Procedure RemoveEntry()
  
  If Not GetGadgetState(Nodes()\li) = #PB_Any
    SelectElement(Nodes()\Entries(), GetGadgetState(Nodes()\li))
    DeleteElement(Nodes()\Entries())
    RemoveGadgetItem(Nodes()\li, GetGadgetState(Nodes()\li))
    FindAlsoIns()
  EndIf
  
EndProcedure

Manager = OpenWindow(#PB_Any, 5, 5, 200, 80, "Knotenmanager", #PB_Window_SystemMenu|#PB_Window_MinimizeGadget)

Button_Neu = ButtonGadget(#PB_Any, 0, 0, 200, 20, "Neuer Knoten")

;- XML-Datei lesen

Xml = LoadXML(#PB_Any, GetHomeDirectory() + "standard.xml")

If Xml
  
  MainNode = MainXMLNode(Xml)
  ChildNode = ChildXMLNode(MainNode)
  
  While ChildNode
    AddElement(Nodes())
    Nodes()\Node = ChildNode
    
    If ExamineXMLAttributes(ChildNode)
      While NextXMLAttribute(ChildNode)
        Select XMLAttributeName(ChildNode)
          Case "Name"
            Nodes()\Name$ = XMLAttributeValue(ChildNode)
          Case "X"
            Nodes()\X = Val(XMLAttributeValue(ChildNode))
          Case "Y"
            Nodes()\Y = Val(XMLAttributeValue(ChildNode))
          Case "W"
            Nodes()\W = Val(XMLAttributeValue(ChildNode))
          Case "H"
            Nodes()\H = Val(XMLAttributeValue(ChildNode))
          Case "S"
            Nodes()\S = Val(XMLAttributeValue(ChildNode))
        EndSelect
      Wend
    EndIf
    
    EntryNode = ChildXMLNode(ChildNode)
    
    While EntryNode
      AddElement(Nodes()\Entries())
      If ExamineXMLAttributes(EntryNode)
        While NextXMLAttribute(EntryNode)
          Select XMLAttributeName(EntryNode)
            Case "word"
              Nodes()\Entries()\word$ = XMLAttributeValue(EntryNode)
          EndSelect
        Wend
      EndIf
      EntryNode = NextXMLNode(EntryNode)
    Wend
    
    ChildNode = NextXMLNode(ChildNode)
  Wend
  
  FindAlsoIns()
  
  ForEach Nodes()
    
    CreateNewNode(Nodes())
    
  Next
  
EndIf

;-

Repeat
  
  eventid = WaitWindowEvent(#True)
  Select eventid
      
    Case #PB_Event_CloseWindow
      
      If EventWindow() = Manager
        Break
      Else
        ForEach Nodes()
          
          If Nodes()\wnd = EventWindow()
            If MessageRequester("Knoten löschen", "Möchten Sie diesen Knoten und seinen gesammten Inhalt wirklich löschen?", #PB_MessageRequester_YesNoCancel) = #PB_MessageRequester_Yes
              CloseWindow(Nodes()\wnd)
              DeleteElement(Nodes())
              Break
            EndIf
          EndIf
          
          If Nodes()\addwnd = EventWindow()
            CloseWindow(Nodes()\addwnd)
            Break
          EndIf
          
        Next
      EndIf
      
    Case #PB_Event_Gadget
      
      Select EventGadget()
          
        Case Button_Neu
          
          AddElement(Nodes())
          Nodes()\Name$ = InputRequester("Neuer Knoten", "Wie soll der Knoten heißen?", "Neuer Knoten")
          If Nodes()\Name$
            Nodes()\W = 320
            Nodes()\H = 240
            CreateNewNode(Nodes())
          Else
            DeleteElement(Nodes())
          EndIf
          
      EndSelect
      
      ForEach Nodes()
        
        If EventGadget() = Nodes()\addwndbnone
          
          FileName$ = OpenFileRequester("", "", "CSV-Datei (*.csv)|*.csv|Alle Dateien (*.*)|*.*", 0)
          
          If ReadFile(0, FileName$)
            
            While Not Eof(0)
              
              Vorhanden$ = ""
              ReadString$ = ReadString(0)
              
              CurrentNode = ListIndex(Nodes())
              ForEach Nodes()
                
                CurrentEntry = ListIndex(Nodes()\Entries())
                ForEach Nodes()\Entries()
                  
                  If Nodes()\Entries()\word$ = StringField(ReadString$, 4, ";")
                    
                    Vorhanden$ = "zugeordnet"
                    Break
                    
                  EndIf
                  
                Next
                If Not CurrentEntry = #PB_Any
                  SelectElement(Nodes()\Entries(), CurrentEntry)
                EndIf
                
              Next
              If Not CurrentNode = #PB_Any
                SelectElement(Nodes(), CurrentNode)
              EndIf
              
              AddGadgetItem(Nodes()\addwndli, #PB_Any, StringField(ReadString$, 4, ";") + Chr(10) + StringField(ReadString$, 2, ";") + Chr(10) + StringField(ReadString$, 3, ";") + Chr(10) + Vorhanden$)
              
            Wend
            
            CloseFile(0)
            
          EndIf
          Break
          
        ElseIf EventGadget() = Nodes()\addwndbntwo
          
          AddElement(Nodes()\Entries())
          Nodes()\Entries()\word$ = GetGadgetItemText(Nodes()\addwndli, GetGadgetState(Nodes()\addwndli))
          CloseWindow(Nodes()\addwnd)
          AddGadgetItem(Nodes()\li, #PB_Any, Nodes()\Entries()\word$)
          FindAlsoIns()
          Gosub ResetLi
          Break
        
        ElseIf EventGadget() = Nodes()\bnone
          
          AddWindow()
          Break
          
        ElseIf EventGadget() = Nodes()\bntwo
          
          RemoveEntry()
          FindAlsoIns()
          Gosub ResetLi
          Break
          
        ElseIf EventGadget() = Nodes()\li
          
          If EventType() = #PB_EventType_RightClick
            
            DisplayPopupMenu(Nodes()\ppm, WindowID(Nodes()\wnd))
            
          EndIf
          
        EndIf
          
      Next
      
    Case #PB_Event_Menu
      
      Select EventMenu()
          
        Case 001
          
          ClipboardText$ = ""
          For Index = 1 To ListSize(Nodes()\Entries()\alsoin$())
            ClipboardText$ + Nodes()\Entries()\alsoin$()
          Next
          
      EndSelect
      
    Case #PB_Event_SizeWindow
      
      ForEach Nodes()
        
        If Nodes()\wnd = EventWindow()
          
          ResizeGadget(Nodes()\li, 0, 20, WindowWidth(Nodes()\wnd), WindowHeight(Nodes()\wnd) - 20)
          SetGadgetItemAttribute(Nodes()\li, #False, #PB_ListIcon_ColumnWidth, GadgetWidth(Nodes()\li) - 140, 1)
          
        ElseIf Nodes()\addwnd = EventWindow()
          
          If IsGadget(Nodes()\addwndli)
            ResizeGadget(Nodes()\addwndli, 20, 40, WindowWidth(Nodes()\addwnd) - 40, WindowHeight(Nodes()\addwnd) - 60)
          EndIf
          If IsGadget(Nodes()\addwndbntwo)
            ResizeGadget(Nodes()\addwndbntwo, WindowWidth(Nodes()\addwnd) - 100, 10, 80, 20)
          EndIf
          
        EndIf
        
      Next
      
  EndSelect
  
  ForEach Nodes()
    
    Nodes()\S = GetWindowState(Nodes()\wnd)
    If Nodes()\S = #PB_Window_Normal
      Nodes()\X = WindowX(Nodes()\wnd)
      Nodes()\Y = WindowY(Nodes()\wnd)
      Nodes()\W = WindowWidth(Nodes()\wnd)
      Nodes()\H = WindowHeight(Nodes()\wnd)
    EndIf
    
  Next
  
ForEver

;- XML-Datei schreiben

Xml = CreateXML(#PB_Any)
MainNode = CreateXMLNode(RootXMLNode(Xml))
SetXMLNodeName(MainNode, "Nodes")

ForEach Nodes()
  
  Nodes()\Node = CreateXMLNode(MainNode)
  SetXMLNodeName(Nodes()\Node, "Node")
  SetXMLAttribute(Nodes()\Node, "X", Str(Nodes()\X))
  SetXMLAttribute(Nodes()\Node, "Y", Str(Nodes()\Y))
  SetXMLAttribute(Nodes()\Node, "W", Str(Nodes()\W))
  SetXMLAttribute(Nodes()\Node, "H", Str(Nodes()\H))
  SetXMLAttribute(Nodes()\Node, "S", Str(Nodes()\S))
  SetXMLAttribute(Nodes()\Node, "Name", Nodes()\Name$)
  
  ForEach Nodes()\Entries()
    
    EntryNode = CreateXMLNode(Nodes()\Node)
    SetXMLNodeName(EntryNode, "Entry")
    SetXMLAttribute(EntryNode, "word", Nodes()\Entries()\word$)
    
  Next
  
Next

SaveXML(Xml, GetHomeDirectory() + "standard.xml")

;-

End

ResetLi:
CurrentNode = ListIndex(Nodes())
ForEach Nodes()
  ClearGadgetItems(Nodes()\li)
  CurrentEntry = ListIndex(Nodes()\Entries())
  ForEach Nodes()\Entries()
    AlsoIn$ = ""
    For Index = 1 To ListSize(Nodes()\Entries()\alsoin$())
      SelectElement(Nodes()\Entries()\alsoin$(), Index - 1)
      If AlsoIn$
        AlsoIn$ + "; " + Nodes()\Entries()\alsoin$()
      Else
        AlsoIn$ + Nodes()\Entries()\alsoin$()
      EndIf
    Next
    AddGadgetItem(Nodes()\li, #PB_Any, Nodes()\Entries()\word$ + Chr(10) + AlsoIn$)
  Next
  If Not CurrentEntry = #PB_Any
    SelectElement(Nodes()\Entries(), CurrentEntry)
  EndIf
Next
If Not CurrentNode = #PB_Any
  SelectElement(Nodes(), CurrentNode)
EndIf
          
Return
Und beim Klick auf "CSV-Datei laden..." im "Add Window" wird plötzlich folgendes angezeigt:

Bild

Dabei habe ich den entsprechenden Button "Nodes()\addwndbntwo" gar nicht geklickt!

Eine Analyse der dynamisch verteilten Gadget-Nummern im Variablen-Viewer der PB-IDE ergab dann folgende Erkenntniss:

Bild

Wie ganz unten im Bild zu sehen ist hat "Nodes(:1:)\addwndli", das ListIconGadget im "Add Window" des zweiten Knoten, dieselbe Nummer wie "Nodes(:0:)\addwndbntwo", der Hinzufügen-Button im "AddWindow" des ersten Knotens.

Wie kann das sein?

/EDIT: Fehler gefunden. Eine dynamisch erzeugte Gadget-Nummer wird natürlich nur solange vorgehalten, wie der Gadget geöffnet ist. Da die "Add Windows" dynamisch erzeugt und auch gleich wieder geschlossen werden kann eine Doppelbelegung auftreten. Ich muss alle Add Windows im Vorraus erzeugen und dann nur noch dynamisch einblenden.

Sorry für diesen Thread.
Benutzeravatar
Kiffi
Beiträge: 10725
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: Ein Bug? [gelöst]

Beitrag von Kiffi »

habe jetzt mehrfach Fenster geöffnet, 'CSV laden' angeklickt, CSV geladen, Einträge selektiert, Fenster geschlossen...

Bei mir tritt der von Dir genannte Fehler nicht auf.

Grüße ... Kiffi
a²+b²=mc²
es_91
Beiträge: 411
Registriert: 25.01.2011 04:48

Re: Ein Bug? [gelöst]

Beitrag von es_91 »

Nun, es scheint ein Zufallsspiel zu sein. Nur unter bestimmten Systemvorraussetzungen verwendet PureBasic die bereits wieder abgegebenen Gadget-Nummern erneut. Weiteres kann ich dazu aber nicht sagen, ich habe davon auch keine Ahnung.
Antworten