wxpython выполните действие перед закрытием wx.EVT_CLOSE

#python-3.x #wxpython #wxgrid

Вопрос:

У меня есть фрейм, содержащий сетку, строки которой заполнены данными из моего api, поэтому пользователь редактирует данные из сетки, и я хочу, чтобы они были сохранены, когда пользователь закроет, нажмите X, чтобы закрыть фрейм, поэтому я делаю это

 title = "Datos"

    def __init__(self,title,parent=None):
        wx.Frame.__init__(self, parent=parent, title=title)
        user=self.get_ser()
        self.Show()
        panel=wx.Panel(self, -1)
        myGrid = gridlib.Grid(panel)
        user_data = json.loads(self.decrypt(self.get_data(user)))
        print(user_data)
        myGrid.CreateGrid(len(user_data), 3)
        
        myGrid.SetColLabelValue(0, "WEB")
        myGrid.SetColLabelValue(1, "USERNAME")
        myGrid.SetColLabelValue(2, "PASSWORD")
        for i in range(0,len(user_data)):
            myGrid.SetCellValue(i, 0, user_data[i]["web"])
            myGrid.SetCellValue(i, 1, user_data[i]["username"])
            myGrid.SetCellValue(i, 2, user_data[i]["password"])
        
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(myGrid, 1, wx.EXPAND)
        panel.SetSizer(sizer)
        self.SetBackgroundColour(wx.Colour(100,100,100))
        self.Centre()
        self.Show()
        self.Bind(wx.EVT_CLOSE, self.OnClose(myGrid,user_data))
    def OnClose(self, myGrid,user_data):
        dlg = wx.MessageDialog(self, 
            "Do you really want to close this application?",
            "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
        result = dlg.ShowModal()
        dlg.Destroy()
        if result == wx.ID_OK:
            self.savedata(myGrid,user_data)
            self.Destroy()
    def savedata(self, myGrid,user_data):
        for i in range(0,(len(user_data))):
            print(myGrid.GetCellValue(i,0) " " myGrid.GetCellValue(i,1) " " myGrid.GetCellValue(i,2))
 

моя проблема в том, что при открытии кадра появляется всплывающее диалоговое окно, и я передаю myGrid, чтобы он мог читать содержимое каждой строки, когда пользователь закрывает кадр, чтобы я мог сохранить данные, в настоящее время я печатаю данные на консоли, чтобы проверить их

всплывающее диалоговое окно


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

открытая рама

Ответ №1:

  1. У вас есть ошибка self.Show в начале вашего кода.
  2. EVENT_CLOSE Отправляет event , поэтому вы не можете просто добавить что-то в параметры вызываемой подпрограммы (без использования lambda )
  3. Если вы создаете myGrid член экземпляра класса , т. е. объявляете его self.myGrid , он доступен для запроса и изменения. Объявив его как myGrid просто local переменную.

Если мы объединим это вместе с издевательской и измененной версией вашего кода, мы получим следующее:

 import wx
import wx.grid as gridlib


class MainFrame(wx.Frame): 
    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title)
        #user=self.get_ser()
        panel=wx.Panel(self, -1)
        self.myGrid = gridlib.Grid(panel)
        #user_data = json.loads(self.decrypt(self.get_data(user)))
        user_data = [["web1","user1","password1"],["web1","user2","password2"],["web3","user3","password3"]]
        print(user_data)
        self.myGrid.CreateGrid(len(user_data), 3)
        
        self.myGrid.SetColLabelValue(0, "WEB")
        self.myGrid.SetColLabelValue(1, "USERNAME")
        self.myGrid.SetColLabelValue(2, "PASSWORD")
        for i in range(0,len(user_data)):
            self.myGrid.SetCellValue(i, 0, user_data[i][0])
            self.myGrid.SetCellValue(i, 1, user_data[i][1])
            self.myGrid.SetCellValue(i, 2, user_data[i][2])
        
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.myGrid, 1, wx.EXPAND)
        panel.SetSizer(sizer)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.SetBackgroundColour(wx.Colour(100,100,100))
        self.Centre()
        self.Show()

    def OnClose(self, event):
        dlg = wx.MessageDialog(self, 
            "Do you really want to close this application?",
            "Confirm Exit", wx.OK|wx.CANCEL|wx.ICON_QUESTION)
        result = dlg.ShowModal()
        dlg.Destroy()
        if result == wx.ID_OK:
            self.savedata()
            self.Destroy()

    def savedata(self):
        gr = self.myGrid.GetNumberRows()
        for i in range(0,(gr)):
            print(self.myGrid.GetCellValue(i,0) " " self.myGrid.GetCellValue(i,1) " " self.myGrid.GetCellValue(i,2))

app = wx.App()
MainFrame(None, "Data")
app.MainLoop()
 

Как вы можете видеть OnClose , принимает событие, суть здесь в том, что в данном случае вы знаете, откуда исходит событие и что это Близкое событие.

Подпрограмме savedata, также в этом случае, не нужно знать, что сохранять, есть только myGrid. Тем не менее, мы могли бы отправить event object , если бы были какие-либо сомнения, или вызвать разные процедуры сохранения для разных объектов.

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

N. B. Возможно, вы захотите рассмотреть вариант, при котором вы откажетесь от редактирования и выйдете. В нынешнем виде это сохранение, иначе вы обречены редактировать данные навсегда.

введите описание изображения здесь

Результат экономии:

 web1 user1 password1
Stackoverflow.com Rodrigo xXx
web3 user3 password3
 

Комментарии:

1. оооо, я делал это плохим способом, исправил это с вашей помощью, большое вам спасибо!