wxpython如何动态演示冒泡排序过程

海蓝天蓝 2013-01-17 11:57:53
各位大侠,

有没有好的建议如何用wxpython动态地演示一个排序算法的过程?目前我的程序能自动地产生random高度的长方体,但是我想用bubble sort比较长方体的高度来进行排序,涉及到erase 长方体,然后redraw。我的思路想到这就卡住了。求各位大神帮帮忙。下面是我的代码
万分感谢
import wx
import random

size = 30
xPos = 50
BarData = []
width = 900/(size*2)
gap = 900/(size*4)

class TopPanel(wx.Panel):
def __init__(self,parent):
wx.Panel.__init__(self,parent)

self.GenerateBarData(xPos)
self.Bind(wx.EVT_PAINT, self.OnPaint)
if size != 50:
self.SetStaticText()

#generate the original bars's data (x,y,w,h)
def GenerateBarData(self,xPos):
for num in range(size):
xPos += (width + gap)
height = random.randrange(1,300)
barParameters=[xPos, 300, width, height]
BarData.append(barParameters)
print BarData[num]
#revert the bars' yPos
self.RevertBarData()


def RevertBarData(self):
maxH = self.maxHeight()
for h in range(size):
moveH = maxH - BarData[h][3]
yPos = BarData[h][1]
yPos += moveH
BarData[h][1] = yPos

#return the hightest height in bars
def maxHeight(self):
Height = []
#store all the bar height in Height[]
for h in range(size):
Height.append(BarData[h][3])
#find out the heightest bar and return
maxH = max(Height)
return maxH

def OnPaint(self, event):
dc = wx.PaintDC(self)
self.paintBox(dc)

def paintBox(self, dc):
print len(BarData)
dc.SetBrush(wx.Brush("green"))

for box in range(0,size):
dc.DrawRectangle(*BarData[box])

#set the static text under bars according there height
def SetStaticText(self):
for i in range(size):
x = BarData[i][0]
y = BarData[i][1] + BarData[i][3]
h = str(BarData[i][3])
text = wx.StaticText(self, -1, h, pos=(x,y), size=(width,1), style = wx.ALIGN_LEFT)
font = wx.Font(8, wx.DEFAULT, wx.ITALIC, wx.NORMAL)
text.SetFont(font)

#bubble sort
def BubbleSort(self):
swapped = True
while swapped:
swapped = False
for i in range(len(BarData)-1):
if BarData[i][3] > BarData[i+1][3]:
BarData[i], BarData[i+1] = BarData[i+1], BarData[i]
swapped = True
print "after sort"
print BarData

class TopFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Bubble sort", size = (900,700))
TopPanel(self)

if __name__ == '__main__':
app = wx.App()
frame = TopFrame()
frame.Show()
#print BarData
app.MainLoop()
...全文
486 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
海蓝天蓝 2013-01-25
  • 打赏
  • 举报
回复
我又有问题啦,昨天我改了一下这个程序的gui,现在我的MainFrame里有2个panel,一个AnimationPanel用于演示排序过程的,一个SidePanel用于控制演示过程,可是这两个panel怎么进行交互呢?例如我的start button 在SidePanel里(SidePanel里又有好多小panel用来放别的控件),timer在AnimationPanel里,如果要start button控制AnimationPanel里演示过程,我要怎么调用呢?
附上我的code,还有目前程序的界面,code貌似有点长
昨天有半天都打不开csdn的论坛,今天终于又能进来啦
'''
Created on Jan 17, 2013

@author: Shannon
'''
import wx
import random


size = 30
xPos = 50
BarData = []
width = 900/(size*2)
gap = 900/(size*4)
delay = 100

class AnimationPanel(wx.Panel):

def __init__(self,parent,ID=-1,pos=(0,0),size=(750,500)):
wx.Panel.__init__(self,parent,ID,pos,size)
self.SetBackgroundColour("BLACK")

self.GenerateBarData(xPos)
self.Bind(wx.EVT_PAINT, self.OnPaint)

self.font = wx.Font(8, wx.DEFAULT, wx.ITALIC, wx.NORMAL)

self.timer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)


#generate the original bars's data (x,y,w,h)
def GenerateBarData(self,xPos):
for num in range(size):
xPos += (width + gap)
height = random.randrange(5,300)
barParameters=[xPos, 100, width, height]
BarData.append(barParameters)
self.RevertBarData()

#revert the bars' yPos
def RevertBarData(self):
maxH = self.maxHeight()
for h in range(size):
moveH = maxH - BarData[h][3]
yPos = BarData[h][1]
yPos += moveH
BarData[h][1] = yPos

#return the hightest height in bars
def maxHeight(self):
Height = []
#store all the bar height in Height[]
for h in range(size):
Height.append(BarData[h][3])
#find out the heightest bar and return
maxH = max(Height)
return maxH

def OnPaint(self, event):
dc = wx.PaintDC(self)
self.paintBox(dc)

def paintBox(self, dc):
dc.SetBrush(wx.Brush("green"))
dc.SetFont(self.font)
dc.SetTextForeground("GREEN")
for i in range(0,size):
dc.DrawRectangle(*BarData[i])
x = BarData[i][0]
y = BarData[i][1] + BarData[i][3]
h = str(BarData[i][3])
dc.DrawText(h, x, y)


