微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

wxPython - 无法在 __init__ 中调用类方法

如何解决wxPython - 无法在 __init__ 中调用类方法

我知道这可能是一个基本问题,但我刚刚进入 GUI 构建领域,不需要在课堂上涉足太多。我有一些代码(见下文)来处理程序的 GUI 部分(CLI 版本已经完美运行,但是每当他们看到 CLI 时管理就会跑山……),但我无法完全理解锻炼。仅供参考,在 Windows 10 上运行 python 3.9.1 和 wxPython 4.1.1 Phoenix(尽管 wx.version 也会吐出 wxWidgets 3.1.5,如果相关的话)

很多代码都是基于示例/其他人在这里问的东西,不幸的是我找不到原始帖子来感谢他们,但这真的只是为了学习,一旦我掌握了我的东西'我正在做我将从头开始写所有东西。所以对于原作者,我深表歉意,但我非常感谢你!

该程序将显示一个“开始”屏幕(框架),只有一个标题一个按钮。单击该按钮时,将打开一个模式文件对话框,用户可以在其中选择要使用的 .csv 数据文件,起始帧消失,并在右侧窗格中(在网格调整器中)出现一个带有数据视图的新帧和左窗格中的一些下拉菜单和单选按钮。最后一个下拉列表 (self.inputNum) 将绑定到一个事件处理程序,该事件处理程序将添加许多额外的下拉列表供用户选择要分析的不同目标(课程数量由他们在self.inputNum 组合框)。但是,在运行脚本时,出现错误

Traceback (most recent call last):
  File "C:\Python\Scripts\wxLOD_2class_panelbased.py",line 98,in _OnStart
    self.frm2 = Frame2(None)
  File "C:\Python\Scripts\wxLOD_2class_panelbased.py",line 154,in __init__
    self.CreateGrid(datalist,cols)
AttributeError: 'Frame2' object has no attribute 'CreateGrid'

