Возвращаемое значение из фрейма wxPython

может ли кто-нибудь показать мне, как я могу вернуть значение из фрейма wxPython? Когда использование щелкает закрыть, я всплывающее диалоговое окно сообщения, задавая ему вопрос. Я хотел бы вернуть код возврата этого диалогового окна сообщения в мою вызывающую функцию.

спасибо

8 ответов


потому что wxFrame имеет события, которые обрабатываются через приложение.Функциональность MainLoop (), единственный способ получить возвращаемое значение wx.Frame () - это улавливание события.

стандартная практика обработки событий обычно происходит из класса, производного от wx.Само окно (например, рама, панель и т. д.). Поскольку вы хотите внешний код для wx.Фрейм для получения информации, которая была собрана при обработке события OnClose (), то лучший способ сделать это-зарегистрироваться обработчик событий для вашего фрейма.

документация для wx.Window:: PushEventHandler, вероятно, лучший ресурс и даже wxPython, в вики есть хорошая статья о том, как это сделать. В статье они регистрируют пользовательский обработчик, который является экземпляром " MouseDownTracker."Вместо того, чтобы создавать экземпляр в вызове PushEventHandler, вы хотели бы создать его до вызова, чтобы сохранить дескриптор производного класса EventHandler. Таким образом, ты можно проверить производные переменные класса EventHandler после уничтожения фрейма или даже разрешить этому производному классу делать для вас специальные вещи.

вот адаптация этого кода из WX python wiki (по общему признанию, немного запутанная из-за требования обработки результатов пользовательского события с функцией "вызова"):

import sys
import wx
import wx.lib.newevent

(MyCustomEvent, EVT_CUSTOM) = wx.lib.newevent.NewEvent()

class CustomEventTracker(wx.EvtHandler):
 def __init__(self, log, processingCodeFunctionHandle):
  wx.EvtHandler.__init__(self)
  self.processingCodeFunctionHandle = processingCodeFunctionHandle
  self.log = log
  EVT_CUSTOM(self, self.MyCustomEventHandler)

 def MyCustomEventHandler(self, evt):
  self.log.write(evt.resultOfDialog + '\n')
  self.processingCodeFunctionHandle(evt.resultOfDialog)
  evt.Skip()

class MyPanel2(wx.Panel):
 def __init__(self, parent, log):
  wx.Panel.__init__(self, parent)
  self.log = log

 def OnResults(self, resultData):
  self.log.write("Result data gathered: %s" % resultData)

