文章目录
一、常用函数介绍
在做界面设计之前,首先来介绍一下常用的函数。
1、wx.StaticText()
函数作用:用来在界面上添加文字。
常见使用方法如下所示:
txt = wx.StaticText(self.panel, label="想要显示的内容")
实现效果如图所示:
2、wx.TextCtrl()
函数作用:用来在界面上显示状态栏
(1)仅显示状态栏
常见使用方法如下:
txt_ctrl1 = wx.TextCtrl(self.panel, size=(10, 10))
txt_ctrl2 = wx.TextCtrl(self.sympol.GetStaticBox(), wx.ID_ANY, wx.EmptyString, pos=wx.DefaultPosition, size=(200, 250), style=wx.TE_MULTILINE)
第二种显示的方式可以在状态栏的后边换行,并增加状态栏的内容;第一种则不行。
最终得到的两种状态栏如下所示,右上为txt_ctrl1,右下为txt_ctrl2.
(2)链接回调
在有了状态栏之后,还可以将指定的内容在其中输出显示;或者将在状态栏中输入的内容作为字符串进行提取。
随后的使用如下所示:
def __init__(self):
self.text_ctrl1 = wx.TextCtrl(Ctrl.GetStaticBox(), size=(10, 50))
self.text_ctrl2 = wx.TextCtrl(Ctrl.GetStaticBox(), wx.ID_ANY, wx.EmptyString, pos=wx.DefaultPosition,size=(200, 250), style=wx.TE_MULTILINE)
def Setvalue(self, event):
'''按下按钮立即执行此函数'''
self.text_ctrl1.SetValue("你是不是猪\n")
self.text_ctrl1.SetValue("你好\n")
self.text_ctrl2.AppendText("hello\n")
self.text_ctrl2.AppendText("world\n")
此时的效果如图所示:
可以看出,在第二个状态栏中,是可以保持第一次输出结果不变的情况下,在后边增加文本输入的。但是第一个状态栏会把第一次输出结果覆盖。
3、wx.Button()
函数作用:在界面中添加按钮,在按钮按下的时候,执行某项操作
(1)仅显示按钮选项
按钮的显示依靠的是wx.Button()函数,其使用方法如下所示:
btn1 = wx.Button(Left.GetStaticBox(), label="按钮1")
其执行效果如下图所示:
(2)链接回调功能函数
此时虽然已经可以正常显示按钮,但是却没有绑定任何的功能。如果想要让按钮在被按下的时候执行某项功能,就需要对按钮进行函数绑定,此时我们用到的ROI是 Bind(),具体使用方法如下所示:
class……
def __init__(self):
wx.App.__init__(self)
self.frame = wx.Frame(None, title="demoUI")
self.panel = wx.Panel(self.frame)
btn1.Bind(wx.EVT_BUTTON, self.Setvalue)
def Setvalue(self, event):
'''按下按钮立即执行此函数'''
self.text_ctrl1.SetValue("你是不是猪\n")
self.text_ctrl1.SetValue("你好\n")
self.text_ctrl2.AppendText("hello\n")
self.text_ctrl2.AppendText("world\n")
此时当按下按钮的时候,就会执行Setvalue()函数中的内容,比如在本例子中,当按下“按钮1”的时候,就会在第一个状态栏中显示“你好\n”;并在第二个状态栏中显示“hello \n world \n ”
4、wx.Choice()
函数作用:用来制作选择框
(1)仅显示选择框按钮
detect_choice = [u"YOLO检测", u"身份检测", u"关键点检测", u"行为检测"]
self.choice = wx.Choice(self.detect_op.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.Size(80, 25), detect_choice, 0)
self.choice.SetSelection(0)
做出的效果如下图所示:
(2)链接回调函数
当我们可以通过选择框选择词条之后,根据常规的编程思维,是要把此词条作为输入传回主进程的。所以还需要一个函数将选择框与主线程连接起来。
也就是使用回调函数。具体实现过程如下所示:
class App(wx.App):
def __init__(self):
self.text_ctrl2 = wx.TextCtrl(Ctrl.GetStaticBox(), wx.ID_ANY, wx.EmptyString, pos=wx.DefaultPosition,size=(200, 250), style=wx.TE_MULTILINE)
detect_choice = [u"我是猪", u"我不是猪", u"你是猪", u"你不是猪"]
self.choice = wx.Choice(self.detect_op.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.Size(80, 25), detect_choice, 0)
self.choice.SetSelection(0)
self.choice.Bind(wx.EVT_CHOICE, self.detect_choice)
def detect_choice(self, event):
detect_sym = event.GetString()
detect_sym = u"当前词条为 :\t{}\n".format(detect_sym)
self.text_ctrl2.AppendText(detect_sym)
此时的执行效果如下图所示:
二、常用框架
wxpython的使用方法形形色色,对于“基于对象”思维薄弱的同学很不友好,有些代码也十分难以理解。因此我自己总结了一套wxpython的使用代码方法,如下所示:
import wx
import cv2
class App(wx.App):
def __init__(self):
wx.App.__init__(self)
self.frame = wx.Frame(None, title="demoUI")
self.panel = wx.Panel(self.frame)
# -----------------------
# 新建控件位置变量
# -----------------------
VERTICAL = wx.BoxSizer(wx.VERTICAL) # 垂直方向的位置变量
HORIZONTAL = wx.BoxSizer(wx.HORIZONTAL) # 水平方向的位置变量
Left = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "操作栏"),
wx.VERTICAL)
Ctrl = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "状态栏"),
wx.VERTICAL)
HORIZONTAL.Add(Left, 0, wx.ALL | wx.EXPAND, 5)
HORIZONTAL.Add(Ctrl, 0, wx.ALL | wx.EXPAND, 5)
VERTICAL.Add(HORIZONTAL)
# 绑定事件
btn1.Bind(wx.EVT_BUTTON, self.Setvalue)
self.choice.Bind(wx.EVT_CHOICE, self.detect_choice)
# -----------------------
# 最终一些乱七八糟的设置
# -----------------------
self.panel.SetSizer(VERTICAL)
self.panel.Layout()
HORIZONTAL.Fit(self.frame)
self.frame.Show()
if __name__ == '__main__':
app = App()
app.MainLoop()
三、使用实例
使用这个框架,我自己写了一个前端界面,以下是最终执行效果:
因为本章内容主要叙述的是如何使用wxpython构建一个前端界面,所以代码中仅包含界面的构建。
整个构建过程实现的代码如下所示,可自由解读:
import wx
import cv2
class App(wx.App):
def __init__(self):
wx.App.__init__(self)
self.frame = wx.Frame(None, title="demoUI")
self.panel = wx.Panel(self.frame)
# -----------------------
# 新建控件位置变量
# -----------------------
VERTICAL = wx.BoxSizer(wx.VERTICAL)
HORIZONTAL = wx.BoxSizer(wx.HORIZONTAL)
# -----------------------
# 新建控件
# -----------------------
image = wx.EmptyImage(500, 500)
self.image_sys = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "检测结果与实时图像"),
wx.VERTICAL)
self.live_image = wx.StaticBoxSizer(wx.StaticBox(self.image_sys.GetStaticBox(), wx.ID_ANY, "实时图像"),
wx.VERTICAL)
self.txt_image = wx.StaticBoxSizer(wx.StaticBox(self.image_sys.GetStaticBox(), wx.ID_ANY, "检测结果"),
wx.HORIZONTAL)
self.txt = wx.StaticText(self.txt_image.GetStaticBox(), size=(10, 10))
self.image = wx.StaticBitmap(self.live_image.GetStaticBox(), wx.ID_ANY,
wx.BitmapFromImage(image))
self.opare = wx.StaticBoxSizer(wx.StaticBox(self.panel, wx.ID_ANY, "操作栏"),
wx.VERTICAL)
self.image_op = wx.StaticBoxSizer(wx.StaticBox(self.opare.GetStaticBox(), wx.ID_ANY, "图片操作栏"),
wx.HORIZONTAL)
self.detect_op = wx.StaticBoxSizer(wx.StaticBox(self.opare.GetStaticBox(), wx.ID_ANY, "检测选择栏"),
wx.HORIZONTAL)
self.para_op = wx.StaticBoxSizer(wx.StaticBox(self.opare.GetStaticBox(), wx.ID_ANY, "参数设置栏"),
wx.VERTICAL)
self.sympol = wx.StaticBoxSizer(wx.StaticBox(self.opare.GetStaticBox(), wx.ID_ANY, "状态栏"),
wx.VERTICAL)
# 图片操作栏
grider = wx.GridSizer(0, 2, 0, 9)
btn_open = wx.Button(self.image_op.GetStaticBox(), label="打开文件", size=(10, 10))
btn_close = wx.Button(self.image_op.GetStaticBox(), label="关闭文件")
# 选择
grider_det = wx.GridSizer(0, 3, 0, 9)
detect_choice = [u"YOLO检测", u"身份检测", u"关键点检测", u"行为检测"]
self.choice = wx.Choice(self.detect_op.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.Size(80, 25), detect_choice, 0)
self.choice.SetSelection(0)
self.btn_det = wx.Button(self.detect_op.GetStaticBox(), label="开始检测")
self.btn_cancel_det = wx.Button(self.detect_op.GetStaticBox(), label="取消检测")
# 参数设置
grider1 = wx.GridSizer(0, 2, 0, 1)
self.btn_ret = wx.Button(self.para_op.GetStaticBox(), label="待检索图片文件夹")
self.sym_ret = wx.TextCtrl(self.para_op.GetStaticBox(), size=(10, 10))
grider2 = wx.GridSizer(0, 3, 0, 2)
self.btn_yolo_para = wx.StaticText(self.para_op.GetStaticBox(), label="YOLO权重")
self.btn_identity_para = wx.StaticText(self.para_op.GetStaticBox(), label="身份识别权重")
self.btn_behav_para = wx.StaticText(self.para_op.GetStaticBox(), label="行为识别权重")
self.txt_yolo_para = wx.TextCtrl(self.para_op.GetStaticBox(), size=(10, 10))
self.txt_identity_para = wx.TextCtrl(self.para_op.GetStaticBox(), size=(10, 10))
self.txt_behav_para = wx.TextCtrl(self.para_op.GetStaticBox(), size=(10, 10))
# 状态栏
self.text_ctrl = wx.TextCtrl(self.sympol.GetStaticBox(), wx.ID_ANY, wx.EmptyString, pos=wx.DefaultPosition, size=(200, 250), style=wx.TE_MULTILINE)
# -----------------------
# 绑定事件
# -----------------------
btn_open.Bind(wx.EVT_BUTTON, self.openfile)
#self.Bind(wx.EVT_BUTTON, self.opendir, self.btn_ret)
self.btn_ret.Bind(wx.EVT_BUTTON, self.opendir)
#btn_close.Bind(wx.EVT_BUTTON, sel)
self.choice.Bind(wx.EVT_CHOICE, self.detect_choice)
# -----------------------
# 控件分布
# -----------------------
grider.Add(btn_open, 0, wx.ALL | wx.EXPAND, 5)
grider.Add(btn_close, 0, wx.ALL | wx.EXPAND, 5)
grider1.Add(self.btn_ret, 0, wx.ALL | wx.EXPAND, 5)
grider1.Add(self.sym_ret, 0, wx.ALL | wx.EXPAND, 5)
grider2.Add(self.btn_yolo_para, 0, wx.ALL | wx.EXPAND, 5)
grider2.Add(self.btn_identity_para, 0, wx.ALL | wx.EXPAND, 5)
grider2.Add(self.btn_behav_para, 0, wx.ALL | wx.EXPAND, 5)
grider2.Add(self.txt_yolo_para, 0, wx.ALL | wx.EXPAND, 5)
grider2.Add(self.txt_identity_para, 0, wx.ALL | wx.EXPAND, 5)
grider2.Add(self.txt_behav_para, 0, wx.ALL | wx.EXPAND, 5)
grider_det.Add(self.choice, 0, wx.ALL | wx.EXPAND, 5)
grider_det.Add(self.btn_det, 0, wx.ALL | wx.EXPAND, 5)
grider_det.Add(self.btn_cancel_det, 0, wx.ALL | wx.EXPAND, 5)
self.sympol.Add(self.text_ctrl, 1, wx.EXPAND, 5)
self.image_op.Add(grider, 0, wx.ALL | wx.EXPAND, 5)
self.detect_op.Add(grider_det, 0, wx.ALL | wx.EXPAND, 5)
self.para_op.Add(grider1, 0, wx.ALL | wx.EXPAND, 5)
self.para_op.Add(grider2, 0, wx.ALL | wx.EXPAND, 5)
self.live_image.Add(self.image, 0, wx.ALL | wx.EXPAND, 5)
self.txt_image.Add(self.txt, 0, wx.ALL | wx.EXPAND, 5)
self.opare.Add(self.image_op, 0, wx.ALL | wx.EXPAND, 5)
self.opare.Add(self.detect_op, 0, wx.ALL | wx.EXPAND, 5)
self.opare.Add(self.para_op, 0, wx.ALL | wx.EXPAND, 5)
self.opare.Add(self.sympol, 0, wx.ALL | wx.EXPAND, 5)
self.image_sys.Add(self.live_image, 0, wx.ALL | wx.EXPAND, 5)
self.image_sys.Add(self.txt_image, 0, wx.ALL | wx.EXPAND, 5)
HORIZONTAL.Add(self.image_sys, 0, wx.ALL | wx.EXPAND, 5)
HORIZONTAL.Add(self.opare, 0, wx.ALL | wx.EXPAND, 5)
VERTICAL.Add(HORIZONTAL)
# -----------------------
# 最终一些乱七八糟的设置
# -----------------------
self.panel.SetSizer(VERTICAL)
self.panel.Layout()
HORIZONTAL.Fit(self.frame)
self.frame.Show()
self.frame.Bind(wx.EVT_CLOSE, self.onclose)
def openfile(self, event):
wildcard = "JPEG files (*.jpg) | *.jpg"
dialog = wx.FileDialog(None, "choose a file",
wildcard=wildcard,
style=wx.FD_OPEN)
if dialog.ShowModal() == wx.ID_OK:
self.text_ctrl.SetValue(dialog.GetPath() + '\n')
dialog.Destroy()
def opendir(self, event):
wildcard = wx.DirDialog(None, "选择文件夹", style=wx.DD_DEFAULT_STYLE)
if wildcard.ShowModal() == wx.ID_OK:
self.sym_ret.SetValue(wildcard.GetPath())
wildcard.Destroy()
def detect_choice(self, event):
detect_sym = event.GetString()
detect_sym = u"当前状态为 :\t{}\n".format(detect_sym)
self.text_ctrl.AppendText(detect_sym)
def Show_sym(self, sym):
self.text_ctrl.AppendText(sym)
def onclose(self, evt):
dlg = wx.MessageDialog(None, u'确定要关闭本窗口?', u'操作提示', wx.YES_NO | wx.ICON_QUESTION)
if (dlg.ShowModal() == wx.ID_YES):
self.Destroy()
if __name__ == '__main__':
app = App()
app.MainLoop()
总结
本章首先介绍了wxpython中几个比较常用的roi函数,并给出了其执行效果;其次总结了wxpython比较好用的一套框架;最终使用此框架搭建了一个比较晚上的前端界面平台。
求学路漫漫,且行且思索