#bubble sort
def BubbleSort(self):
for i in range(len(BarData), 1, -1):
for j in range(i-1):
if BarData[j][3] > BarData[j+1][3]:
BarData[j][1], BarData[j+1][1] = BarData[j+1][1], BarData[j][1]
BarData[j][3], BarData[j+1][3] = BarData[j+1][3], BarData[j][3]
yield

def OnTimer(self, event):
if not hasattr(self, 'g'):
self.g = self.BubbleSort()
try:
next(self.g)
except StopIteration:
del self.g
self.timer.Stop()
wx.MessageBox('Done!')

class SidePanel(wx.Panel):
def __init__(self,parent,ID=-1,pos=(750,0),size=(250,500)):
wx.Panel.__init__(self,parent,ID,pos,size)
self.SetBackgroundColour("GREY")

#---------------------------------------------
#create Button_Panel on Side_Panel
self.Button_Panel = wx.Panel(self, -1,pos=(750,0),size=(250,150))

#create ButtonSizer for button_panel
ButtonSizer = wx.GridSizer(rows = 2, cols = 2)
border = 3
#create 4 buttons label, add them to Button_Panel
#and binding them with corresponding event
buttonLabel = (("Start", self.OnStart),
("Step back", self.OnStepBack),
("Pause", self.OnPause),
("Step forward", self.OnStepForward))

for eachLabel, eachHandle in buttonLabel:
button = wx.Button(self.Button_Panel, -1, eachLabel)
button.Bind(wx.EVT_BUTTON, eachHandle)
ButtonSizer.Add(button, 0, wx.EXPAND|wx.ALL, border)
self.Button_Panel.SetSizer(ButtonSizer)

#---------------------------------------------

#---------------------------------------------
#Create ChoiceList_Panel for 2 choice dropdown list
#Sort_List: provide choice of sorting algorithm
#Graph_List: provide choice of graph algorithm
self.ChoiceList_Panel = wx.Panel(self, -1, pos=(750,150),size=(250,150))

SortList = ['Bubble Sort','Insertion Sort','Merge Sort',
'Quick Sort','Selection Sort','Shell Sort']
GraphList = ['Breath-First Search', 'Depth-First Search',
'Dijkstra\'s Shortest Path', 'Prim\'s minimun spanning tree']
#wx.Choice(parent,id,pos,size,choices,style,validator,name)
SortChoice = wx.Choice(self.ChoiceList_Panel, -1,choices=SortList)
GraphChoice = wx.Choice(self.ChoiceList_Panel, -1, choices=GraphList)
al_tex = wx.StaticText(self.ChoiceList_Panel, -1, 'Select a sorting algorithm:')
graph_tex = wx.StaticText(self.ChoiceList_Panel, -1, 'Or a graph algorithm:')
ChoiceSizer = wx.BoxSizer(wx.VERTICAL)
ChoiceSizer.Add(al_tex,1,wx.EXPAND|wx.ALL)
ChoiceSizer.Add(SortChoice,1, wx.EXPAND|wx.ALL)
ChoiceSizer.Add(graph_tex,1,wx.EXPAND|wx.ALL)
ChoiceSizer.Add(GraphChoice,1,wx.EXPAND|wx.ALL)
self.ChoiceList_Panel.SetSizer(ChoiceSizer)
#---------------------------------------------

#---------------------------------------------
#create Size_Panel
#Provide a set of size RadioBox
self.Size_Panel = wx.Panel(self, -1, pos=(750,300),size=(250,100))
SizeList = ['5','10','15','20','25','30','35','40','45','50']
Size_RadioBox = wx.RadioBox(self.Size_Panel,-1,"Select size",wx.DefaultPosition,wx.DefaultSize,SizeList,5,wx.RA_SPECIFY_COLS)
SizeSizer = wx.BoxSizer(wx.VERTICAL)
SizeSizer.Add(Size_RadioBox,1, wx.EXPAND|wx.ALL)
self.Size_Panel.SetSizer(SizeSizer)
#---------------------------------------------

#---------------------------------------------
#create a Speed_Panel
#Speed_Panel contains a slider used for control the speed of animation
self.Speed_Panel = wx.Panel(self, -1, pos=(750,400),size=(250,100))
Speed_Slider = wx.Slider(self.Speed_Panel, -1,25,1,50,wx.DefaultPosition,(250,-1),wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_LABELS,name="Speed")
Speed_Slider.SetTickFreq(5,1)
Speed_tex = wx.StaticText(self.Speed_Panel, -1, "Change animation's speed")
Speed_Sizer = wx.BoxSizer(wx.VERTICAL)
Speed_Sizer.Add(Speed_tex,0,wx.EXPAND|wx.ALL)
Speed_Sizer.Add(Speed_Slider,0,wx.EXPAND|wx.ALL)
self.Speed_Panel.SetSizer(Speed_Sizer)
#---------------------------------------------

Side_PanelSizer = wx.BoxSizer(wx.VERTICAL)
Side_PanelSizer.Add(self.Button_Panel,0,wx.EXPAND)
Side_PanelSizer.Add(self.ChoiceList_Panel,0,wx.EXPAND)
Side_PanelSizer.Add(self.Size_Panel,0,wx.EXPAND)
Side_PanelSizer.Add(self.Speed_Panel,0,wx.EXPAND)
self.SetSizer(Side_PanelSizer)

