zoukankan      html  css  js  c++  java
  • Python:初识GUI编程【wxPython】

      GUI是Graphical User Interface(图形用户界面)的缩写,在Gui中,并不是只有键入文本和返回文本,用户可以看到窗口,按钮、文本框等图形,并且可以用鼠标单机,也可以用键盘输入。GUI是与程序交换的种不同方式.GUI的程序有3个基本要素:输入,处理和输出。

    一、常用的GUI框架

      对于python的GUI开发,有很多工具包供我们选择。以下是一些留下的工具包。

     二、安装wxPython

      wxPython是一个成熟而且特性丰富的跨平台GUI工具包,使用pip 工具安装wxPython

    pip install -U wxPython 

      使用wxPython之前,先来了解2个基础对象:应用程序对象和顶级窗口

      A应用程序对象管理主事件循环,主时间循环是wxPython程序的动力,如果没有应用程序对象,wxPython应用程序将不能运行。

      顶级窗口通常用于管理最重要的数据,控制并呈现给用户。这2个基础对象和应用程序的其他部分之前的关系,如图所示。

       在图中,这个应用程序对象拥有顶级窗口和主循环时间。顶级窗口管理其窗口中的组件和其他分配给它的数据对象。窗口和她的组件触发的时间基于用户的动作,并接受事件通知以便于改变现实。

      1、创建一个wx.App的子类

      在创建应用程序之前,先来创建一个没有任何功能的子类。创建和使用一个wx.App子类,需要执行4个步骤

      a:定义这个子类

      b:在定义的子类中写一个OnInit()初始化方法

      c:在程序的主要部分创建这个类的一个实例。

      d:调用应用程序实例MainLoop()方法。这个方法将程序的控制权转交给wxPython.

    创建一个没有任何功能的子类。具体代码如下:

    import wx#导入wxPython
    class App(wx.App):
        #初始化方法
        def OnInit(self):
            frame = wx.Frame(parent = None,title = 'hello wyPython')
            #创建窗口,因为是主窗口,所以他的父类为None title:窗口标题
            frame.Show()#显示窗口
            return  True #返回值
    if __name__ == '__main__':
        app = App()#创建App类实例
        app.mainloop()#调用App类的MainLoop()主循环方法

    上述代码中,定义了一个子类App().他冀衡父类wx.App.子类中包含一个初始方法OnInit().

    在主程序中创建类的实例。然后再调用MainLoop()主循环方法。运行结果如图所示

     2、直接使用wx.App

      通常,如果在系统中只有一个窗口的话,可以不创建wx.App子类。直接使用wx.App.这个类提供了一个最基本的OnInit()初始化方法。具体代码如下

    import wx
    app = wx.App()
    frame = wx.Frame(None,title = "hello world")
    frame.Show()
    app.MainLoop()

    3、使用wx.Frame框架

      在GUI中框架通常也称为窗口,框架是一个容器,用户可以将在屏幕上任意移动。并可对他进行缩放,他通常包含标题栏,菜单等。在wxPython中,wx.Frame是所有框架的父类。当你创建wx.Fame的子类时,子类应该调用其父类的构造器wx.Frame.__init__().wx.Frame构造器的语法格式如下:

    wx.Frame(parent,id=1,title="“,pos = wx.DefaultPosition,size=wx.DefaultSize,style=wx.DEFAULT_FRAME_STYLE,name="frame")

    参数说明:

    parent:框架的父窗口。如果是顶级窗口,这个是None。

    id:关于新窗口的wxPython ID号。通常设为-1,让wxPython自动生成一个新的ID.

    title:窗口的标题

    pos:一个wx.Point对象,他指定这个窗口的左上角在屏幕中的位置。在图形用户界面程序中。通常(0,0)是显示器的左上角。这个默认值(-1,-1)将让系统决定窗口的位置。

    size:一个wx.Size对象,他指定这个窗口的初始尺寸。这个默认值(-1,-1)将让系统决定窗口的初始尺寸。

    style:指定窗口类型的常量。可以使用或运算来组合他们。

    name:框架内的名字。可以使用它来寻找这个窗口。

    创建wx.Frame子类的代码如下:

    import wx
    class MyFrame(wx.Frame):
        def __init__(self,parent,id):
            wx.Frame.__init__(self,parent,id,title="创建Frame",pos=(100,100),size=(300,300))
    if __name__ == "__main__":
        app = wx.App()#初始化应用
        frame = MyFrame(parent = None,id= 1)#实例MyFrame类,并传递参数。
        frame.Show()#显示窗口
        app.MainLoop()#调用MainLoop方法

    上述代码中,在主程序中调用MyFrame类,并且传递2个参数。在MyFrame类中,自动执行__init__()初始化方法。接受参数。然后调用父类wx.Frame的__init__()初始方法。设置顶级窗口的相关属性。运行结果如图所示

     三、常用控件

      创建完窗口以后,我们可以在窗口添加一些控件,所谓的控件,就是经常使用的按钮、文本、输入框,单选框等。

      1、StaticText文本类

      对于所有的UI工具来说,最基本的任务就是在屏幕上绘制纯文本,在wx.Python中,可以使用wx.StatiText类来完成。使用wx.StaticText能够改变文本的对齐方式,字体和颜色等。wx.StaticText类的构造语法如下:

    wx.StaticText(parent,id,label,pos = wx.DefaultPosition,size=wx.DefaultSize,style=wx.DEFAULT_FRAME_STYLE,name="frame")

    参数说明:

    parent:框架的父窗口。

    id:标识符。使用-1可以自动创建一个唯一的标识

    label:显示在静态控件中的文本内容。

    pos:一个wx.Point对象或者一个python元组。他是窗口部件的位置

    size:一个wx.Size对象或者一个python元组。他是窗口部件的尺寸

    style:样式标记

    name:对象的名字

    实例01:使用wx.StaticText输出python之禅.

    import wx
    class MyFrame(wx.Frame):
        def __init__(self,parent,id):
            wx.Frame.__init__(self,parent,id,title='创建StaticText类',
                              pos = (100,100),size = (600,400))
            panel= wx.Panel(self) #创建画板
            #创建标题,并设置字体
            title = wx.StaticText(panel,label="Python之禅",pos = (100,20))
            font = wx.Font(16,wx.DEFAULT,wx.FONTSTYLE_NORMAL,wx.NORMAL)
            title.SetFont(font)
            #创建文本
            wx.StaticText(panel,label = "优美胜于丑陋",pos = (50,50))
            wx.StaticText(panel,label="明了胜于晦涩", pos = (50, 70))
            wx.StaticText(panel, label="简洁胜于复杂", pos=(50, 90))
            wx.StaticText(panel, label="复杂胜于凌乱", pos=(50, 110))
            wx.StaticText(panel, label="扁平胜于嵌套", pos=(50, 130))
            wx.StaticText(panel,label="间隔胜于紧凑", pos = (50, 150))
            wx.StaticText(panel, label="可读性很重要", pos=(50, 170))
            wx.StaticText(panel, label="即便假借特例的实用性之名,也不可违背这些规则", pos=(50, 190))
            wx.StaticText(panel, label="不要包容所有错误,除非你确定需要这样做", pos=(50, 210))
            wx.StaticText(panel, label="当存在多种可能,不要尝试去猜测", pos=(50, 230))
            wx.StaticText(panel, label="尽量找一种,最好是唯一一种明显的解决方案", pos=(50, 250))
            wx.StaticText(panel, label="虽然这并不容易,因为你不是 Python 之父", pos=(50, 270))
            wx.StaticText(panel, label="做也许好过不做,但不假思索就动手还不如不做", pos=(50, 290))
            wx.StaticText(panel, label="如果你无法向人描述你的方案,那肯定不是一个好方案;反之亦然", pos=(50, 310))
            wx.StaticText(panel, label="命名空间是一种绝妙的理念,我们应当多加利用", pos=(50, 330))
    if __name__ == "__main__":
        app = wx.App()
        frame = MyFrame(parent=None,id = -1)
        frame.Show()
        app.MainLoop()

      上述代码中,使用panel = wx.Panel(self)来创建画板,并将panel作为父类,然后将组建放入窗体中,此外,使用wx.Font类来设置字体创建一个字体实例,需要使用如下的构造函数:

    wx.Font(pointSize,family,style,weight,underline=False,faceName="",encoding = wx.FONTENCODING_DEFFAULT)

    pointSize:字体的整数尺寸,单位为磅。

    family:用于快速指定一个字体而不需要知道实际字体的名字。

    style:指字体是否倾斜。

    weight:指字体的醒目程度。

    underline:在windows系统下生效,如果取值为true,则是加下划线,False则无下划线。

    faceName:指定字体名。

    encoding= 允许在几个编码中选择一个,大多数情况可以使用默认编码。

    运行结果如图

     2 、TextCtrl输入文本类

      wx.StaticText类智能够用于显示纯粹的静态文本,但是有时候要输入文本与用户进行交互,此时就需要使用wx.TextCtrl类,它允许输入单行和多行文本,他可以做为密码输入控件。

      wx.TextCtrl类的构造函数语法格式如下: 

    wx.TextCtrl(parent,id,value = " ",pos = wx.DefaulPosition,size = wx.DefaultSize,style= 0,validator =wx.DefaultValidator name =wx.textCtrlNameStr) 

       参数说明:

      style:单行wxTextCtrl样式,取值说明如下:

        wx.TE_CENTER:控制中的文本居中。

        wx.TE_LEFT:控件中的文本左对齐

        wx.TE_NOHIDESEL:文本始终高亮显示,只适用于windows.

        wx.TE._PASSWORD:不显示所键入的文本,以星号(*)代替显示。

        wx.TE_PROCESS_ENTER:如果使用该参数,那么当用户在空间内按下 回车              时,一个文本输入时间将会触发。否则按键时间由该文本控件或对话框管理

        wx.TE_PROCESS_TAB:如果指定了这个样式,那么通常的字符串事件在按下            【TAB】键时创建(一般以为一个制表符将会被插入文本),否则tab由对话框来管             理,通常指控件之间的切换

        wx.TE_READONLY:文本控件为只读,用户不能修改其中的文本。

        wx.TE_RIGHT:控件中的文本左右对齐。

      value:显示该控件中的初始文本。

      validator:常用于过滤数据以确保只能键入要接受的数据。

    实例2,使用一个wx.TextCtrl类和wx.StaticText类实现一个包含用户名和密码的登录界面。

    import wx
    class MyFrame(wx.Frame):
        def __init__(self,parent,id):
            wx.Frame.__init__(self,parent,id,title="创建TextCtrl类",
                              size = (400,300))
            panel = wx.Panel(self)
            self.title = wx.StaticText(panel,label="请输入用户名和密码",pos = (140,20))
            self.label_user = wx.StaticText(panel,label="用户名:",pos=(50,50))
            self.text_user = wx.TextCtrl(panel,pos = (100,50),size=(235,25),style = wx.TE_LEFT)
            self.label_pwd = wx.StaticText(panel,pos = (50,90),label= "密   码")
            self.text_password = wx.TextCtrl(panel,pos = (100,90),size = (235,25),style = wx.TE_PASSWORD)if __name__== "__main__":
        app = wx.App()
        frame = MyFrame(parent=None, id=-1)
        frame.Show()
        app.MainLoop()

      上述代码中,使用wx.TextCtrl类生成用户名,并且设置控件中的文本左对齐。使用wx.TextCtrl类,生成密码。并且设置文本用型号代替。执行效果如图

      

     3、Button按钮类

      按钮是GUI界面应用最为广泛的控件,他常用语捕获用户生成的单机时间,最明显的用途是触发绑定到一个处理函数,wxPython类库提供不同类型的按钮,其中最常用的是wx.Button类。

    实例3,在实例2的基础上加上【确认】和【取消】按钮

    import wx
    class MyFrame(wx.Frame):
        def __init__(self,parent,id):
            wx.Frame.__init__(self,parent,id,title="创建TextCtrl类",
                              size = (400,300))
            panel = wx.Panel(self)
            self.title = wx.StaticText(panel,label="请输入用户名和密码",pos = (140,20))
            self.label_user = wx.StaticText(panel,label="用户名:",pos=(50,50))
            self.text_user = wx.TextCtrl(panel,pos = (100,50),size=(235,25),style = wx.TE_LEFT)
            self.label_pwd = wx.StaticText(panel,pos = (50,90),label= "密   码")
            self.text_password = wx.TextCtrl(panel,pos = (100,90),size = (235,25),style = wx.TE_PASSWORD)
            self.bt_confirm = wx.Button(panel,label="确定",pos=(105,130))
            self.bt_cancel = wx.Button(panel,label = "取消",pos = (195,130))
    if __name__== "__main__":
        app = wx.App()
        frame = MyFrame(parent=None, id=-1)
        frame.Show()
        app.MainLoop()
    Button

    四、BoxSizer布局

      在前面的实例中,使用了文本和按钮等空间并将这些空间通过pos参数布置在pannel面板上。虽然这种设置坐标的方式很容易理解,但是过程很麻烦,此外空间的几核位置是绝对位置,也就是固定道德。当调整窗口大小时,界面会不美观。在wxPython中有一种更智能的布局方式-sizer(尺寸器)。sizer是用户自动布局一组窗口空间的算法。sizer被附加到一个容器,通常是一个框架或者面板。在父容器中,创建的子窗口空间必须被分别添加到sizer。当sizer被附加到容器时,它随后就可以管理它所包含的子布局。

      wxPython提供了5个sizer.

       (1)使用BoxSizer布局

      从尺寸器会管理组件的尺寸。只要将部件添加到尺寸器上,再添加一些布局参数,就可以让尺寸器自己去管理父组件的尺寸。下面使用BoxSize实现简单的布局。代码如下:

    import wx
    class MyFrame(wx.Frame):
        def __init__(self,parent,id):
            wx.Frame.__init__(self,parent,id,"用户名登录",size = (400,300))
            panel = wx.Panel(self)
            self.title = wx.StaticText(panel,label = "请输入用户名和密码")
            #添加容器,容器中控件按纵向排列
            vsizer = wx.BoxSizer(wx.VERTICAL)
            vsizer.Add(self.title,proportion = 0,flag = wx.BOTTOM|wx.TOP|wx.ALIGN_CENTER,border = 15)
            panel.SetSizer(vsizer)
    if __name__ == "__main__":
        app = wx.App()
        frame = MyFrame(parent=None,id = -1)
        frame.Show()
        app.MainLoop()

    执行结果如图

     上述代码中,首先设置了增加背景控件(wx.Panel),并创建了一个wx.BoxSizer,它带一个决定其水平还是垂直的参数(wx.HORIZONTAL或者wxVERTICAL),默认为水平;然后用Add方法将孔家加入到sizer;最后使用面板SetSizer()方法设定他的尺寸器。

      Add()方法的语法格式如下;

    Box.add(control,proportion,flag,border)

      参数说明:

      control:要添加的控件。

      proportion:所添加控件在定义的方式所代表方向向上占据的空间比例。如果有如3个按钮,他们的比例值分别为0,1,2,他们都已经天追到一个宽度为30的水平排列wx.BoxSizer,起始宽度都是10,当sizer的宽度从30变成60时,按钮1的宽度保持不变,任然是10,按钮2的苦读约为(10+(60-30)*1/(1+2))=30,按钮2约为20.

      flag:flag参数与border参数结合使用可以指定边距宽度,包括以下选项:

        wx.LEFT:左边距

        wx.RIGHT:右边距

        wx.BOTTOM:底边距

        wx.TOP:上边距

        wx.ALL:上下左右4个边距

        可以通过竖线“|”操作符,来联合使用这些标志,此flag参数还可以与proportion是参数结合,指定控件本身的对齐(排列)方式,包括以下选项:

        wx.ALIGN_LEFT:左边对齐

        wx.ALIGN_RIGHT:右边对齐

        wx.ALIGN_TOP:顶部对齐

        wx.ALLGN_BOTTOM:底边对齐

        wx.ALGN_CENTER_VERTICAL:处置对齐

        wx.ALIGN_CENTER_HORIZONTAL:水平对齐

        wx.ALIGN_CENTER:居中对齐

        wx.EXPAND:所添加控件将占有sizer定位方向上所有可用的控件

        boder:控制所添加控件的边距,就是在部件之间添加一些像素的空白。

    实例4,使用BoxSizer布局方式,实现实例3道德界面布局效果。具体代码如下:

    # 导入wxPython
    import wx
    
    
    class MyFrame(wx.Frame):
        def __init__(self, parent, id):
            wx.Frame.__init__(self, parent, id, "用户登录", size=(400, 300))
            panel = wx.Panel(self)# 创建面板
    
            # 创建文本,左对齐
            self.title = wx.StaticText(panel, label="请输入用户名和密码 ")#设置控件名称
            self.label_user = wx.StaticText(panel, label="用户名:")
            self.text_user = wx.TextCtrl(panel, style=wx.TE_LEFT)#输入框
            self.label_pwd = wx.StaticText(panel, label="密     码:")
            self.text_password = wx.TextCtrl(panel, style=wx.TE_PASSWORD)#输入框
    
            # 创建“确定”,“取消”按钮并 绑定事件
            self.bt_confirm = wx.Button(panel, label="确定")
            self.bt_canel = wx.Button(panel, label=" 取消")
    
            # 创建布局 添加容器,容器中控件横向排列
            hsizer_user = wx.BoxSizer(wx.HORIZONTAL)
            hsizer_user.Add(self.label_user, proportion=0, flag=wx.ALL, border=5)#文本的[用户名占比]
            hsizer_user.Add(self.text_user, proportion=1, flag=wx.ALL, border=5)#[用户名输入框占比]
            #因为是用户名和用户名的输入框是在一行,所以设置用1个容器来设置,以下都一样
            hsizer_pwd = wx.BoxSizer(wx.HORIZONTAL)
            hsizer_pwd.Add(self.label_pwd, proportion=0, flag=wx.ALL, border=5)#文本的[密码占比]
            hsizer_pwd.Add(self.text_password, proportion=1, flag=wx.ALL, border=5)#[密码输入框占比]
            hsizer_button = wx.BoxSizer(wx.HORIZONTAL)
            hsizer_button.Add(self.bt_confirm, proportion=0, flag=wx.ALIGN_CENTRE, border=5)#按钮确认占比
            hsizer_button.Add(self.bt_canel, proportion=0, flag=wx.ALIGN_CENTRE, border=5)#按钮取消占比
    
    
            # 添加容器,容器中的控件纵向排列
            vsizer_all = wx.BoxSizer(wx.VERTICAL)
            vsizer_all.Add(self.title, proportion=0, flag=wx.BOTTOM | wx.TOP | wx.ALIGN_CENTRE, border=15)
            #title是单独的,所以在横向没设置容器
            vsizer_all.Add(hsizer_user, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=45)
            vsizer_all.Add(hsizer_pwd, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=45)
            vsizer_all.Add(hsizer_button, proportion=0, flag=wx.ALIGN_CENTRE | wx.TOP | wx.RIGHT, border=15)
            panel.SetSizer(vsizer_all)
            #备注因为是竖向排列只有1个容器,横向的话有3个容器
    
    
    if __name__ == "__main__":
        app = wx.App()
        frame = MyFrame(parent=None, id=-1)
        frame.Show()
        app.MainLoop()

      在上述代码中,首先创建按钮和文本控件,然后将其添加到容器中,并且设置横向排列接着设置纵向排列。在蒲剧过程中,通过设置控件的flag和border参数,实现控件位置间的布局。运行结果和实例3的类似。

    五、绑定事件

      当发生一个事件时,需要让程序注意这些事件并作出反应。这时可以将函数绑定到所涉及事件可能的控件上,当事件发生时,函数就会被调用利用控件Bind()方法将事件处理处理函数绑定到给定的事件上。例如为【确定】按钮加一个单机事件,代码如下。

    bt_confirm.Bind(wx.EVT_BUTTON,OnclickSubmit)

     参数说明:

      wx.EVT_BUTTON:事件类型为按钮箱,在wxPython中有很多wx.EVT_开头的事件类型,例如,类型wx.EVT_MOTION产生移动鼠标,类型wx.ENTER_WINDOW和wx.LEAVE_WINDOW产生当鼠标进入或者离开一个窗口空间,类型wx.EVT_MOUSEWHEEL被绑定到鼠标滚轮的活动

      OnclickSunbmit:方法名,事件发生立即执行的方法。

      实例5,在实例4的基础上,分别为“确定”,“取消”按钮添加单机事件当用户输入用户名密码后,单机“确定”按钮,如果输入的用户名为“sjc”且密码为“xfd”.则弹出对话框提示“登陆成功”,否则提供“用户名密码不匹配”。当用户单机“取消”按钮时,清空用户输入的用户名密码。

    # 导入wxPython
    import wx
    
    
    class MyFrame(wx.Frame):
        def __init__(self, parent, id):
            wx.Frame.__init__(self, parent, id, "用户登录", size=(400, 300))
            panel = wx.Panel(self)# 创建面板
    
            # 创建文本,左对齐
            self.title = wx.StaticText(panel, label="请输入用户名和密码 ")#设置控件名称
            self.label_user = wx.StaticText(panel, label="用户名:")
            self.text_user = wx.TextCtrl(panel, style=wx.TE_LEFT)#输入框
            self.label_pwd = wx.StaticText(panel, label="密     码:")
            self.text_password = wx.TextCtrl(panel, style=wx.TE_PASSWORD)#输入框
    
            # 创建“确定”,“取消”按钮并 绑定事件
            self.bt_confirm = wx.Button(panel, label="确定")
            self.bt_confirm.Bind(wx.EVT_BUTTON,self.OnclickSunbmit)
            self.bt_canel = wx.Button(panel, label=" 取消")
            self.bt_canel.Bind(wx.EVT_BUTTON, self.OnclickCancel)
    
            # 创建布局 添加容器,容器中控件横向排列
            hsizer_user = wx.BoxSizer(wx.HORIZONTAL)
            hsizer_user.Add(self.label_user, proportion=0, flag=wx.ALL, border=5)#文本的[用户名占比]
            hsizer_user.Add(self.text_user, proportion=1, flag=wx.ALL, border=5)#[用户名输入框占比]
            #因为是用户名和用户名的输入框是在一行,所以设置用1个容器来设置,以下都一样
            hsizer_pwd = wx.BoxSizer(wx.HORIZONTAL)
            hsizer_pwd.Add(self.label_pwd, proportion=0, flag=wx.ALL, border=5)#文本的[密码占比]
            hsizer_pwd.Add(self.text_password, proportion=1, flag=wx.ALL, border=5)#[密码输入框占比]
            hsizer_button = wx.BoxSizer(wx.HORIZONTAL)
            hsizer_button.Add(self.bt_confirm, proportion=0, flag=wx.ALIGN_CENTRE, border=5)#按钮确认占比
            hsizer_button.Add(self.bt_canel, proportion=0, flag=wx.ALIGN_CENTRE, border=5)#按钮取消占比
    
    
            # 添加容器,容器中的控件纵向排列
            vsizer_all = wx.BoxSizer(wx.VERTICAL)
            vsizer_all.Add(self.title, proportion=0, flag=wx.BOTTOM | wx.TOP | wx.ALIGN_CENTRE, border=15)
            #title是单独的,所以在横向没设置容器
            vsizer_all.Add(hsizer_user, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=45)
            vsizer_all.Add(hsizer_pwd, proportion=0, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=45)
            vsizer_all.Add(hsizer_button, proportion=0, flag=wx.ALIGN_CENTRE | wx.TOP | wx.RIGHT, border=15)
            panel.SetSizer(vsizer_all)
            #备注因为是竖向排列只有1个容器,横向的话有3个容器
    
        def OnclickSunbmit(self, event):
            message = ""
            username = self.text_user.GetValue()
            password = self.text_password.GetValue()
            if username == "" or password == "":
                message = "用户名密码不能为空"
            elif username == "sjc" and password == "xfd":
                message = "登陆成功"
            else:
                message = "用户名密码不匹配"
            wx.MessageBox(message)
        def OnclickCancel(self,event):
            self.text_user.SetValue("")#清空用户名
            self.text_password.SetValue("")#清空密码
    
    
    
    
    
    
    if __name__ == "__main__":
        app = wx.App()
        frame = MyFrame(parent=None, id=-1)
        frame.Show()
        app.MainLoop()
    事件

      在商户代码中,分别使用bind()函数为bt.confirm和bt_cancel绑定了单机事件。运行结果如图所示

       

  • 相关阅读:
    口腔溃疡
    English 好的报纸
    线段树
    归并排序 霍纳规则(法则) 统计逆序对
    xfce4桌面自动整理脚本
    解决xubuntu的thunar第一次启动慢
    解决ibus图标为红圈(图标丢失)
    linux tar 备份命令
    ubuntu中的Wine详解
    我的conky配置
  • 原文地址:https://www.cnblogs.com/sunjinchao/p/11995402.html
Copyright © 2011-2022 走看看