在这里搜索,发现有人有类似的问题(在同一类的 init调用方法),但“正确”的答案是使用 {{ 1}}(OP 一直称它为 self.classmethodname(args),我已经在这样做了。

为草率的格式提前道歉。我试图尽可能地清理它,但由于我不知道错误来自哪里,我不想偏离我用来构建我目前拥有的混乱的(工作)示例太远。请参阅下面的我的脚本、我基于“Frame2”的稍微修改的脚本以及屏幕截图。

我的代码(我知道在一行中导入模块是不受欢迎的,但我为这篇文章压缩了很多):

classmethodname(args)

我基于我的“Frame2”的稍微编辑但有效的代码如下(不知道他为什么把它分成 3 个类,或者 import os,sys,csv,time,math,warnings,collections,wx,wx.grid,scipy import numpy as np import matplotlib.pyplot as plt import win32gui as wg import pandas as pd from datetime import datetime from scipy.stats import norm from tkinter import filedialog from tkinter import * from decimal import * pd.options.mode.chained_assignment = None # default='warn' class StartFrame(wx.Frame): """App controller class""" FRAME_MIN_SIZE = (900,600) def __init__(self,parent): wx.Frame.__init__(self,parent=parent,id=wx.ID_ANY,title="LOD Calculator",size=wx.Size(900,600),style=wx.CAPTION|wx.CLOSE_Box|wx.MINIMIZE_Box|wx.SYstem_MENU|wx.TAB_TRAVERSAL) self.SetSizeHints(wx.DefaultSize,wx.DefaultSize) self.startpnl = wx.Panel(self) self.startvsizer = wx.BoxSizer(wx.VERTICAL) self.startbtnsizer = wx.BoxSizer(wx.HORIZONTAL) # make title and subtitle,format fonts self.st = wx.StaticText(self.startpnl,style=wx.ALIGN_CENTER,label="DCB LoD Calculator") self.font = self.st.GetFont() self.font.PointSize += 10 self.font = self.font.Bold() self.st.SetFont(self.font) self.stsub = wx.StaticText(self.startpnl,label="Probit/Linear Regression Method") self.fontsub = self.stsub.GetFont() self.fontsub.PointSize += 2 self.stsub.SetFont(self.fontsub) # make the "begin" button to start the script self.btn = wx.Button(self.startpnl,wx.ID_ANY,"Start Analysis",\ size = (200,60)) self.btn.Bind(wx.EVT_BUTTON,self._OnStart) self.startbtnsizer.AddStretchSpacer() self.startbtnsizer.Add(self.btn,wx.CENTER) self.startbtnsizer.AddStretchSpacer() self.startvsizer.Add(self.st,wx.SizerFlags().Expand().Border(wx.ALL,25)) self.startvsizer.Add(self.stsub,25)) self.startvsizer.AddStretchSpacer() self.startvsizer.Add(self.startbtnsizer,25)) self.startvsizer.AddStretchSpacer() self.startpnl.SetSizerAndFit(self.startvsizer) # create a menu & status bar self.makeMenuBar() self.CreateStatusBar() self.SetStatusText("PLACEHOLDER -- STATUS BAR") self.Center(wx.BOTH) def makeMenuBar(self): fileMenu = wx.Menu() helloItem = fileMenu.Append(-1,"&Hello...\tCtrl-H","Help string shown in status bar for this menu item") fileMenu.AppendSeparator() exitItem = fileMenu.Append(wx.ID_EXIT) helpMenu = wx.Menu() aboutItem = helpMenu.Append(wx.ID_ABOUT) menuBar = wx.MenuBar() menuBar.Append(fileMenu,"&File") menuBar.Append(helpMenu,"&Help") self.SetMenuBar(menuBar) self.Bind(wx.EVT_MENU,self.OnHello,helloItem) self.Bind(wx.EVT_MENU,self.OnExit,exitItem) self.Bind(wx.EVT_MENU,self.OnAbout,aboutItem) def OnExit(self,event): """Close frame & terminate app""" self.Close(True) def OnHello(self,event): """oh hey what's up""" wx.MessageBox("Stuff would go here",\ "The dialog with the stuff would have this title") def OnAbout(self,event): """for displaying 'about' dialog""" wx.MessageBox("Main dialog Box text for About",\ "About title text",wx.OK|wx.ICON_informatION) def _OnStart(self,event): self.Hide() self.frm2 = Frame2(None) self.frm2.Show() class Frame2(wx.Frame): """Data load frame""" FRAME_MIN_SIZE = (900,style=wx.CAPTION|wx.CLOSE_Box|wx.MINIMIZE_Box|wx.SYstem_MENU|wx.TAB_TRAVERSAL) self.SetSizeHints(wx.DefaultSize,wx.DefaultSize) self.dirname = os.getcwd() filedlg = wx.FileDialog(self,'Choose a file',os.getcwd(),\ '','CSV files (*.csv)|*.csv|All files(*.*)|*.*',wx.FD_OPEN) if filedlg.ShowModal() == wx.ID_OK: self.dirname = filedlg.GetDirectory() self.filename = filedlg.GetFilename() self.path = os.path.join(self.dirname,self.filename) self.file = open(self.path,'r') dialect = csv.Sniffer().sniff(self.file.read(1024),\ delimiters = ";|,") self.file.seek(0) csvfile = csv.reader(self.file,dialect) filedata = [] filedata.extend(csvfile) self.file.seek(0) datasample = self.file.read(2048) self.file.seek(0) if csv.Sniffer().has_header(datasample): self.cols = next(csvfile) self.datalist = [] self.datalist.extend(filedata[1:len(filedata)]) else: self.cols = [] for idx in range(len(next(csvfile))): self.cols.append(f'col_{i}') self.file.seek(0) self.datalist = filedata self.file.close() # Create Sizers Sizer1 = wx.BoxSizer(wx.HORIZONTAL) paraLsizer = wx.BoxSizer(wx.VERTICAL) paraRsizer = wx.BoxSizer(wx.VERTICAL) # Create Panels self.paraLpnl = wx.Panel(self,wx.DefaultPosition,\ wx.DefaultSize,wx.TAB_TRAVERSAL) self.pararpnl = wx.Panel(self,wx.TAB_TRAVERSAL) ### FOLLOWING LINE SPITS THE ERROR ### HAVE TRIED USING BOTH self.datalist/self/cols AND JUST datalist/cols - NO EFFECT self.CreateGrid(self.datalist,self.cols) # Create Widgets self.reImportButton = wx.Button(self.paraLpnl,\ wx.ID_ANY,u"Import New CSV File",0) self.paraInput = wx.StaticText(self.paraLpnl,\ label="Select input column:",style = wx.ALIGN_CENTER_HORIZONTAL) self.inputcb = wx.ComboBox(self.paraLpnl,value=cols[0],\ choices=cols,style = wx.CB_READONLY) self.logbtn = wx.RadioButton(self.paraLpnl,label='Check button\ if input is in log10(conc.)') self.logbtn.SetValue(False) numInputs = ['1','2','3','4','5','6','7','8','9'] self.inputNumLabel = wx.StaticText(self.paraLpnl,\ label="Select number of targets",style = wx.ALIGN_CENTER_HORIZONTAL) self.inputNum = wx.ComboBox(self.paraLpnl,value='',\ choices = numInputs,style = wx.CB_READONLY) # Add stuff to sub-sizers,set them,and fit stuff paraLsizer.Add(self.reImportButton,wx.ALL,5) paraLsizer.Add(self.paraInput,5) paraLsizer.Add(self.inputcb,5) paraLsizer.Add(self.logbtn,5) paraLsizer.Add(self.inputNumLabel,5) paraLsizer.Add(self.inputNum,5) self.paraLpnl.SetSizer(paraLsizer) self.paraLpnl.Layout() paraLsizer.Fit(self.paraLpnl) paraRsizer.Add(self.grid,1,wx.EXPAND) self.pararpnl.SetSizer(paraRsizer) self.pararpnl.Layout() paraRsizer.Fit(self.pararpnl) # Add panels (containing sub-sizers) to main sizer Sizer1.Add(self.paraLpnl,wx.EXPAND |wx.BottOM,5) Sizer1.Add(self.pararpnl,wx.EXPAND |wx.ALL,5) # Set main sizer for the window; add status and menu bars self.SetSizer(Sizer1) StartFrame.makeMenuBar(self) StartFrame.CreateStatusBar(self) StartFrame.SetStatusText(self,"PLACEHOLDER -- STATUS BAR") # Finally,lay the whole window out and center it. self.Layout() self.Centre(wx.BOTH) #create the grid def createGrid(self,datalist,colnames): if getattr(self,'grid',0): self.grid.Destroy() self.grid = wx.grid.Grid(self.pararpnl,0) self.grid.CreateGrid(len(datalist),len(colnames)) #create grid,same size as file (rows,cols) #fill in headings for i in range(len(colnames)): self.grid.SetColLabelValue(i,colnames[i]) #populate the grid for row in range(len(datalist)): for col in range(len(colnames)): try: self.grid.SetCellValue(row,col,datalist[row][col]) except: pass self.grid.AutoSizeColumns(False) # size columns to data (from cvsomatic.py) self.twiddle() def twiddle(self): x,y = self.GetSize() self.SetSize((x,y+1)) self.SetSize((x,y)) def Exit(self,event): if getattr(self,'file',0): self.file.close() self.Close(True) import wx.lib.mixins.inspection app = wx.App() frm = StartFrame(None) frm.Show() wx.lib.inspection.inspectionTool().Show() app.MainLoop() 类的用途是什么):

csv_view(wx.App)

我的应用程序启动时的屏幕(在您尝试在“开始分析”按钮产生的模式对话框中选择 .csv 文件之前一直有效)、我用来引导第二帧打开的应用程序,以及相同的导入 csv 后的应用程序。

My start screen

His start screen

His screen after selecting a .csv with the left button

此外,任何不直接涉及我的问题的改进/建议/更正都非常受欢迎。我是开发这方面的新手,需要我能得到的所有帮助!

解决方法

抱歉各位,当函数被定义为 CreateGrid() 时,我的咖啡前大脑正在调用 createGrid()。代码中还有一些其他错误(引用我不再实现的按钮的事件处理程序、从不同的类调用 StartFrame.makeMenuBar 而不导入调用的函数 StartFrame.makeMenuBar 等)。>

但仍然可以随意指出我正在做的低效率和冗余以及其他各种非 Pythonic 的事情。还在学习:)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。