9 Stimmen

Wie verhält sich ein wxFrame wie ein modales wxDialog-Objekt?

Ist es möglich, ein wxFrame-Objekt wie ein modales Dialogfeld zu verhalten, so dass das Fenster, das das wxFrame-Objekt erstellt, die Ausführung stoppt, bis das wxFrame-Objekt beendet wird?

Ich arbeite an einem Kleinwild und bin auf das folgende Problem gestoßen. Ich habe ein Hauptprogrammfenster, in dem sich die Hauptanwendung (der strategische Teil) befindet. Gelegentlich muss ich die Kontrolle auf ein zweites Fenster übertragen, um einen Teil des Spiels (den taktischen Teil) aufzulösen. Während ich mich im zweiten Fenster befinde, soll die Verarbeitung im ersten Fenster angehalten und auf den Abschluss der Arbeit im zweiten Fenster gewartet werden.

Normalerweise würde ein modaler Dialog den Trick tun, aber ich möchte, dass das neue Fenster einige Funktionen hat, die ich mit einem wxDialog nicht zu bekommen scheine, nämlich eine Statusleiste am unteren Rand und die Fähigkeit, die Größe/Maximierung/Minimierung des Fensters zu ändern (dies sollte möglich sein, funktioniert aber nicht, siehe diese Frage Wie man die Schaltflächen zum Minimieren und Maximieren auf einem wxDialog-Objekt anzeigt ).

Außerdem möchte ich, dass die Funktionalität des zweiten Fensters vollständig vom Hauptfenster entkoppelt bleibt, da es später in ein separates Programm ausgegliedert wird.

Hat das schon jemand gemacht oder hat jemand Vorschläge?

0 Stimmen

Vielleicht sollte man das zweite Fenster zu einer zweiten Anwendung machen und die Kommunikation zwischen den beiden Anwendungen über einen Socket laufen lassen. Das könnte das vereinfachen, was Sie mit wxWidgets tun müssen.

4voto

Anurag Uniyal Punkte 81337

Ich war auch auf der Suche nach einer ähnlichen Lösung und habe diese Lösung gefunden. Erstellen Sie einen Rahmen, deaktivieren Sie andere Windows, indem Sie frame.MakeModal() und um die Ausführung zu stoppen, starten Sie eine Ereignisschleife, nachdem Sie den Rahmen angezeigt haben, und wenn der Rahmen geschlossen ist, verlassen Sie die Ereignisschleife z.B. Ich hier ist Beispiel mit wxpython, aber es sollte ähnlich in wxwidgets sein.

import wx

class ModalFrame(wx.Frame):
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, style=wx.DEFAULT_FRAME_STYLE|wx.STAY_ON_TOP)

        btn = wx.Button(self, label="Close me")
        btn.Bind(wx.EVT_BUTTON, self.onClose)
        self.Bind(wx.EVT_CLOSE, self.onClose) # (Allows main window close to work)

    def onClose(self, event):
        self.MakeModal(False) # (Re-enables parent window)
        self.eventLoop.Exit()
        self.Destroy() # (Closes window without recursion errors)

    def ShowModal(self):
        self.MakeModal(True) # (Explicit call to MakeModal)
        self.Show()

        # now to stop execution start a event loop 
        self.eventLoop = wx.EventLoop()
        self.eventLoop.Run()

app = wx.PySimpleApp()
frame = wx.Frame(None, title="Test Modal Frame")
btn = wx.Button(frame, label="Open modal frame")

def onclick(event):
    modalFrame = ModalFrame(frame, "Modal Frame")
    modalFrame.ShowModal()
    print "i will get printed after modal close"

btn.Bind(wx.EVT_BUTTON, onclick)

frame.Show()
app.SetTopWindow(frame)
app.MainLoop()

3voto

mghie Punkte 31618

Es ist nicht wirklich sinnvoll, die Ausführung eines Fensters "anzuhalten", da das Fenster nur Ereignisse verarbeitet, die an es gesendet werden, wie z.B. Maus-, Tastatur- oder Malereignisse, und das Ignorieren dieser Ereignisse würde das Programm aufgehängt erscheinen lassen. Was Sie tun sollten, ist, alle Steuerelemente in Ihrem Rahmen zu deaktivieren. Dadurch werden sie ausgegraut und der Benutzer wird darauf aufmerksam gemacht, dass mit ihnen in diesem Moment nicht interagiert werden kann.

Sie können auch den übergeordneten Rahmen vollständig deaktivieren, anstatt alle Steuerelemente darin zu deaktivieren. Sehen Sie sich die wxWindowDisabler Klasse hat der Konstruktor einen Parameter, der ein Fenster angibt, mit dem interagiert werden kann, und alle anderen Fenster der Anwendung werden deaktiviert.

Wenn Sie zu einem späteren Zeitpunkt ein sekundäres Programm ausführen wollen, dann können Sie die wxExecute() Funktion, um dies zu tun.

3voto

Nate Punkte 17748

Es hat mich viel Zeit gekostet, das herauszufinden, aber hier ist ein funktionierendes Beispiel, das aus Anurags Beispiel hervorgegangen ist:

import wx

class ChildFrame(wx.Frame):
    ''' ChildFrame launched from MainFrame '''
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, -1,
                          title=self.__class__.__name__,
                          size=(300,150))

        panel = wx.Panel(self, -1)
        closeButton = wx.Button(panel, label="Close Me")

        self.Bind(wx.EVT_BUTTON, self.__onClose, id=closeButton.GetId())
        self.Bind(wx.EVT_CLOSE, self.__onClose) # (Allows frame's title-bar close to work)

        self.CenterOnParent()
        self.GetParent().Enable(False)
        self.Show(True)

        self.__eventLoop = wx.EventLoop()
        self.__eventLoop.Run()

    def __onClose(self, event):
        self.GetParent().Enable(True)
        self.__eventLoop.Exit()
        self.Destroy()

class MainFrame(wx.Frame):
    ''' Launches ChildFrame when button is clicked. '''
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id,
                          title=self.__class__.__name__,
                          size=(400, 300))

        panel = wx.Panel(self, -1)
        launchButton = wx.Button(panel, label="launch modal window")

        self.Bind(wx.EVT_BUTTON, self.__onClick, id=launchButton.GetId())

        self.Centre()
        self.Show(True)

    def __onClick(self, event):
        dialog = ChildFrame(self, -1)
        print "I am printed by MainFrame and get printed after ChildFrame is closed"

if __name__ == '__main__':
    app = wx.App()    
    frame = MainFrame(None, -1)
    frame.Show()
    app.MainLoop()

0voto

dex black Punkte 36

Ich weiß nicht, ob das eine gute Antwort ist, aber es hat funktioniert.

bool WinApp1::OnInit()
{
  if (!wxApp::OnInit())
    return false;

  SettingsDialog dialog(m_settingsData);
  dialog.ShowModal();

  return false;
}

SettingsDialog::SettingsDialog(SettingsData& settingsData)
  : m_settingsData(settingsData)
{
  SetExtraStyle(wxDIALOG_EX_CONTEXTHELP);

  wxWindow* parent = nullptr;
  Create(parent, wxID_ANY, "Preferences", wxDefaultPosition, wxDefaultSize,
    wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);

Das WinApp1-Fenster erhält nie einen wxFrame und malt nie.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X