我已经编写了一个 wxPython 应用程序(遵循文档),它几乎可以完成我想要的一切。它有我想要的所有方式的复选框和文本行等。唯一的问题是我把它作为我的应用程序的主要框架。
我真正想要的是把它变成一个小部件,这样我就可以在我的最终应用程序框架中实例化其中的一些。然而,当我试图让我的小部件从 wx.Panel 而不是 wx.Frame 继承,然后将一个小部件实例化到我的 Frame 类中时,它像中子星一样自行塌陷。
请看一下我的两个代码示例,看看你是否知道出了什么问题。
这是我的小部件直接在从 wx.Frame 继承的类中构建的版本:
#!/usr/bin/env python
"""
This demo attempts to override the C++ MainLoop and implement it
in Python.
"""
import time
import wx
import serial
from serial.tools.list_ports import comports
#str1 = '[12:28:14]fxn_name() ***ISCFLAGS***1***0***0***0***3.19***00-1C-FA-F1-00-09-F1-EE***\r\n'
logAll = 1
"""lowBat1 = 0
pir1 = 0
batVolt1 = 0
tamp1 = 0
supervise1 = 0
mac1 = 0"""
######################################################################################
class ETL_test(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(275, 200))
self.initGUI()
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
self.Show()
def initGUI(self):
#main container panel for all of the ISC status information
self.checkBoxPanel = wx.Panel(self,-1,size=(100,200),style= wx.SUNKEN_BORDER)
self.checkBoxVbox = wx.BoxSizer(wx.VERTICAL)
#make the three individual checkboxes
self.superviseCheck = wx.CheckBox(self.checkBoxPanel,-1,'Supervisory Trouble')
self.pirCheck = wx.CheckBox(self.checkBoxPanel,-1,'PIR Activity')
self.tamperCheck = wx.CheckBox(self.checkBoxPanel,-1,'Tamper Tripped')
#make the MAC hbox section
self.macHbox = wx.BoxSizer(wx.HORIZONTAL)
self.macLabel = wx.StaticText(self.checkBoxPanel,-1,'MAC ADDR: ')
macFont1 = wx.Font(10, wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD)
self.macLabel.SetFont(macFont1)
macFont2 = wx.Font(10, wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_NORMAL)
self.macAddr = wx.StaticText(self.checkBoxPanel,-1,'001CFAF10009F1EE')
self.macAddr.SetFont(macFont2)
self.macHbox.Add(self.macLabel,0,wx.RIGHT,5)
self.macHbox.Add(self.macAddr,0,0,0)
#make the low battery hbox section
self.lowBatCheck = wx.CheckBox(self.checkBoxPanel,-1,'Low Battery Voltage')
self.batVoltText = wx.StaticText(self.checkBoxPanel,-1, '9.9V')
self.lowBatHbox = wx.BoxSizer(wx.HORIZONTAL)
self.lowBatHbox.Add(self.lowBatCheck, 0,wx.RIGHT,20)
self.lowBatHbox.Add(self.batVoltText, 0,wx.ALL,0)
#make the pirCount hbox section
self.pirCountHbox = wx.BoxSizer(wx.HORIZONTAL)
self.pirCountNumber = 3
self.pirLabel = wx.StaticText(self.checkBoxPanel,-1,'PIR Count: ')
self.pirCount = wx.StaticText(self.checkBoxPanel,-1,str(self.pirCountNumber))
self.pirReset = wx.Button(self.checkBoxPanel,-1,label='Reset PIR Count')
self.pirCountHbox.Add(self.pirLabel,0,wx.RIGHT,3)
self.pirCountHbox.Add(self.pirCount,0,wx.RIGHT, 40)
self.pirCountHbox.Add(self.pirReset,0,wx.ALIGN_RIGHT,0)
self.pirReset.Bind(wx.EVT_BUTTON,self.resetPIR)
#add all the parts to the main vbox
self.checkBoxVbox.Add(self.macHbox,0,wx.ALL,5)
self.checkBoxVbox.Add(self.superviseCheck,0,wx.ALL,5)
self.checkBoxVbox.Add(self.lowBatHbox,0,wx.ALL,5)
self.checkBoxVbox.Add(self.tamperCheck,0,wx.ALL,5)
self.checkBoxVbox.Add(self.pirCheck,0,wx.ALL,5)
self.checkBoxVbox.Add(self.pirCountHbox,0,wx.ALL,5)
self.checkBoxPanel.SetSizer(self.checkBoxVbox)
#setup the 1 sec timer to update all the data based on the global data
#self.updateTimer = wx.Timer(self)
#self.Bind(wx.EVT_TIMER,self.updateData,self.updateTimer)
#self.updateTimer.Start(500)
#The event handler for pushing the PIR reset button
def resetPIR(self,event):
self.pirCountNumber = 0
self.pirCount.SetLabel(str(self.pirCountNumber))
self.Show()
#The event handler for the 1 sec timer to update the data fields based on last flags msg
## def updateData(self,event):
## global batVolt1
## self.pirCountNumber += 1;
## self.pirCount.SetLabel(str(self.pirCountNumber))
## self.batVoltText.SetLabel(str(batVolt1)+'V')
#The event handler for closing the window
def OnCloseWindow(self, event):
app.keepGoing = False
self.Destroy()
logFile.close()
def updateOnSerial(self,flags):
self.superviseCheck.SetValue(flags[0] == 1)
self.pirCheck.SetValue(flags[1] == 1)
if flags[1] == 1:
self.pirCountNumber += 1
self.pirCount.SetLabel(str(self.pirCountNumber))
self.tamperCheck.SetValue(flags[2] == 1)
self.lowBatCheck.SetValue(flags[3] == 1)
self.batVoltText.SetLabel(str(flags[4])+'V')
self.macAddr.SetLabel(str(flags[5]))
#####################################################################################
class MyApp(wx.App):
def MainLoop(self):
# Create an event loop and make it active
evtloop = wx.EventLoop()
old = wx.EventLoop.GetActive()
wx.EventLoop.SetActive(evtloop)
# This outer loop determines when to exit the application
while self.keepGoing:
# call_my_code_here()
line = ser.readline()
parsedLines = line.split('***')
global logAll
if len(parsedLines) > 4 and parsedLines[1] == 'ISCFLAGS': #got a flags msg
print('Now parsing a ISCFLAGS msg!')
self.parseFlagsMsg(parsedLines)
logFile.write(str(line))
elif logAll > 0 and len(parsedLines) < 2: #logAll is on and it's not a flags msg
logFile.write(str(line))
# This inner loop will process any GUI events
# until there are no more waiting.
while evtloop.Pending():
evtloop.Dispatch()
# Send idle events to idle handlers.
# I'll just snooze a little...
time.sleep(0.10)
self.ProcessIdle()
wx.EventLoop.SetActive(old)
def parseFlagsMsg(self):
global lowBat1
global pir1
global batVolt1
global tamp1
global supervise1
global mac1
if len(parsedLines) != 10:
print('ERROR: not enough flag tokens!!')
return False
else:
camID = parsedLines[2];#1,2, or 3
# TODO: array of testApps... testApp[camID].updateOnSerial()
# This passes the 4th element through the 8th element
testApp.updateOnSerial(parsedLines[3:8])
def OnInit(self):
testApp = ETL_test(None, -1, "Alarm.com 2GIG Image Sensor ETL Test Application")
testApp.Show(True)
self.SetTopWindow(testApp)
self.keepGoing = True
return True
app = MyApp(False)
logFile = open('C:/Python26/temp/test.txt', 'w')
ser = serial.Serial('com5',115200,timeout=0.01)
app.MainLoop()
然后这是我尝试将其设为自定义小部件的版本,然后在我的 wx.Frame 类中实例化其中一个:
#!/usr/bin/env python
"""
This demo attempts to override the C++ MainLoop and implement it
in Python.
"""
import time
import wx
import serial
from serial.tools.list_ports import comports
str1 = '[12:28:14]fxn_name() ***ISCFLAGS***1***0***0***0***3.19***00-1C-FA-F1-00-09-F1-EE***\r\n'
logAll = 1
"""lowBat1 = 0
pir1 = 0
batVolt1 = 0
tamp1 = 0
supervise1 = 0
mac1 = 0"""
#---------------------------------------------------------------------------
class ISC_status(wx.Panel):
def __init__(self, parent, id):
wx.Panel.__init__(self, parent, id, size=(275, 200))
self.initGUI()
#self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
self.Show()
def initGUI(self):
#main container panel for all of the ISC status information
self.checkBoxPanel = wx.Panel(self,-1,size=(100,200),style= wx.SUNKEN_BORDER)
self.checkBoxVbox = wx.BoxSizer(wx.VERTICAL)
#make the three individual checkboxes
self.superviseCheck = wx.CheckBox(self.checkBoxPanel,-1,'Supervisory Trouble')
self.pirCheck = wx.CheckBox(self.checkBoxPanel,-1,'PIR Activity')
self.tamperCheck = wx.CheckBox(self.checkBoxPanel,-1,'Tamper Tripped')
#make the MAC hbox section
self.macHbox = wx.BoxSizer(wx.HORIZONTAL)
self.macLabel = wx.StaticText(self.checkBoxPanel,-1,'MAC ADDR: ')
macFont1 = wx.Font(10, wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_BOLD)
self.macLabel.SetFont(macFont1)
macFont2 = wx.Font(10, wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_NORMAL)
self.macAddr = wx.StaticText(self.checkBoxPanel,-1,'001CFAF10009F1EE')
self.macAddr.SetFont(macFont2)
self.macHbox.Add(self.macLabel,0,wx.RIGHT,5)
self.macHbox.Add(self.macAddr,0,0,0)
#make the low battery hbox section
self.lowBatCheck = wx.CheckBox(self.checkBoxPanel,-1,'Low Battery Voltage')
self.batVoltText = wx.StaticText(self.checkBoxPanel,-1, '9.9V')
self.lowBatHbox = wx.BoxSizer(wx.HORIZONTAL)
self.lowBatHbox.Add(self.lowBatCheck, 0,wx.RIGHT,20)
self.lowBatHbox.Add(self.batVoltText, 0,wx.ALL,0)
#make the pirCount hbox section
self.pirCountHbox = wx.BoxSizer(wx.HORIZONTAL)
self.pirCountNumber = 3
self.pirLabel = wx.StaticText(self.checkBoxPanel,-1,'PIR Count: ')
self.pirCount = wx.StaticText(self.checkBoxPanel,-1,str(self.pirCountNumber))
self.pirReset = wx.Button(self.checkBoxPanel,-1,label='Reset PIR Count')
self.pirCountHbox.Add(self.pirLabel,0,wx.RIGHT,3)
self.pirCountHbox.Add(self.pirCount,0,wx.RIGHT, 40)
self.pirCountHbox.Add(self.pirReset,0,wx.ALIGN_RIGHT,0)
self.pirReset.Bind(wx.EVT_BUTTON,self.resetPIR)
#add all the parts to the main vbox
self.checkBoxVbox.Add(self.macHbox,0,wx.ALL,5)
self.checkBoxVbox.Add(self.superviseCheck,0,wx.ALL,5)
self.checkBoxVbox.Add(self.lowBatHbox,0,wx.ALL,5)
self.checkBoxVbox.Add(self.tamperCheck,0,wx.ALL,5)
self.checkBoxVbox.Add(self.pirCheck,0,wx.ALL,5)
self.checkBoxVbox.Add(self.pirCountHbox,0,wx.ALL,5)
self.checkBoxPanel.SetSizer(self.checkBoxVbox)
#setup the 1 sec timer to update all the data based on the global data
#self.updateTimer = wx.Timer(self)
#self.Bind(wx.EVT_TIMER,self.updateData,self.updateTimer)
#self.updateTimer.Start(500)
#The event handler for pushing the PIR reset button
def resetPIR(self,event):
self.pirCountNumber = 0
self.pirCount.SetLabel(str(self.pirCountNumber))
self.Show()
#The event handler for the 1 sec timer to update the data fields based on last flags msg
## def updateData(self,event):
## global batVolt1
## self.pirCountNumber += 1;
## self.pirCount.SetLabel(str(self.pirCountNumber))
## self.batVoltText.SetLabel(str(batVolt1)+'V')
def updateOnSerial(self,flags):
self.superviseCheck.SetValue(flags[0] == 1)
self.pirCheck.SetValue(flags[1] == 1)
if flags[1] == 1:
self.pirCountNumber += 1
self.pirCount.SetLabel(str(self.pirCountNumber))
self.tamperCheck.SetValue(flags[2] == 1)
self.lowBatCheck.SetValue(flags[3] == 1)
self.batVoltText.SetLabel(str(flags[4])+'V')
self.macAddr.SetLabel(str(flags[5]))
#---------------------------------------------------------------------------
class ETL_test(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(275, 200))
self.initGUI()
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
self.Show()
def initGUI(self):
panel = wx.Panel(self)
ISC1 = ISC_status(self,-1)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(ISC1,1,wx.ALL|wx.EXPAND,5)
panel.SetSizer(sizer)
self.Layout()
self.Show()
#The event handler for closing the window
def OnCloseWindow(self, event):
app.keepGoing = False
self.Destroy()
logFile.close()
#---------------------------------------------------------------------------
class MyApp(wx.App):
def MainLoop(self):
# Create an event loop and make it active
evtloop = wx.EventLoop()
old = wx.EventLoop.GetActive()
wx.EventLoop.SetActive(evtloop)
# This outer loop determines when to exit the application
while self.keepGoing:
# call_my_code_here()
line = ser.readline()
parsedLines = line.split('***')
global logAll
if len(parsedLines) > 4 and parsedLines[1] == 'ISCFLAGS': #got a flags msg
print('Now parsing a ISCFLAGS msg!')
self.parseFlagsMsg(parsedLines)
logFile.write(str(line))
elif logAll > 0 and len(parsedLines) < 2: #logAll is on and it's not a flags msg
logFile.write(str(line))
# This inner loop will process any GUI events
# until there are no more waiting.
while evtloop.Pending():
evtloop.Dispatch()
# Send idle events to idle handlers.
# I'll just snooze a little...
time.sleep(0.10)
self.ProcessIdle()
wx.EventLoop.SetActive(old)
def parseFlagsMsg(self):
global lowBat1
global pir1
global batVolt1
global tamp1
global supervise1
global mac1
if len(parsedLines) != 10:
print('ERROR: not enough flag tokens!!')
return False
else:
camID = parsedLines[2];#1,2, or 3
# TODO: array of testApps... testApp[camID].updateOnSerial()
# This passes the 4th element through the 8th element
testApp.updateOnSerial(parsedLines[3:8])
def OnInit(self):
testApp = ETL_test(None, -1, "Alarm.com 2GIG Image Sensor ETL Test Application")
testApp.Show(True)
self.SetTopWindow(testApp)
self.keepGoing = True
return True
app = MyApp(False)
logFile = open('C:/Python26/temp/test.txt', 'w')
ser = serial.Serial('com5',115200,timeout=0.01)
app.MainLoop()
重申一下:第一个代码示例基本上可以按我的意愿工作,但这需要是我最终程序中的一个小部件。为什么当我尝试在从 wx.Frame 继承的类中实例化它时,格式会消失并且所有内容都位于彼此之上?
在此先感谢您的帮助。如果我需要提供任何其他信息,请告诉我。