def OnStart(self, event):
if not self.timer.IsRunning():
self.timer.Start(milliseconds=delay)
def OnStepBack(self, event):
pass
def OnPause(self, event):
if self.timer.IsRunning():
self.timer.Stop()
def OnStepForward(self, event):
pass

class MainFrame(wx.Frame):
def __init__(self):

wx.Frame.__init__(self, None, title="GUI",size=(1000,500))

#---------------------------------------------
#create 2 panels
#Animation_Panel---display the sorting animation
#Side_panels---display the buttons, comboBox, slider
self.Animation_Panel = AnimationPanel(self)
self.Side_Panel = SidePanel(self)

#---------------------------------------------
#arrange the two main panels in the main sizer for the MainFrame
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
mainSizer.Add(self.Animation_Panel, 1, wx.EXPAND)
mainSizer.Add(self.Side_Panel, 0, wx.EXPAND)
self.SetSizer(mainSizer)
mainSizer.Fit(self)
#---------------------------------------------


if __name__ == '__main__':
app = wx.App()
frame = MainFrame()
frame.Show()
app.MainLoop()
海蓝天蓝 2013-01-25
  • 打赏
  • 举报
回复
非常感谢 @bugs2k
bugs2k 2013-01-25
  • 打赏
  • 举报
回复
'''
Created on Jan 17, 2013

@author: Shannon
'''
import wx
import random


size = 30
xPos = 50
BarData = []
width = 900/(size*2)
gap = 900/(size*4)
delay = 100

class AnimationPanel(wx.Panel):
    
    def __init__(self,parent,ID=-1,pos=(0,0),size=(750,500)):
        wx.Panel.__init__(self,parent,ID,pos,size)
        self.SetBackgroundColour("BLACK")
        
        self.GenerateBarData(xPos)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
         
        self.font = wx.Font(8, wx.DEFAULT, wx.ITALIC, wx.NORMAL)
        
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
                
  
    #generate the original bars's data (x,y,w,h)    
    def GenerateBarData(self,xPos):               
        for num in range(size):           
            xPos += (width + gap)
            height = random.randrange(5,300)
            barParameters=[xPos, 100, width, height]
            BarData.append(barParameters)                  
        self.RevertBarData()
          
    #revert the bars' yPos      
    def RevertBarData(self):
        maxH = self.maxHeight()
        for h in range(size):            
            moveH = maxH - BarData[h][3]
            yPos = BarData[h][1]
            yPos += moveH
            BarData[h][1] = yPos
  
    #return the hightest height in bars
    def maxHeight(self):
        Height = []
        #store all the bar height in Height[]
        for h in range(size):
            Height.append(BarData[h][3])
        #find out the heightest bar and return
        maxH = max(Height)
        return maxH
      
    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.paintBox(dc)
      
    def paintBox(self, dc):
        dc.SetBrush(wx.Brush("green"))
        dc.SetFont(self.font)
        dc.SetTextForeground("GREEN")
        for i in range(0,size):
            dc.DrawRectangle(*BarData[i])
            x = BarData[i][0]
            y = BarData[i][1] + BarData[i][3]
            h = str(BarData[i][3])
            dc.DrawText(h, x, y)
             
                
    #bubble sort
    def BubbleSort(self):
        for i in range(len(BarData), 1, -1):
            for j in range(i-1):
                if BarData[j][3] > BarData[j+1][3]:
                    BarData[j][1], BarData[j+1][1] = BarData[j+1][1], BarData[j][1]
                    BarData[j][3], BarData[j+1][3] = BarData[j+1][3], BarData[j][3]
                    yield
                     
    def OnTimer(self, event):
        if not hasattr(self, 'g'):
            self.g = self.BubbleSort()
        try:
            next(self.g)
            self.Refresh()
        except StopIteration:
            del self.g
            self.timer.Stop()
            wx.MessageBox('Done!')
        
