Un sacco di domande diverse qui, sarebbe stato meglio chiedere questo in 2 o 3 post separati, ma vediamo cosa succede ...
1) "il mondo", suppongo sia un termine relativo. Non darei un valore puntatore a "il mondo", ma sulla base del tuo esempio, direi di andare avanti perché non considererei un contenitore di un widget "il mondo". D'altra parte, se hai creato un insieme di oggetti basato su richiesta client esterna e poi invece di identificatori univoci, puntatori usati direttamente come identificatori, darebbe un puntatore alla memoria interna al mondo. Eviterei di farlo.
2) Considero gli oggetti (oi widget) che contengono puntatori ad altri oggetti (o widget) per essere automaticamente design errato. Ovviamente vuoi mantenere le cose il più liberamente accoppiate possibile, ma posso vedere alcune situazioni, dove questo sarebbe accettabile. Abbastanza sciolto significa semplicemente che vuoi che ognuno dei tuoi oggetti (o widget) sappia solo quanto sugli altri come assolutamente necessario (e non fare ipotesi sulle implementazioni interne)
3) Ho realizzato numerosi progetti in cui hai un contenitore genitore e un gruppo di bambini. Una cosa che cerco sempre di fare è evitare le dipendenze circolari dove l'oggetto A sa che B e B conoscono A. In genere, quando lo fai, stai cercando dei problemi. Invece definirei un child (la nostra classe widget) e accanto ad esso definirò l'interfaccia "IWidgetOwner" o "IWidgetKeeper" (ghostbusters reference). Quindi il genitore implementa questa interfaccia e passa un puntatore a ogni bambino. Ora hai una relazione gerarchica molto chiara. Il tuo contenitore conosce i widget che contiene, ma i widget non sanno nulla del tuo contenitore specifico. Invece, possono essere inseriti in qualsiasi contenitore che implementa la tua interfaccia di "custode".
4) Detto questo, se si sta facendo un lavoro specifico sull'interfaccia utente, starei lontano dall'aggiungere troppa logica di business all'interno dei controlli della GUI (widget) stessi. Invece, avrei un layer separato (classe) che configurerebbe le sottoscrizioni sui gestori di eventi e definirò quale azione dovrebbe essere intrapresa quando determinati eventi vengono lanciati. In questo modo il codice del tuo widget rimane generico e riutilizzabile e tutta la logica di business è racchiusa in un unico posto, quindi quando devi andare a cambiarlo, non è necessario cercare in tutto il tuo codice.
5) Un pulsante mai "necessario" per scrivere un file. Invece, l'applicazione deve scrivere un file in risposta a un clic dell'utente. Separerei sempre il codice che "funziona" dall'interfaccia utente il più possibile. Pensa allo scenario in cui desideri un secondo pulsante o un tasto di scelta rapida globale per scrivere lo stesso file? O se vuoi aggiungere automazione e devi scrivere lo stesso file ma senza alcuna GUI. Quando avvii un progetto con un'interfaccia utente, inizia definendo una linea molto chiara tra la tua GUI e il tuo lavoro. Potrebbe sembrare un sovraccarico, ma è solo un esercizio mentale e dopo averlo fatto un paio di volte, diventerà molto più naturale, quindi il sovraccarico quasi scomparirà. Ma scriverò codice che è più liberamente accoppiato e posizionato meglio per l'espansione futura.