私は wxPython アプリケーション (以下のドキュメント) を作成しました。チェックボックスやテキストラインなど、私が望むすべての方法があります。唯一の問題は、これをアプリケーションのメイン フレームとして作成したことです。
私が本当に望んでいるのは、これをウィジェットに変換して、最終的なアプリケーション フレームでそれらのいくつかをインスタンス化できるようにすることです。しかし、wx.Frame ではなく wx.Panel からウィジェットを継承させてから、ウィジェットを Frame クラスにインスタンス化しようとすると、中性子星のように崩壊しました。
私の 2 つのコード例を見て、何が問題なのかを確認してください。
これは、私のウィジェットが 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()
次に、これをカスタム ウィジェットにして、そのうちの 1 つを 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()
繰り返しますが、最初のコード サンプルは基本的に希望どおりに動作しますが、最終的なプログラムでは 1 つのウィジェットにする必要があります。wx.Frame から継承するクラスでそれをインスタンス化しようとすると、書式設定が消えてすべてが重なり合うのはなぜですか?
よろしくお願いします。他に提供する必要がある情報があれば教えてください。