class SidePanel(wx.Panel):
    def __init__(self, parent, aPanel, ID=-1,pos=(750,0),size=(250,500)): 
        wx.Panel.__init__(self,parent,ID,pos,size)
        self.SetBackgroundColour("GREY")
        self._aPanel = aPanel
        
        #---------------------------------------------        
        #create Button_Panel on Side_Panel
        self.Button_Panel = wx.Panel(self, -1,pos=(750,0),size=(250,150))
        
        #create ButtonSizer for button_panel
        ButtonSizer = wx.GridSizer(rows = 2, cols = 2)
        border = 3
        #create 4 buttons label, add them to Button_Panel
        #and binding them with corresponding event
        buttonLabel = (("Start", self.OnStart),
                       ("Step back", self.OnStepBack),
                       ("Pause", self.OnPause),
                       ("Step forward", self.OnStepForward))
        
        for eachLabel, eachHandle in buttonLabel:
            button = wx.Button(self.Button_Panel, -1, eachLabel)
            button.Bind(wx.EVT_BUTTON, eachHandle)
            ButtonSizer.Add(button, 0, wx.EXPAND|wx.ALL, border)
        self.Button_Panel.SetSizer(ButtonSizer)
        
        #---------------------------------------------

        #---------------------------------------------
        #Create ChoiceList_Panel for 2 choice dropdown list
        #Sort_List: provide choice of sorting algorithm
        #Graph_List: provide choice of graph algorithm
        self.ChoiceList_Panel = wx.Panel(self, -1, pos=(750,150),size=(250,150))
       
        SortList = ['Bubble Sort','Insertion Sort','Merge Sort',
                       'Quick Sort','Selection Sort','Shell Sort']
        GraphList = ['Breath-First Search', 'Depth-First Search',
                     'Dijkstra\'s Shortest Path', 'Prim\'s minimun spanning tree']
        #wx.Choice(parent,id,pos,size,choices,style,validator,name)
        SortChoice = wx.Choice(self.ChoiceList_Panel, -1,choices=SortList)
        GraphChoice = wx.Choice(self.ChoiceList_Panel, -1, choices=GraphList)
        al_tex = wx.StaticText(self.ChoiceList_Panel, -1, 'Select a sorting algorithm:')
        graph_tex = wx.StaticText(self.ChoiceList_Panel, -1, 'Or a graph algorithm:')
        ChoiceSizer = wx.BoxSizer(wx.VERTICAL)
        ChoiceSizer.Add(al_tex,1,wx.EXPAND|wx.ALL)
        ChoiceSizer.Add(SortChoice,1, wx.EXPAND|wx.ALL)
        ChoiceSizer.Add(graph_tex,1,wx.EXPAND|wx.ALL)
        ChoiceSizer.Add(GraphChoice,1,wx.EXPAND|wx.ALL)
        self.ChoiceList_Panel.SetSizer(ChoiceSizer)
        #---------------------------------------------

        #---------------------------------------------
        #create Size_Panel
        #Provide a set of size RadioBox
        self.Size_Panel = wx.Panel(self, -1, pos=(750,300),size=(250,100))
        SizeList = ['5','10','15','20','25','30','35','40','45','50']
        Size_RadioBox = wx.RadioBox(self.Size_Panel,-1,"Select size",wx.DefaultPosition,wx.DefaultSize,SizeList,5,wx.RA_SPECIFY_COLS)
        SizeSizer = wx.BoxSizer(wx.VERTICAL)
        SizeSizer.Add(Size_RadioBox,1, wx.EXPAND|wx.ALL)
        self.Size_Panel.SetSizer(SizeSizer)
        #---------------------------------------------

        #---------------------------------------------
        #create a Speed_Panel
        #Speed_Panel contains a slider used for control the speed of animation
        self.Speed_Panel = wx.Panel(self, -1, pos=(750,400),size=(250,100))
        Speed_Slider = wx.Slider(self.Speed_Panel, -1,25,1,50,wx.DefaultPosition,(250,-1),wx.SL_HORIZONTAL|wx.SL_AUTOTICKS|wx.SL_LABELS,name="Speed")
        Speed_Slider.SetTickFreq(5,1)
        Speed_tex = wx.StaticText(self.Speed_Panel, -1, "Change animation's speed")
        Speed_Sizer = wx.BoxSizer(wx.VERTICAL)
        Speed_Sizer.Add(Speed_tex,0,wx.EXPAND|wx.ALL)
        Speed_Sizer.Add(Speed_Slider,0,wx.EXPAND|wx.ALL)
        self.Speed_Panel.SetSizer(Speed_Sizer)
        #---------------------------------------------
        
        Side_PanelSizer = wx.BoxSizer(wx.VERTICAL)
        Side_PanelSizer.Add(self.Button_Panel,0,wx.EXPAND)
        Side_PanelSizer.Add(self.ChoiceList_Panel,0,wx.EXPAND)
        Side_PanelSizer.Add(self.Size_Panel,0,wx.EXPAND)
        Side_PanelSizer.Add(self.Speed_Panel,0,wx.EXPAND)
        self.SetSizer(Side_PanelSizer)
        
    def OnStart(self, event):
        self._aPanel.timer.Start(delay)
        pass
            
    def OnStepBack(self, event):
        pass

    def OnPause(self, event):
        self._aPanel.timer.Stop()
        pass

    def OnStepForward(self, event):
        pass
             
class MainFrame(wx.Frame):
    def __init__(self):
        
        wx.Frame.__init__(self, None, title="GUI",size=(1000,500))

        #---------------------------------------------       
        #create 2 panels
        #Animation_Panel---display the sorting animation
        #Side_panels---display the buttons, comboBox, slider
        self.Animation_Panel = AnimationPanel(self)
        self.Side_Panel = SidePanel(self, self.Animation_Panel)       

        #--------------------------------------------- 
        #arrange the two main panels in the main sizer for the MainFrame
        mainSizer = wx.BoxSizer(wx.HORIZONTAL)
        mainSizer.Add(self.Animation_Panel, 2, wx.EXPAND)
        mainSizer.Add(self.Side_Panel, 1, wx.EXPAND)
        self.SetSizer(mainSizer)
        mainSizer.Fit(self)
        #---------------------------------------------
        
        
if __name__ == '__main__':
    app = wx.App()
    frame = MainFrame()
    frame.Show()
    app.MainLoop()
bugs2k 2013-01-23
  • 打赏
  • 举报
回复
引用 15 楼 hailantianlanzx 的回复:
@bugs2k 我试了你po的3个代码,button可以启动timer,就是排序好像不是bubble sort了
import wx
import random
  
