Tab-Menü über Schleife erstellen lassen

  • Hallo zusammen!

    Ich hänge mal wieder an einem Problem fest, und zwar möchte ich ein Tab-Menü über eine Schleife erstellen und füllen lassen. Das Tab-Menü wird auch ganz normal erstellt und angezeigt, allerdings deren Inhalte nicht. In den Tabs sollen nur Edit-Felder mit einem Inhalt erscheinen. Die Tabs dienen quasi nur zur Information. Im Klartext sieht das Ganze so aus:

    Code
    ; RAW-Export
    Local $hRAWExportGUI = GUICreate( "", 600, 400, 0, 0, $WS_CHILD, Default, $hGUI)
    GUICtrlCreateLabel( "RAW-Export", 10, 10, 200, 23)
    GUICtrlSetFont( -1, 12, 400, 0, "Calibri" )
    Local $idAmount = GUICtrlCreateLabel( "", 10, 40, 200, 40 )
    Local $idExportAllBtn = GUICtrlCreateButton("Export all", 515, 10, 75, 25)
    Local $hRAWExportTab = GUICtrlCreateTab( 10, 80, 580, 280 )
    GUICtrlCreateTabItem( "" )
    Local $idCancelRAWExportBtn = GUICtrlCreateButton( "Cancel", 270, 365, 75, 25 )

    zuerst wird das GUI dazu erstellt. Im Laufe des Programms wird ein Array gefüllt, der dann die Inhalte für das weitere Erstellen der Tabs nötig ist:

    Wie gesagt, die Tabs bleiben leider leer. Wenn ich das GUI mehrfach aufrufe (Menüpunkt wieder auswähle), dann fängt er irgendwann an zu flackern, dabei sieht man, dass er sehr wohl was in die Tabs rein schreibt, aber es verschwindet sofort wieder.

    Kann mir jemand helfen und sagen, woran das liegt, bzw. was ich da falsch mache? Und wie kann ich verhindern, dass man beim erneuten anklicken des Menüpunkts die GUI nicht wieder neu aufruft?

    VG

  • OK, da ich schon ein paar Aufrufe hatte, aber mir bis jetzt wohl niemand dabei helfen konnte bzw. ich mich vlt. auch umständlich ausgedrückt habe, hier eine alternative Frage:

    Ich habe eine Liste mit "ID" und "Name", die sehr lang sein kann. Darum habe ich sie in Pakete aufgeteilt. Die Paketgröße soll variabel sein, als Beispiel nehm ich mal eine Größe von 10. Also habe ich eine variable Anzahl an Paketen von jeweils 10 Einträgen mit "ID und "Name", also einen 3D-Array. Dessen Inhalt möchte ich jetzt in meinem GUI darstellen mit einem Button, mit dem ich die Liste abarbeiten kann, bzw. z. B. an ConsoleWrite schicken könnte. (ich will es nicht an ConsoleWrite schicken, aber der Einfachheit halber sagen wir mal das ^^)

    Hat jemand eine idee, wie ich das am besten darstellen kann, damit es schön übersichtlich ist und man sich leicht merken kann, welches Paket bereits abgearbeitet ist?

    VG

  • So, ich hab nochmal ein wenig umgebaut. Mittlerweile hab ich (aus Testzwecken) das GUI erst erstellt:

    Code
    Local $hRAWExportGUI = GUICreate( "", 600, 400, 0, 0, $WS_CHILD, Default, $hGUI)
    GUICtrlCreateLabel( "RAW-Export", 10, 10, 200, 23)
    GUICtrlSetFont( -1, 12, 400, 0, "Calibri" )
    Local $idAmount = GUICtrlCreateLabel( "", 10, 40, 200, 40 )
    Local $idExportAllBtn = GUICtrlCreateButton("Export all", 515, 10, 75, 25)
    Local $idCancelRAWExportBtn = GUICtrlCreateButton( "Cancel", 270, 365, 75, 25 )

    und in der While-Schleife wird das GUI noch ergänzt:

    Blöderweise bleibt das GUI unverändert. Da wird kein weiteres Element hinzugefügt.

    Weiß jemand, was ich da falsch mache?

  • Schon mal geschaut ob er deine Schleife überhaupt durchläuft (_ArrayDisplay($aTabs) z.B. mal ganz am Ende ausführen)?

    $ahExports ist auch wirklich gefüllt? Leider fehlt der Teil des codes hier.

  • Ich habe eine Liste mit "ID" und "Name", die sehr lang sein kann. Darum habe ich sie in Pakete aufgeteilt. Die Paketgröße soll variabel sein, als Beispiel nehm ich mal eine Größe von 10. Also habe ich eine variable Anzahl an Paketen von jeweils 10 Einträgen mit "ID und "Name", also einen 3D-Array.

    Es reicht hier sogar ein 1D-Array!

    ID = Index

    Name = Array[Index]

    Wenn du z.B. 500 Einträge hast, erstellst du einfach das Array nachdem alle anderen GUI-Elemente erstellt sind, wie folgt:

    Du kannst das auch irgendwo innerhalb der Gui-Erstellung ausführen. Du darfst nur zwischendurch keine anderen Ctrl erstellen, sonst stimmt die Zuordnung nicht.


    Ansonsten, wie Oscar bereits sagte:

    Bitte ein lauffähiges Minimalskript erstellen, d. h. ein Skript ohne Formatierungen oder Parent-Child-Geschichten, solange diese nicht Teil des Problems sind.

  • Sooo, ich hab jetzt mal mein Programm überarbeitet und ein allein lauffähiges Script erstellt, allerdings so, wie ich es gerne hätte, mit Tabs:

    Sorry für die vielen Includes, aber die hab ich jetzt nicht auch noch gefiltert ;)

    Das Problem ist, dass mir beim ersten Aufruf des Menüpunkts "RAW-Export" zwar die Tabs angezeigt werden, aber die Edit-Felder nicht. Wenn ich allerdings das GUI 3 mal aufrufe, dann fängt es an zu flackern und man sieht, dass er die Felder aufbaut. Offenbar werden sie aufgebaut, aber durch das Neuerstellen des nächsten Tabs, wird das wieder gelöscht.

    Wenn ich das GUI so umbaue, dass die auskommentierten Zeilen aktiv sind und die Tab-Erstellung auskommentiert, dann funktioniert der Aufbau.

    Achja und wie kann ich die erstellten Buttons abfragen? Das funktioniert leider auch nicht, da ich nicht weiß, wie ich das machen soll.

    VG

  • Es reicht hier sogar ein 1D-Array!

    Nein, leider nicht, bzw. würde es die ganze Sache komplizierter machen, da ich in dem Array erst ein Handle stehen habe und dann einen String (PatientenID). Ich könnte zwar mit For-Schleifen das alles abzählen und aufbauen lassen, aber ich muss später wissen, welches "Packet" zum Beariten ausgewählt wurde. Dann müsste ich ja wieder mit einer For-Schleife abzählen.


    Wenn du z.B. 500 Einträge hast, erstellst du einfach das Array nachdem alle anderen GUI-Elemente erstellt sind, wie folgt:

    Die restlichen GUI-Einträge werden ja anhand der Größe des Arrays erstellt. Das Array kann <100, aber auch >1000 Einträge haben, das kann ich nicht hardcoden.

    Jede Liste/jedes Tab bzw. jedes Pack soll noch einen Button bekommen, den ich dann auslesen kann.

  • Die restlichen GUI-Einträge werden ja anhand der Größe des Arrays erstellt. Das Array kann <100, aber auch >1000 Einträge haben, das kann ich nicht hardcoden.

    Das ist klar, sowas wird auch nicht hardcodiert - du musst ja auf jeden Fall irgendeine Liste in ein Array lesen - dieses hat dann einen UBound und den verwendet man dann statt der Bsp.-500.

    Jede Liste/jedes Tab bzw. jedes Pack soll noch einen Button bekommen, den ich dann auslesen kann.

    Wozu das?

    Ganz ehrlich - ich kann mir momentan dein Konzept dahinter nicht vorstellen. Vielleicht ist es ja auch schlüssig, aber das sollte dann auch mit schlüssiger Codierung einhergehen.

    Wenn ich viele, seeehr viele Einträge sehe, springt mich spontan immer das Listview als optimales Ctrl an. Du kannst gefühlt unzählige Infos zu jedem Eintrag speichern, lässt aber nur das Erforderliche anzeigen. Eine GUI sollte m.M.n. zuerst die erforderliche Funktionalität bedienen und erst danach kann man sich über Optik Gedanken machen.

    Vielleicht schilderst du dein Vorhaben mal nur in Stichworten oder in Art eines PAP. Empfehle ich immer. Oft ist es so, dass einem Ungereimtheiten beim Schreiben des PAP selbst auffallen.

    (Mein bevorzugter PAP-Designer).

  • Da ich gleich off muss, hier nur kurz die Beschreibung, was ich machen möchte. Um ein PAP kann ich mich später kümmern, wenn es dann noch unklar sein sollte:

    Also, ich habe eine Liste (TreeView), die durchsuche ich nach einem bestimmten Schlagwort. Ist dieses in einem der Items (Level 2) vorhanden, soll das Level0-Item in einem Array abgespeichert werden, dazu soll noch ein Teil der Bezeichnung in einem 2. Eintrag im Array gespeichert werden (1. Dimension).

    Da das Programm, was ich mit diesen Informationen füttern möchte, mit zu vielen Einträgen nicht klar kommt und sich dabei verhaspelt, habe ich den Array zerlegt und "Packete". Die Packetgröße soll man über die Einstellungen im Programm bestimmen sollen (2. Dimension) und die Anzahl der Packete ergibt sich aus der Länge der Liste (3. Dimension).

    Nachdem das Array erstellt und aufgeteilt wurde, soll man in einem GUI das Packet, was einem auch angezeigt wird mit Inhalt, auswählen, um es dann abarbeiten zu lassen. Damit man als Anwender die Übersicht behält, wollte ich Tabs nehmen. Dann muss man sich nur noch den Tab merken, den man als letztes bearbeitet hat. Es können dabei nur sehr wenige Tabs oder sehr viele Tabs entstehen, je nach länge der Liste eben. Damit das ganze auch Übersichtlich bleibt, ist eine Listview ungeeignet, weil das dann das GUI-Fenster sprengen würde.

    Ich dachte, ich bräuchte noch in jedem Tab einen Button, über den ich den aktuellen Tab abarbeiten lassen kann. Wenn es eine Möglichkeit gibt, den ausgewählten Tab festzustellen, brauch ich ja nur noch einen Button unter den Tabs im GUI, aber das weiß ich nicht, ob oder wie das geht.

    So, ich hoffe, dass das jetzt etwas Licht ins Dunkle gebracht hat ;)

  • Ich dachte, ich bräuchte noch in jedem Tab einen Button, über den ich den aktuellen Tab abarbeiten lassen kann. Wenn es eine Möglichkeit gibt, den ausgewählten Tab festzustellen, brauch ich ja nur noch einen Button unter den Tabs im GUI, aber das weiß ich nicht, ob oder wie das geht.

    Dem Manne kann geholfen werden:

    Online Help

    Beachte den advanced mode.

  • Dem Manne kann geholfen werden:

    Online Help

    Beachte den advanced mode.

    :D Danke!!! Funktioniert soweit. Allerdings bleibt das Problem, dass der Inhalt der Tabs nicht anzeigt wird. Wie gesagt, wenn ich die Tabs mehrmals erstellen lasse, dann fängt das GUI an zu flackern, wobei man sieht, dass er sehr wohl den Inhalt aufbaut, aber sofort wieder löscht/überschreibt. Woran kann das liegen, bzw. wie verhindere ich das?

  • Du blendest den alten Tab "nur aus" müsstest ihn doch aber "Zerstören" und beim nächsten mal anhand der neuen Daten neu erstellen oder bin ich da gerade komplett auf dem Holzweg?

    Und mal ganz nebenbei, in deinem Beispiel sind alle "Local" gesetzten Variablen "Global", da sie nicht in einer Funktion gekapselt sind.

    Ich selber tendiere auch dazu, Werte mit "Const" zu deklarieren, wo sich der Wert nicht mehr ändert (nur mal so am Rande). Das wäre bei den GUI-ID's der Fall.

  • Du blendest den alten Tab "nur aus" müsstest ihn doch aber "Zerstören" und beim nächsten mal anhand der neuen Daten neu erstellen oder bin ich da gerade komplett auf dem Holzweg?

    Ehm, verstehe ich das dann richtig, dass ich die GUI quasi komplett neu aufbauen muss? Weil dann brauch ich ja nur das GUICreate machen, damit etwas vorhanden ist, aber die Lables und Buttons kann ich dann in das Case schieben, wenn ich das ja eh neu aufbauen muss!?

    Und mal ganz nebenbei, in deinem Beispiel sind alle "Local" gesetzten Variablen "Global", da sie nicht in einer Funktion gekapselt sind.

    also kann ich alle Variablen auf "Local" ändern? Weil ich die Variablen eigentlich an die Funktionen übergebe?

    Ich selber tendiere auch dazu, Werte mit "Const" zu deklarieren, wo sich der Wert nicht mehr ändert (nur mal so am Rande). Das wäre bei den GUI-ID's der Fall.

    Ah ok, das kann ich noch ändern.

  • Zitat

    Ehm, verstehe ich das dann richtig, dass ich die GUI quasi komplett neu aufbauen muss? Weil dann brauch ich ja nur das GUICreate machen, damit etwas vorhanden ist, aber die Lables und Buttons kann ich dann in das Case schieben, wenn ich das ja eh neu aufbauen muss!?

    Ich befürchte, das du ansonsten immer wieder in die gleiche GUI schreibst und dort dann sich alles überlppt, habe es aber selber noch nicht ausprobiert/testen können.

    Ich kann aber gerade auch komplett auf dem Holzweg sein...ich arbeite in AutoIt halt möglichst wenig mit GUI :P

    Zitat

    also kann ich alle Variablen auf "Local" ändern? Weil ich die Variablen eigentlich an die Funktionen übergebe?

    Du müsstest die Variablen eigentlich alle als Global setzen, da sie im globalen Kontext genutzt werden (wie bereits erwähnt, nicht in einer Funktion).

    Wäre das in einer Funktion gekapselt (Func/EndFunc), sollten sie als "Locale" definiert werden und auch nur dort sind sie wirklich lokal.

  • Ich befürchte, das du ansonsten immer wieder in die gleiche GUI schreibst und dort dann sich alles überlppt, habe es aber selber noch nicht ausprobiert/testen können.

    Ich kann aber gerade auch komplett auf dem Holzweg sein...

    ja, das Gefühl hab ich auch, da die Eingabefelder, bzw. jetzt sind es im Moment Labels, ja erstellt werden, aber dann wohl unter den Tabitems liegen. Ich habe allerdings keine Ahnung, wie ich AutoIt beibringen kann, dass die Felder in den jewiligen Tabs erscheinen sollen. Im Internet wird sowas ja nicht erklärt.

    Du müsstest die Variablen eigentlich alle als Global setzen, da sie im globalen Kontext genutzt werden (wie bereits erwähnt, nicht in einer Funktion).

    Wäre das in einer Funktion gekapselt (Func/EndFunc), sollten sie als "Locale" definiert werden und auch nur dort sind sie wirklich lokal.

    Hm, ok. Ich kenne das so, dass eine Variable nur so lange lebt, wie der Programmteil, in dem sie genutzt wird, also die Zählvariable $i einer For-Schleife nur solange, wie die For-Schleife läuft, danach wird sie gelöscht bzw. die Adresse der Variable. Wenn ich allerdings eine Variable am Anfang des Programms initialisiere, dann ist sie quasi Global, weil sie erst stirbt, wenn das Programm beendet wird. Ist das bei AutoIt anders, oder einfach nur ein "schlechter Style", wenn man kein Global benutzt?

  • Moombas Wenn ich übrigens ein GUIDelete mache, dann bekomme ich gar nichts mehr angezeigt, egal was ich mit dem GUI danach anstelle. Also da tappe ich total im Dunkeln, wie ich das richtig machen muss!

  • Ich habe allerdings keine Ahnung, wie ich AutoIt beibringen kann, dass die Felder in den jewiligen Tabs erscheinen sollen.

    2. Parameter von:

    Function GUISwitch

    Zur Nutzung dieses Forum's, ist ein Übersetzer für folgende Begriffe unerlässlich:

    "On-Bort, weier, verscheiden, schädliges, Butten steyling, näckstet, Parr, Porblem, scripe, Kompletenz, harken, manuel zu extramieren, geckukt, würglich, excell, acces oder Compilevorgeng"

  • 2. Parameter von:

    Function GUISwitch

    Hab ich grade nochmal alle kontrolliert, steht aber überall drin. Ich erstelle die TabItems und speichere die ID in einen Array. Diese ID übergebe ich dann auch an GUISwitch. Ich hab meine Erstellung jetzt so geändert, dass ich beim öffnen der GUI erst alle TabItems erstellen lasse und danach erstelle ich für jedes TabItem die Labels.

    Trotzdem bleiben die Tabs leer X(