class MyFrame(wx.Frame):
 def __init__(self, parent, ID = -1, title = "", pos = wx.DefaultPosition,
     size = wx.DefaultSize, style = wx.DEFAULT_FRAME_STYLE):
  wx.Frame.__init__(self, parent, ID, title, pos, size, style)
  self.panel = panel = wx.Panel(self, -1, style = wx.TAB_TRAVERSAL
       | wx.CLIP_CHILDREN
       | wx.FULL_REPAINT_ON_RESIZE)
  sizer = wx.BoxSizer(wx.VERTICAL)
  sizer.Add((25, 25))

  row = wx.BoxSizer(wx.HORIZONTAL)
  row.Add((25,1))
  m_close = wx.Button(self.panel, wx.ID_CLOSE, "Close")
  m_close.Bind(wx.EVT_BUTTON, self.OnClose)
  row.Add(m_close, 0, wx.ALL, 10)
  sizer.Add(row)
  self.panel.SetSizer(sizer)

 def OnClose(self, evt):
  dlg = wx.MessageDialog(self, 
   "Do you really want to close this frame?",
   "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
  result = dlg.ShowModal()
  dlg.Destroy()
  if result == wx.ID_CANCEL:
   event = MyCustomEvent(resultOfDialog = "User Clicked CANCEL")
   self.GetEventHandler().ProcessEvent(event)
  else: # result == wx.ID_OK
   event = MyCustomEvent(resultOfDialog = "User Clicked OK")
   self.GetEventHandler().ProcessEvent(event)
   self.Destroy()

app = wx.App(False)
f2 = wx.Frame(None, title="Frame 1 (for feedback)", size=(400, 350))
p2 = MyPanel2(f2, sys.stdout)
f2.Show()
eventTrackerHandle = CustomEventTracker(sys.stdout, p2.OnResults)
f1 = MyFrame(None, title="PushEventHandler Tester (deals with on close event)", size=(400, 350))
f1.PushEventHandler(eventTrackerHandle)
f1.Show()
app.MainLoop()

вы можете получить результат нажатия кнопок OK, CANCEL из диалогового метода ShowModal.
Данный диалог является экземпляром одного из диалоговых классов wxPython:

result = dialog.ShowModal()
if result == wx.ID_OK:
    print "OK"
else:
    print "Cancel"
dialog.Destroy()

Я хотел сделать то же самое, чтобы иметь графический "выбор", который я мог бы запустить из консольного приложения. Вот как я это сделал.

# Fruit.py

import wx

class Picker (wx.App):
    def __init__ (self, title, parent=None, size=(400,300)):
        wx.App.__init__(self, False)
        self.frame = wx.Frame(parent, title=title, size=size)

        self.apple_button = wx.Button(self.frame, -1, "Apple", (0,0))
        self.apple_button.Bind(wx.EVT_BUTTON, self.apple_button_click)

        self.orange_button = wx.Button(self.frame, -1, "Orange", (0,100))
        self.orange_button.Bind(wx.EVT_BUTTON, self.orange_button_click)

        self.fruit = None
        self.frame.Show(True)

    def apple_button_click (self, event):
        self.fruit = 'apple'
        self.frame.Destroy()

    def orange_button_click (self, event):
        self.fruit = 'orange'
        self.frame.Destroy()

    def pick (self):
        self.MainLoop()
        return self.fruit

затем из консольного приложения я бы запустил этот код.

# Usage.py

import Fruit

picker = Fruit.Picker('Pick a Fruit')
fruit = picker.pick()
print 'User picked %s' % fruit

ответ user1594322 работает, но он требует, чтобы вы поместили все свои элементы управления в свой wx.Приложение, а не wx.Рамка. Это затруднит переработку кода.

мое решение включает в себя определение переменной "PassBack" при определении вашего init. (аналогично" родительской " переменной, но она обычно используется уже при инициировании wx.Кадр)

из моего кода:

class MyApp(wx.App):
    def __init__ (self, parent=None, size=(500,700)):
        wx.App.__init__(self, False)
        self.frame = MyFrame(parent, -1, passBack=self) #Pass this app in
        self.outputFromFrame = "" #The output from my frame


    def getOutput(self):
        self.frame.Show()
        self.MainLoop()
        return self.outputFromFrame

и для класса frame:

class MyFrame(wx.Frame):
    def __init__(self, parent, ID, passBack, title="My Frame"):
        wx.Frame.__init__(self, parent, ID, title, size=(500, 700))
        self.passBack = passBack #this will be used to pass back variables/objects

и где-то во время выполнения MyFrame

self.passBack.outputFromFrame = "Hello"

все, чтобы получить строку из приложения

app = MyApp()
val = app.getOutput()
#Proceed to do something with val

несколько лет спустя для первоначального вопроса, но при поиске ответа на этот вопрос я сам наткнулся на встроенный метод получения возвращаемого значения из модального, не возясь с какой-либо пользовательской забавностью событий. Подумал, что напишу здесь на случай, если кому-то еще понадобится.

Это просто этот парень прямо здесь:

wxDialog:: EndModal void EndModal (int retCode)

заканчивается модальный диалог, передающий значение, возвращаемое из *wxDialog::вызов ShowModal.*

используя вышеизложенное, вы можете вернуть все, что хотите из диалогового окна.

примером использования будет подкласс a wx.Dialog, а затем помещая EndModal функция в обработчиках кнопок.

class ProjectSettingsDialog(wx.Dialog):
    def __init__(self):
        wx.Dialog.__init__(self, None, -1, "Project Settings", size=(600,400))

        sizer = wx.BoxSizer(wx.VERTICAL) #main sized
        sizer.AddStretchSpacer(1) 

        msg = wx.StaticText(self, -1, label="This is a sample message")
        sizer.Add(msg, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 15)


        horizontal_sizer = wx.BoxSizer(wx.HORIZONTAL)
        okButton = wx.Button(self, -1, 'OK')
        self.Bind(wx.EVT_BUTTON, self.OnOK, okButton)

        cancelBtn = wx.Button(self, -1, "Cancel")
        self.Bind(wx.EVT_BUTTON, self.OnCancel, cancelBtn)

        horizontal_sizer.Add(okButton, 0, wx.ALIGN_LEFT)
        horizontal_sizer.AddStretchSpacer(1)
        horizontal_sizer.Add(cancelBtn, 0, wx.ALIGN_RIGHT)

        sizer.Add(horizontal_sizer, 0)

        sizer.AddStretchSpacer(1)
            self.SetSizer(sizer)

    def OnOK(self, event):
        self.EndModal(wx.ID_OK) #returns numeric code to caller
        self.Destroy()


    def OnCancel(self, event):
        self.EndModal(wx.ID_CANCEL) #returns numeric code to caller
        self.Destroy()

(Примечание: я просто ударил этот код быстро; не тестировал сайзеры)

Как видите, все, что вам нужно сделать, это вызовите EndModal из события button, чтобы вернуть значение тому, что породило диалог.


проверьте этот ответ на comp.ленг.python:линки


Я не думаю, что wxFrame может возвращать значение, поскольку оно не является модальным. Если вам не нужно использовать wxFrame, тогда модальный диалог может работать для вас. Если вам действительно нужен фрейм, я бы рассмотрел использование пользовательского события.

Это будет что-то вроде этого: (1) пользователь щелкает, чтобы закрыть wxFrame (2) вы переопределяете OnClose (или что-то в этом роде), чтобы открыть диалоговое окно, чтобы задать пользователю вопрос (3) Создание и публикация пользовательского события (4) закройте wxFrame (5) некоторые другие процессы кода пользовательское событие


Я думаю, что у меня была та же проблема, что и у вас. Вместо того, чтобы сделать это всплывающее окно рамкой, я сделал его диалогом. Я сделал пользовательский диалог, унаследовав wx.диалог вместо wx.рамка. Затем вы можете использовать код, который Хоакин выложил выше. Проверьте возвращаемое значение диалогового окна, чтобы увидеть, что было введено. Это можно сделать, сохранив значение textctrl, когда пользователь нажимает ok в локальную переменную. Затем, прежде чем он будет уничтожен, вы каким-то образом получите эту ценность.

в раздел пользовательского диалога этого сайта очень помог мне. http://zetcode.com/wxpython/dialogs/