size = 30
xPos = 50
BarData = []
width = 900/(size*2)
gap = 900/(size*4)
delay = 100
  
class TopPanel(wx.Panel):
    def __init__(self,parent):
        wx.Panel.__init__(self,parent)
        self.GenerateBarData(xPos)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.font = wx.Font(8, wx.DEFAULT, wx.ITALIC, wx.NORMAL)
        self.toggleBtn = wx.Button(self, wx.ID_ANY,"Start")
        self.toggleBtn.Bind(wx.EVT_BUTTON, self.OnToggle)
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        self.bStart = False
        self.g = None

    def StartTimer(self):
        self.bStart = True
        self.timer.Start(delay)
        self.toggleBtn.SetLabel("Stop")

    def StopTimer(self):
        self.bStart = False
        self.timer.Stop()
        self.toggleBtn.SetLabel("Start")      

    def OnToggle(self, event):
        if self.bStart:
            self.StopTimer()
        else:
            self.StartTimer()

    def GenerateBarData(self,xPos):               
        for num in range(size):           
            xPos += (width + gap)
            height = random.randrange(1,300)
            barParameters=[xPos, 300, width, height]
            BarData.append(barParameters)
        self.RevertBarData()
          
    def RevertBarData(self):
        maxH = self.maxHeight()
        for h in range(size):            
            moveH = maxH - BarData[h][3]
            yPos = BarData[h][1]
            yPos += moveH
            BarData[h][1] = yPos
  
    def maxHeight(self):
        Height = []
        for h in range(size):
            Height.append(BarData[h][3])
        maxH = max(Height)
        return maxH
      
    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.paintBox(dc)
      
    def paintBox(self, dc):
        dc.SetBrush(wx.Brush("green"))
        dc.SetFont(self.font)
        for i in range(0,size):
            dc.DrawRectangle(*BarData[i])
            x = BarData[i][0]
            y = BarData[i][1] + BarData[i][3]
            h = str(BarData[i][3])
            dc.DrawText(h, x, y)
             
    def BubbleSort(self):
        for i in range(len(BarData), 1, -1):
            for j in range(i-1):
                if BarData[j][3] > BarData[j+1][3]:
                    BarData[j][1], BarData[j+1][1] = BarData[j+1][1], BarData[j][1]
                    BarData[j][3], BarData[j+1][3] = BarData[j+1][3], BarData[j][3]
                    yield
                     
    def OnTimer(self, event):
        if self.g == None:
            self.g = self.BubbleSort()
        try:
            self.g.next()
            self.Refresh()
        except:
            self.StopTimer()
            wx.MessageBox('Done!')
              
class TopFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Bubble sort", size = (900,700))
        TopPanel(self)     
          
if __name__ == '__main__':
    app = wx.App()
    frame = TopFrame()
    frame.Show()
    app.MainLoop()
海蓝天蓝 2013-01-22
  • 打赏
  • 举报
回复
@bugs2k 我试了你po的3个代码,button可以启动timer,就是排序好像不是bubble sort了
海蓝天蓝 2013-01-22
  • 打赏
  • 举报
回复
@angel_su 谢谢,button is working!!!
bugs2k 2013-01-22
  • 打赏
  • 举报
回复
前面貌似有点问题

import wx
import random
  
size = 30
xPos = 50
BarData = []
width = 900/(size*2)
gap = 900/(size*4)
delay = 100
  
class TopPanel(wx.Panel):
    def __init__(self,parent):
        wx.Panel.__init__(self,parent)
        self.GenerateBarData(xPos)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.font = wx.Font(8, wx.DEFAULT, wx.ITALIC, wx.NORMAL)
        self.toggleBtn = wx.Button(self, wx.ID_ANY,"Start")
        self.toggleBtn.Bind(wx.EVT_BUTTON, self.OnToggle)
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        self.bStart = False

    def StartTimer(self):
        self.bStart = True
        self.timer.Start(delay)
        self.toggleBtn.SetLabel("Stop")

    def StopTimer(self):
        self.bStart = False
        self.timer.Stop()
        self.toggleBtn.SetLabel("Start")      

    def OnToggle(self, event):
        if self.bStart:
            self.StopTimer()
        else:
            self.StartTimer()

    def GenerateBarData(self,xPos):               
        for num in range(size):           
            xPos += (width + gap)
            height = random.randrange(1,300)
            barParameters=[xPos, 300, width, height]
            BarData.append(barParameters)
        self.RevertBarData()
          
    def RevertBarData(self):
        maxH = self.maxHeight()
        for h in range(size):            
            moveH = maxH - BarData[h][3]
            yPos = BarData[h][1]
            yPos += moveH
            BarData[h][1] = yPos
  
    def maxHeight(self):
        Height = []
        for h in range(size):
            Height.append(BarData[h][3])
        maxH = max(Height)
        return maxH
      
    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.paintBox(dc)
      
    def paintBox(self, dc):
        dc.SetBrush(wx.Brush("green"))
        dc.SetFont(self.font)
        for i in range(0,size):
            dc.DrawRectangle(*BarData[i])
            x = BarData[i][0]
            y = BarData[i][1] + BarData[i][3]
            h = str(BarData[i][3])
            dc.DrawText(h, x, y)
             
    def BubbleSort(self):
        for i in range(len(BarData), 1, -1):
            for j in range(i-1):
                if BarData[j][3] > BarData[j+1][3]:
                    BarData[j][1], BarData[j+1][1] = BarData[j+1][1], BarData[j][1]
                    BarData[j][3], BarData[j+1][3] = BarData[j+1][3], BarData[j][3]
                    return True
        return False
                     
    def OnTimer(self, event):
        if self.BubbleSort():
            self.Refresh()
        else:
            self.StopTimer()
            wx.MessageBox('Done!')
              
class TopFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Bubble sort", size = (900,700))
        TopPanel(self)     
          
if __name__ == '__main__':
    app = wx.App()
    frame = TopFrame()
    frame.Show()
    app.MainLoop()
bugs2k 2013-01-22
  • 打赏
  • 举报
回复
import wx
import random
  
size = 30
xPos = 50
BarData = []
width = 900/(size*2)
gap = 900/(size*4)
delay = 100
  
class TopPanel(wx.Panel):
    def __init__(self,parent):
        wx.Panel.__init__(self,parent)
        self.GenerateBarData(xPos)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.font = wx.Font(8, wx.DEFAULT, wx.ITALIC, wx.NORMAL)
        self.toggleBtn = wx.Button(self, wx.ID_ANY,"Start")
        self.toggleBtn.Bind(wx.EVT_BUTTON, self.OnToggle)
        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
        self.bStart = False

    def StartTimer(self):
        self.bStart = True
        self.timer.Start(delay)
        self.toggleBtn.SetLabel("Stop")

    def StopTimer(self):
        self.bStart = False
        self.timer.Stop()
        self.toggleBtn.SetLabel("Start")      

    def OnToggle(self, event):
        btnLabel = self.toggleBtn.GetLabel()
        wx.CallAfter(self.OnTimer)
        if self.bStart:
            self.StopTimer()
        else:
            self.StartTimer()

    def GenerateBarData(self,xPos):               
        for num in range(size):           
            xPos += (width + gap)
            height = random.randrange(1,300)
            barParameters=[xPos, 300, width, height]
            BarData.append(barParameters)
        self.RevertBarData()
          
    def RevertBarData(self):
        maxH = self.maxHeight()
        for h in range(size):            
            moveH = maxH - BarData[h][3]
            yPos = BarData[h][1]
            yPos += moveH
            BarData[h][1] = yPos
  
    def maxHeight(self):
        Height = []
        for h in range(size):
            Height.append(BarData[h][3])
        maxH = max(Height)
        return maxH
      
    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.paintBox(dc)
      
    def paintBox(self, dc):
        dc.SetBrush(wx.Brush("green"))
        dc.SetFont(self.font)
        for i in range(0,size):
            dc.DrawRectangle(*BarData[i])
            x = BarData[i][0]
            y = BarData[i][1] + BarData[i][3]
            h = str(BarData[i][3])
            dc.DrawText(h, x, y)
             
    def BubbleSort(self):
        for i in range(len(BarData), 1, -1):
            for j in range(i-1):
                if BarData[j][3] > BarData[j+1][3]:
                    BarData[j][1], BarData[j+1][1] = BarData[j+1][1], BarData[j][1]
                    BarData[j][3], BarData[j+1][3] = BarData[j+1][3], BarData[j][3]
                    return True
        return False
                     
    def OnTimer(self, event):
        if self.BubbleSort():
            self.Refresh()
        else:
            self.StopTimer()
            wx.MessageBox('Done!')
              
class TopFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Bubble sort", size = (900,700))
        TopPanel(self)     
          
if __name__ == '__main__':
    app = wx.App()
    frame = TopFrame()
    frame.Show()
    app.MainLoop()
bugs2k 2013-01-22
  • 打赏
  • 举报
回复
import wx
import random
  
size = 30
xPos = 50
BarData = []
width = 900/(size*2)
gap = 900/(size*4)
delay = 100
  
