Mit Button ein neues Fenster öffnen bzw. Schließen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Mit Button ein neues Fenster öffnen bzw. Schließen

    Hallo an alle,

    ich möchte mir gerne, wenn ich auf einen Button drücke, ein weiteres Fenster anzeigen lassen bzw. Schließen.
    Ja ich weis, Storyboard, Reche Maustaste, ziehen...
    Das ganze soll aber vom code aus funktionieren, da zuerst der Inhalt von einem Textfeld abgeglichen werden soll und nur, wenn dieser Richtig ist, dann soll der Nutzer das neue Fenster zu sehn bekommen. Und das selbe dann halt auch fürs schließen...

    Weis jemand von euch wie das geht?

    Liebe Grüße
    Paul
  • Du könntest doch dem Button eine Action hinterlegen, in deren Code Du dann einen NSWindowController instanzierst. Dieser lädt sein Fenster aus einem XIB (initWithWindowNibName:) und zeigt es per showWindow: an.

    Und zum Schließen hat NSWindow auch entsprechende Methoden, die Du einfach im Code nutzen kannst.

    Der Controller kann auch aus einem Storyboard instanziert werden (instantiateControllerWithIdentifier:), aber so ein Konstrukt habe ich unter macOS nicht ... eben noch old school :)

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • MyMattes schrieb:

    Du könntest doch dem Button eine Action hinterlegen, in deren Code Du dann einen NSWindowController instanzierst. Dieser lädt sein Fenster aus einem XIB (initWithWindowNibName:) und zeigt es per showWindow: an.

    Und zum Schließen hat NSWindow auch entsprechende Methoden, die Du einfach im Code nutzen kannst.

    Der Controller kann auch aus einem Storyboard instanziert werden (instantiateControllerWithIdentifier:), aber so ein Konstrukt habe ich unter macOS nicht ... eben noch old school :)

    Mattes
    @'MyMattes
    Ok vielen dank! Nur ein Problem bleibt - ich bin noch nicht so fortgeschritten in Swift - was genau schreibe ich jetzt in den Code

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Paul___Paul ()

  • Swift-Code kann ich Dir keinen liefern ... mangels Kenntnis und wahrscheinlich ist es für Dich auch langfristig hilfreicher, keine fertige Lösungen präsentiert zu bekommen. Stichworte zur eigenen Recherche sind oben ja genug und das Web liefert dazu z. B. SO-Artikel wie diesen.

    Fang einfach mit kleinen Schritten an: Erstelle einen WindowsController im Storyboard, gib ihm einen Identifier, schreib' dann zwei Zeilen Code, die diesen Controller aus dem Storyboard instanzieren usw.

    Wenn Du an einem Punkt nicht weiter kommst, probiere, verwerfe, probiere neu. Wenn Google, dann versuche gefundene Lösungen 100% zu verstehen. Und frage bei konkreten Problemen, idealerweise mit Deinem Code.

    Mattes

    P.S.: Weil ich es jetzt selber probieren wollte, habe ich ein neues Xcode-Projekt auf Basis des Apple-Templates angelegt: Im Storyboard einen zusätzlichen NSWindowsController angelegt, in beide Views je einen Button geschoben und Actions im jeweiligen NSViewController hinterlegt / verknüpft: Läuft - quick & dirty mit null Fehlerprüfungen und ohne Gewähr ... vielleicht motiviert Dich das zum Weitermachen. Mein Rat bzgl. Verständnis von kopiertem Code bleibt bestehen :)

    Quellcode

    1. @IBAction func showView(_ sender: NSButton) {
    2. let storyboard:NSStoryboard = NSStoryboard(name: "Main", bundle: nil)
    3. let wc:NSWindowController = storyboard.instantiateController(withIdentifier: "myWC2") as! NSWindowController
    4. wc.showWindow(self)
    5. }
    6. @IBAction func closeButton(_ sender: NSButton) {
    7. self.view.window?.close()
    8. }
    Diese Seite bleibt aus technischen Gründen unbedruckt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von MyMattes ()

  • Wenn wir schon bei funktionsfähigen Code sind, hier mal zwei Fenster, einfach neues macOS Projekt erstellen, und hier die Contentview reinkopieren, ausführen ... fertig

    Quellcode

    1. import SwiftUI
    2. struct NewWindow: View {
    3. @Environment(\.dismiss) var dismiss
    4. var body: some View {
    5. Button { dismiss() } label: { Text("Dismiss")}
    6. }
    7. }
    8. struct ContentView: View {
    9. @State private var showMe: Bool = false
    10. var body: some View {
    11. VStack {
    12. Button { showMe.toggle() } label: { Text("Show Window")}
    13. }.sheet(isPresented: $showMe) {
    14. NewWindow()
    15. .frame(width: 100, height: 100)
    16. }
    17. .frame(width: 200, height: 100)
    18. }
    19. }
    Alles anzeigen

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Wolf ()

  • Wolf schrieb:

    Wenn wir schon bei funktionsfähigen Code sind, hier mal zwei Fenster, einfach neues macOS Projekt erstellen, und hier die Contentview reinkopieren, ausführen ... fertig

    Quellcode

    1. import SwiftUI
    2. struct NewWindow: View {
    3. @Environment(\.dismiss) var dismiss
    4. var body: some View {
    5. Button { dismiss() } label: { Text("Dismiss")}
    6. }
    7. }
    8. struct ContentView: View {
    9. @State private var showMe: Bool = false
    10. var body: some View {
    11. VStack {
    12. Button { showMe.toggle() } label: { Text("Show Window")}
    13. }.sheet(isPresented: $showMe) {
    14. NewWindow()
    15. .frame(width: 100, height: 100)
    16. }
    17. .frame(width: 200, height: 100)
    18. }
    19. }
    Alles anzeigen
    Danke, ich bin nur auf der suche das ganz auch mit einem Storyboard zu lösen...
  • MyMattes schrieb:

    Wolf schrieb:

    Wenn wir schon bei funktionsfähigen Code sind, hier mal zwei Fenster...
    Naja, ein Fenster und ein Sheet ... Trotzdem cool, hab's gerade mal compiliert. Wäre es für zwei "echte" Fenster wesentlich umständlicher?

    Hallo Mattes, das sind zwei echte Fenster. Da zweite Fenster kannst auch ganz anders aufrufen. Das Sheet sagt nur, dass das Fenster Modal dargestellt werden soll.

    Wenn Du den dismiss weg lässt, kannst das andere Fenster auch in das erste einbinden. Unter SwiftUI ist alles eine View. Die kannst verwenden wie du möchtest.
  • Wolf schrieb:

    das sind zwei echte Fenster. Da zweite Fenster kannst auch ganz anders aufrufen.
    Ich habe einmal etwas geforscht und mit der Anforderung "echter Fenster" (eben kein Sheet, sondern mit Titlebar, Close-Button etc.) sieht es momentan mit SwiftUI scheinbar nicht mehr so "clean" aus: Laut dieses SO-Artikels muss man hierzu entweder über eine eigene View-Extension ein neues NSWindow im Hosting-Controller erzeugen oder über das URL-Schema der App externe Events faken.

    Nicht als Bashing gemeint, aber mein Verständnis von verständlicher und plattformübergreifender Programmierung ist ein anderes. Ich glaube auch, dass in Zukunft viele - nicht alle - Anwendungsfälle sinnvoll in SwiftUI abbildbar sein werden ... zumindest unter macOS scheint dies aber momentan noch nicht der Fall zu sein.

    Sorry für's Abdriften in's Offtopic: Ich höre jetzt mal auf, bei Bedarf können wir uns ja in einen neuen Thread verlagern... :)

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von MyMattes ()

  • Tja, das sind WindowGroup‘s, welche Du auf dem App-Level definierst. So etwas brauchte ich bisher nie, aber wenn, du siehst ja, das ist auch mit relativ geringen Aufwand möglich. Ich gehe mal davon aus, dass die „Modeless Dialogs„ dann wohl im kommenden Jahr kommen werden. Auf diese Spezialität von macOS kann ich aktuell ganz gut verzichten, ansonsten sind sie ja auch in 5 Minuten implementiert.
  • Das schließen hat mit @'MyMattes Hilfe gut funktioniert! Nur Problematisch wird's beim öffnen des Fensters.

    - Das einzige was bei mir passierte war eine ewiglange Ausgabe in der Konsole!
    - Oder das in den Hintergrund treten des Fensters mit dem Button, ohne das ein neues erschien.
    - Ich glaube ich habe Probleme mit dem "Identifier", wo genau legt man den fest?
    - @'MyMattes schieb immer von NSWindowController kann man auch einen ViewControler nutzen?
  • Paul___Paul schrieb:

    - Ich glaube ich habe Probleme mit dem "Identifier", wo genau legt man den fest?

    - @'MyMattes schieb immer von NSWindowController kann man auch einen ViewControler nutzen?
    Ne, es muss schon ein NSWindowController sein, der wieder (standardmässig) eine View mit ViewController beinhaltet. Geschieht aber automatisch, wenn Du einen NSWindowController aus der Library in's Storyboard ziehst.

    Den "Storyboard Identifier" legst Du rechts in den Objekteigenschaften im IB fest. Achte darauf, das richtige Objekt markiert zu haben.

    Mattes

    P.S.: Bei Fehlermeldungen macht es Sinn, diese zu posten. Sonst brauchen wir Kristallkugeln...
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • MyMattes schrieb:

    Ne, es muss schon ein NSWindowController sein, der wieder (standardmässig) eine View mit ViewController beinhaltet. Geschieht aber automatisch, wenn Du einen NSWindowController aus der Library in's Storyboard ziehst.
    Den "Storyboard Identifier" legst Du rechts in den Objekteigenschaften im IB fest. Achte darauf, das richtige Objekt markiert zu haben.

    Mattes
    Ok, die beiden Punkte habe ich richtig befolgt, dann muss das Problem woanders liegen.
  • MyMattes schrieb:

    P.S.: Bei Fehlermeldungen macht es Sinn, diese zu posten. Sonst brauchen wir Kristallkugeln...

    Quellcode

    1. 2022-01-05 14:00:37.173 Login[941:23500] Storyboard (<NSStoryboard: 0x608000005c30>) doesn't contain a controller with identifier 'Neu'
    2. 2022-01-05 14:00:37.229 Login[941:23500] (
    3. 0 CoreFoundation 0x00007fff99bee452 __exceptionPreprocess + 178
    4. 1 libobjc.A.dylib 0x00007fff8ec5173c objc_exception_throw + 48
    5. 2 AppKit 0x00007fff9d18ad84 -[NSStoryboard instantiateInitialController] + 0
    6. 3 Login 0x00000001000019c5 _TFC5Login14ViewController10AnmeldeBtnfPs9AnyObject_T_ + 1173
    7. 4 Login 0x0000000100001d86 _TToFC5Login14ViewController10AnmeldeBtnfPs9AnyObject_T_ + 54
    8. 5 libsystem_trace.dylib 0x00007fff94fa207a _os_activity_initiate + 75
    9. 6 AppKit 0x00007fff9ccafdbd -[NSApplication sendAction:to:from:] + 460
    10. 7 AppKit 0x00007fff9ccc1f12 -[NSControl sendAction:to:] + 86
    11. 8 AppKit 0x00007fff9ccc1e3c __26-[NSCell _sendActionFrom:]_block_invoke + 131
    12. 9 libsystem_trace.dylib 0x00007fff94fa207a _os_activity_initiate + 75
    13. 10 AppKit 0x00007fff9ccc1d99 -[NSCell _sendActionFrom:] + 144
    14. 11 libsystem_trace.dylib 0x00007fff94fa207a _os_activity_initiate + 75
    15. 12 AppKit 0x00007fff9ccc03be -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2693
    16. 13 AppKit 0x00007fff9cd08f04 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 744
    17. 14 AppKit 0x00007fff9ccbeae8 -[NSControl mouseDown:] + 669
    18. 15 AppKit 0x00007fff9d2133c9 -[NSWindow _handleMouseDownEvent:isDelayedEvent:] + 6322
    19. 16 AppKit 0x00007fff9d2143ad -[NSWindow _reallySendEvent:isDelayedEvent:] + 212
    20. 17 AppKit 0x00007fff9cc53539 -[NSWindow sendEvent:] + 517
    21. 18 AppKit 0x00007fff9cbd3a38 -[NSApplication sendEvent:] + 2540
    22. 19 AppKit 0x00007fff9ca3adf2 -[NSApplication run] + 796
    23. 20 AppKit 0x00007fff9ca04368 NSApplicationMain + 1176
    24. 21 Login 0x0000000100004b94 main + 84
    25. 22 libdyld.dylib 0x00007fffa09d65ad start + 1
    26. )
    Alles anzeigen
    Dies wurde in der Konsole ausgegeben ich glaube das liegt aber daran dass ich den identifier an der falsche stelle gesetzt habe...
  • Ich habe nochmal ne Nachfrage muss der Identifier bei "Identifier" oder bei "Storyboard ID" stehen?
    Hier? (A)
    A.png

    Oder Hier? (B)
    B.png

    Wenn ich ihn bei (A) hineinschreibe bekomme ich diese Ewig lange Ausgabe in der Konsole zurück, wenn ich ihn bei (B) hineinschreibe kommt keine Ausgabe in der Konsole, jedoch wird das Fenster, in dem der Button ist, mit dem ich in das andere Wechseln möchte, grau und ist nichtmehr das Vordergrund Fenster, ein anderes weiteres Fenster hat sich jedoch nicht geöffnet.

    Liebe Grüße
    Paul
  • (B) ist richtig, im anderen Fall setzt Du ja eine StoryboardID für das Fenster (NSWindow), nicht den Controller.

    Warum sich kein Fenster öffnet, lässt sich ohne Wissen Deines Codes kaum sagen. Du lässt Dich nicht zufällig dadurch verwirren, dass macOS ein neues Fenster standardmäßig nur in einem zusätzlichen Tab darstellt? Dies lässt sich über den "Tabbing Mode" des aufrufenden Fensters umstellen.

    Vielleicht magst Du zur Orientierung in das angehangene Projekt schauen - Achtung, sehr minimalistisch auf Basis eines "leeren" Apple Xcode-Templates. So verwende ich z. B. für die beiden Fenster den gleichen ViewController, was wohl eher ungewöhnlich ist.

    Mattes
    Dateien
    • Swift-Window.zip

      (37,74 kB, 81 mal heruntergeladen, zuletzt: )
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • MyMattes schrieb:

    Du lässt Dich nicht zufällig dadurch verwirren, dass macOS ein neues Fenster standardmäßig nur in einem zusätzlichen Tab darstellt? Dies lässt sich über den "Tabbing Mode" des aufrufenden Fensters umstellen.
    Vielleicht zufällig doch, was genau ist damit gemeint?
    (Das Projekt habe ich mir mal angeschaut genau das selbe passiert in meinem Projekt auch.)

    Grüße
    Paul