class TopPanel(wx.Panel):
    def __init__(self,parent):
        wx.Panel.__init__(self,parent)
          
        self.GenerateBarData(xPos)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
         
        self.font = wx.Font(8, wx.DEFAULT, wx.ITALIC, wx.NORMAL)
         
        self.toggleBtn = wx.Button(self, wx.ID_ANY,"Start")
        self.toggleBtn.Bind(wx.EVT_BUTTON, self.OnToggle)

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
      
        self.bStart = False

    def StartTimer(self):
            self.bStart = True
            self.timer.Start(delay)
            self.toggleBtn.SetLabel("Stop")

    def StopTimer(self):
        self.bStart = False
        self.timer.Stop()
        self.toggleBtn.SetLabel("Start")      

    def OnToggle(self, event):
        btnLabel = self.toggleBtn.GetLabel()
        wx.CallAfter(self.OnTimer)
        if self.bStart:
            self.StopTimer()
        else:
            self.StartTimer()

    #generate the original bars's data (x,y,w,h)    
    def GenerateBarData(self,xPos):               
        for num in range(size):           
            xPos += (width + gap)
            height = random.randrange(1,300)
            barParameters=[xPos, 300, width, height]
            BarData.append(barParameters)
            #~ print BarData[num]
        #revert the bars' yPos
        self.RevertBarData()
          
          
    def RevertBarData(self):
        maxH = self.maxHeight()
        for h in range(size):            
            moveH = maxH - BarData[h][3]
            yPos = BarData[h][1]
            yPos += moveH
            BarData[h][1] = yPos
  
    #return the hightest height in bars
    def maxHeight(self):
        Height = []
        #store all the bar height in Height[]
        for h in range(size):
            Height.append(BarData[h][3])
        #find out the heightest bar and return
        maxH = max(Height)
        return maxH
      
    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.paintBox(dc)
      
    def paintBox(self, dc):
        #~ print len(BarData)
        dc.SetBrush(wx.Brush("green"))
        dc.SetFont(self.font)
        for i in range(0,size):
            dc.DrawRectangle(*BarData[i])
            x = BarData[i][0]
            y = BarData[i][1] + BarData[i][3]
            h = str(BarData[i][3])
            dc.DrawText(h, x, y)
             
                
    #bubble sort
    def BubbleSort(self):
        for i in range(len(BarData), 1, -1):
            for j in range(i-1):
                if BarData[j][3] > BarData[j+1][3]:
                    BarData[j][1], BarData[j+1][1] = BarData[j+1][1], BarData[j][1]
                    BarData[j][3], BarData[j+1][3] = BarData[j+1][3], BarData[j][3]
                    return True
        return False
                     
    def OnTimer(self, event):
        if self.BubbleSort():
            self.Refresh()
        else:
            self.StopTimer()
            wx.MessageBox('Done!')
             
              
class TopFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Bubble sort", size = (900,700))
        TopPanel(self)     
          
if __name__ == '__main__':
    app = wx.App()
    frame = TopFrame()
    frame.Show()
    #print BarData
    app.MainLoop()
angel_su 2013-01-22
  • 打赏
  • 举报
回复
下面2个函数修改一下...
...
    #The toggle button event
    def OnToggle(self, event=None):
        #~ btnLabel = self.toggleBtn.GetLabel()
        if self.timer.IsRunning():
            self.timer.Stop()
            self.toggleBtn.SetLabel("Start")      
        else:
            self.timer.Start(milliseconds=1000)#, oneShot = True)
            self.toggleBtn.SetLabel("Stop")

...

    #Timer event               
    def OnTimer(self, event):
        if not hasattr(self, 'g'):
            self.g= self.BubbleSort()
        try:
            next(self.g)
        except StopIteration:
            del self.g
            self.timer.Stop()
            self.toggleBtn.Disable()
            wx.MessageBox('Done!')
        
        self.Refresh()

海蓝天蓝 2013-01-22
  • 打赏
  • 举报
回复
@angel_su 我加了一个toogle button来控制timer,可是好像没起作用
import wx
import random
import timer
 
size = 30
xPos = 50
BarData = []
width = 900/(size*2)
gap = 900/(size*4)
delay = 100
 
class TopPanel(wx.Panel):
    def __init__(self,parent):
        panel = wx.Panel.__init__(self,parent)
         
        self.GenerateBarData(xPos)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        
        self.font = wx.Font(8, wx.DEFAULT, wx.ITALIC, wx.NORMAL)
        #wx.CallAfter(self.OnTimer)

        self.timer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)

        self.toggleBtn = wx.Button(self, wx.ID_ANY,"Start")
        self.toggleBtn.Bind(wx.EVT_BUTTON, self.OnToggle)
        
    #The toggle button event
    def OnToggle(self, event):
        btnLabel = self.toggleBtn.GetLabel()
        if self.timer.IsRunning():
            self.timer.Stop()
            self.toggleBtn.SetLabel("Start")      
        else:
            self.timer.Start(milliseconds=1000, oneShot = True)
            self.toggleBtn.SetLabel("Stop")
 
    #generate the original bars's data (x,y,w,h)    
    def GenerateBarData(self,xPos):               
        for num in range(size):           
            xPos += (width + gap)
            height = random.randrange(1,300)
            barParameters=[xPos, 300, width, height]
            BarData.append(barParameters)
            #~ print BarData[num]
        #revert the bars' yPos
        self.RevertBarData()
         
         
    def RevertBarData(self):
        maxH = self.maxHeight()
        for h in range(size):            
            moveH = maxH - BarData[h][3]
            yPos = BarData[h][1]
            yPos += moveH
            BarData[h][1] = yPos
 
    #return the hightest height in bars
    def maxHeight(self):
        Height = []
        #store all the bar height in Height[]
        for h in range(size):
            Height.append(BarData[h][3])
        #find out the heightest bar and return
        maxH = max(Height)
        return maxH
     
    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.paintBox(dc)
     
    def paintBox(self, dc):
        #~ print len(BarData)
        dc.SetBrush(wx.Brush("green"))
        dc.SetFont(self.font)
        for i in range(0,size):
            dc.DrawRectangle(*BarData[i])
            x = BarData[i][0]
            y = BarData[i][1] + BarData[i][3]
            h = str(BarData[i][3])
            dc.DrawText(h, x, y)
            
               
    #bubble sort
    def BubbleSort(self):
        for i in range(len(BarData), 1, -1):
            for j in range(i-1):
                if BarData[j][3] > BarData[j+1][3]:
                    BarData[j][1], BarData[j+1][1] = BarData[j+1][1], BarData[j][1]
                    BarData[j][3], BarData[j+1][3] = BarData[j+1][3], BarData[j][3]
                    yield
    #Timer event               
    def OnTimer(self, g=None):
        if g == None:
            g = self.BubbleSort()
        try:
            g.next()
            self.Refresh()
            #wx.CallLater(delay, self.OnTimer, g)
        except:
            wx.MessageBox('Done!')
            
             
class TopFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Bubble sort", size = (900,700))
        TopPanel(self)     
         
if __name__ == '__main__':
    app = wx.App()
    frame = TopFrame()
    frame.Show()
    #print BarData
    app.MainLoop()
海蓝天蓝 2013-01-22
  • 打赏
  • 举报
回复
谢谢7楼的建议:)可是我感觉matplotlib好像比较适合画图表之类的
angel_su 2013-01-18
  • 打赏
  • 举报
回复
就在原来的基础上,添加一些条件分支设置不同颜色的刷子即可...
chyanog 2013-01-18
  • 打赏
  • 举报
回复
这个如果用matplotlib做会很方便,画条形图的bar函数很好用
海蓝天蓝 2013-01-18
  • 打赏
  • 举报
回复
非常感谢楼上大侠的代码,refresh是自动调用PAINT事件,但是如果程序想要highlight正在比较的两个bar,但是原来的paint事件里的brush已经设为了绿色,可是如果我想把正在比较的bars设为红色之类的,是不是还得重新写一个paint方法?
angel_su 2013-01-18
  • 打赏
  • 举报
回复
wx.CallLater和wx.Timer差不多,也是个类来的,一样有Stop方法可以停止计时,在不需要人为干预情况下用前者,这样代码简单点看起来像调用一个函数.... http://wxpython.org/Phoenix/docs/html/CallLater.html#calllater
海蓝天蓝 2013-01-18
  • 打赏
  • 举报
回复
wx.CallAfter(),wx.CallLater()和wx.Timer 的用法一样吗?我想设置一个start按钮和一个stop按钮来控制排序的流程,可是我换成wx.Timer后好像排序算法并没有被调用。或者有什么方法是可以stop wx.CallAfter()那个线程的吗?
bugs2k 2013-01-17
  • 打赏
  • 举报
回复
试试Refresh()
angel_su 2013-01-17
  • 打赏
  • 举报
回复
嗯,绘图速度不是问题的话,用Refresh()激发PAINT事件自动重绘即可,就不用再写一套绘图流程。演示嘛用定时器方式有节奏地更新,另外,排序里加yield语句形成一个生成器函数,这样组织代码比较方便...
import wx
import random
 
size = 30
xPos = 50
BarData = []
width = 900/(size*2)
gap = 900/(size*4)
delay = 100
 
class TopPanel(wx.Panel):
    def __init__(self,parent):
        wx.Panel.__init__(self,parent)
         
        self.GenerateBarData(xPos)
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        
        self.font = wx.Font(8, wx.DEFAULT, wx.ITALIC, wx.NORMAL)
        wx.CallAfter(self.OnTimer)
        
 
    #generate the original bars's data (x,y,w,h)    
    def GenerateBarData(self,xPos):               
        for num in range(size):           
            xPos += (width + gap)
            height = random.randrange(1,300)
            barParameters=[xPos, 300, width, height]
            BarData.append(barParameters)
            #~ print BarData[num]
        #revert the bars' yPos
        self.RevertBarData()
         
         
    def RevertBarData(self):
        maxH = self.maxHeight()
        for h in range(size):            
            moveH = maxH - BarData[h][3]
            yPos = BarData[h][1]
            yPos += moveH
            BarData[h][1] = yPos
 
    #return the hightest height in bars
    def maxHeight(self):
        Height = []
        #store all the bar height in Height[]
        for h in range(size):
            Height.append(BarData[h][3])
        #find out the heightest bar and return
        maxH = max(Height)
        return maxH
     
    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.paintBox(dc)
     
    def paintBox(self, dc):
        #~ print len(BarData)
        dc.SetBrush(wx.Brush("green"))
        dc.SetFont(self.font)
        for i in range(0,size):
            dc.DrawRectangle(*BarData[i])
            x = BarData[i][0]
            y = BarData[i][1] + BarData[i][3]
            h = str(BarData[i][3])
            dc.DrawText(h, x, y)
            
               
    #bubble sort
    def BubbleSort(self):
        for i in range(len(BarData), 1, -1):
            for j in range(i-1):
                if BarData[j][3] > BarData[j+1][3]:
                    BarData[j][1], BarData[j+1][1] = BarData[j+1][1], BarData[j][1]
                    BarData[j][3], BarData[j+1][3] = BarData[j+1][3], BarData[j][3]
                    yield
                    
    def OnTimer(self, g=None):
        if g == None:
            g = self.BubbleSort()
        try:
            g.next()
            self.Refresh()
            wx.CallLater(delay, self.OnTimer, g)
        except:
            wx.MessageBox('Done!')
            
             
class TopFrame(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None, title="Bubble sort", size = (900,700))
        TopPanel(self)     
         
if __name__ == '__main__':
    app = wx.App()
    frame = TopFrame()
    frame.Show()
    #print BarData
    app.MainLoop()

37,719

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