Python自帶的GUI界面(Tkinter)教程


1.Python Tkinter(GUI圖形界面):

a. What's Tkinter(Tkinter 是什么)?

Tkinter是Python自帶的一個GUI庫,他可以將我們在command line中的操作進行可視化操作。並且它簡單的構造, 多平台, 多系統的兼容性, 能讓它成為讓你快速入門定制窗口文件的好助手. 它在 python 窗口視窗模塊中是一款簡單型的. 所以用來入門, 熟悉 窗口視窗的使用, 非常有必要.

b. Tkinter創建窗口以及標簽按鈕:

我們可以通過如下代碼校驗你的Tkinter包是否安裝成功:

python -m tkinter # 如果安裝成功,那么你的桌面會彈出一個窗口,如下:

alt tk原始窗口

接下來,我們要自己創建一個窗口,並且在窗口中加入一個標簽Label:

import tkinter as tk

window = tk.Tk() # 創建一個窗口對象
window.title('my first window') #給窗口命名
window.geometry('200x100') #定義窗口的長寬,geometry方法中傳入字符串參數,字符串中應為長x寬(Note:x是小寫字母x)

# Label(master = None, cnf = {}, **kw), kw參數是類似dict一樣接收label組件定義的鍵值對
l = tk.Label(window, text='successful! created new Label', bg='green', font=('Arial', 12), width=25, height=4)
l.pack() #將定義好的label添加到window上

window.mainloop()  #mainloop實際上是使用while循環實現的,因為窗口的內容是會動態變化的

alt create window & Label

接下來我們繼續在窗口上創建Button按鈕,並且我們實現了點擊一次按鈕Label消失,再點擊一次按鈕Label重新顯示:

import tkinter as tk

window = tk.Tk() # 創建一個窗口對象
window.title('my first window') #給窗口命名
window.geometry('200x100') #定義窗口的長寬,geometry方法中傳入字符串參數,字符串中應為長x寬(Note:x是小寫字母x)

# Label(master = None, cnf = {}, **kw), kw參數是類似dict一樣接收label組件定義的鍵值對
#l = tk.Label(window, text='successful! created new Label', bg='green', font=('Arial', 12), width=25, height=4)
var = tk.StringVar() #將label中的文本動態化設置,可以利用var.set()方法設置textvariable
l = tk.Label(window, textvariable=var, bg='green', font=('Arial', 12), width=25, height=4)
l.pack() #將定義好的label添加到window上

is_Hidden = False # 設置一個flag變量,用來判斷現在窗口的label是顯示的還是未顯示的
def hidden_me():
    global is_Hidden
    if is_Hidden == False:
        is_Hidden = True
        var.set('click me and hidden')
    else:
        is_Hidden = False
        var.set('')

var1 = tk.StringVar()
var1.set('hidden')
#Button(master, option = value, ..), command是點擊后發生什么效果的函數
b = tk.Button(window, textvariable = var1, width = 12, height = 2, command = hidden_me)
b.pack()  # 將button顯示在窗口中

window.mainloop()  #mainloop實際上是使用while循環實現的,因為窗口的內容是會動態變化的

點擊Button之前:

點擊Button之后:

再點擊hidden Button,Label又會隱藏。

c. Tkinter在窗口中使用輸入框Entry & 文本框Text:

我們在網頁中經常會遇到輸入框和文本框兩種常用的表單項,那么,在Tkinter中有Entry和Text對應了這兩種常用的框。我們接下來要做一個小案例(在輸入框輸入文本,然后設置兩個button,button1是在你點擊文本框內容的光標處插入輸入框中的文本。button2是在文本框內容的末尾插入輸入框的文本)

import tkinter as tk

window = tk.Tk()
window.title('My Window')
window.geometry('300x200')
e = tk.Entry(window, show = None) # show = None:輸入字符可見, show = '*':
e.pack()

# 在光標處插入entry輸入框的數據
def insert_point():
    var = e.get()
    t.insert('insert', var)

# 在文本末尾插入entry輸入框的數據
def insert_end():
    var = e.get()
    t.insert('end', var)
b1 = tk.Button(window, text = 'insert point', width = 15, height = 2, command = insert_point)
b1.pack()
b2 = tk.Button(window, text = 'insert end', width = 15, height = 2,command = insert_end)
b2.pack()

t = tk.Text(window, height = 5) # height定義文本框有多少行
t.pack()

window.mainloop()

初始狀態:

點擊button1 在光標處插入:

![](/Users/liyan/Library/Application Support/typora-user-images/image-20200712223347218.png)

![](/Users/liyan/Library/Application Support/typora-user-images/image-20200712223421949.png)

點擊button2在文本框末尾插入:

這樣就使用Entry & Text完成了一個小實例

Note:以上例子在PyCharm中運行,button上的文本不會顯示,我的電腦是Mac,Python版本3.7+,在命令行運行腳本既可以看到button中的文本屬性。大佬如果知道原因可以給我留言。

d. Tkinter中Listbox的使用:

我們經常在網頁上使用列表框,就比如選擇你在填寫表單的時候,你需要填寫你的學歷,這時候會有一個下拉列表框,上面寫着:初中畢業,中專,高中,大學等常見的學歷選項,你下拉選擇好,點擊后就會自動給您填上,我們下面做一個小例子:使用Tikinter中的listbox實現點擊下拉列表框中的value,在點擊Button,將value打印到窗口設置的Label中。

import tkinter as tk

window = tk.Tk()
window.title('My Listbox')
window.geometry('300x200')

var1 = tk.StringVar()
l = tk.Label(window, textvariable = var1, bg = 'yellow', font=('Arial', 12), width=25, height=4)
l.pack()

def print_selection():
    tmp = lb.get(lb.curselection()) #curselection()表示的是獲取當前列表所選中的
    var1.set(tmp) # 將當前所選中的listbox的value設置到Lable上。

b = tk.Button(window, text = 'print list selection', width = 12, height = 2, command = print_selection)
b.pack()
var2 = tk.StringVar()
var2.set(('first', 'second', 'third', 'fourth'))
lb = tk.Listbox(window, listvariable = var2) # 初始化listbox時,將var2賦值給lb初始化
list_items = [1, 2, 3, 4]
for item in list_items:
    lb.insert('end', item)

# 還可以使用insert(index, value)形式,按照list的下標插入value
# lb.insert(1, 'one')
# 使用delete(index)形式,刪除list中index的元素
lb.pack()

window.mainloop()

初始化:

![](/Users/liyan/Library/Application Support/typora-user-images/image-20200713210112094.png)

選中列表框任意一個value打印到Label上:

e. Tkinter中RadioButton的使用

大家應該都在網上做過測試,像單選題的那種選擇框就是RadioButton的典型應用。我們將做一個ABC三個選項,當你選擇某一個選項時,點擊后,窗口的Label就會打印出你當前選的值是什么的例子:

import tkinter as tk

window = tk.Tk()
window.title('My RadioButton')
window.geometry('400x400')

var = tk.StringVar()
l = tk.Label(window, text = 'empty', bg = 'red', font = ('Arial', 12), width = 25, height = 5)
l.pack()

def choose_button():
    l.config(text = 'you have choosen ' + var.get()) #config()給Label進行屬性設置,這里獲取當前選項的value進行綁定

# RadioButton中variable將所選中的value值綁定到var變量中,方便在點擊后,給label進行綁定
r1 = tk.Radiobutton(window, text = 'Option A', variable = var, value = 'A', command = choose_button)
r1.pack()

r2 = tk.Radiobutton(window, text = 'Option B', variable = var, value = 'B', command = choose_button)
r2.pack()

r3 = tk.Radiobutton(window, text = 'Option C', variable = var, value = 'C', command = choose_button)
r3.pack()

window.mainloop()

初始:

![](/Users/liyan/Library/Application Support/typora-user-images/image-20200713212826346.png)

這里其實應該不是三個-號,是mac系統才有的,windows系統應該是正常的。

choose 后:

f. Tkinter中Scale(滾動條)的使用:

我們經常會在某些特定的場合使用滾動條,但是那種滾動條使用比較多的可能是網站登錄使用的滾動驗證碼。我們必須把殘缺的圖案滑動到指定的缺口令其重合。我們現在就做一個滾動條的小例子:滑動滾動條,將滾動條滑動所到的刻度傳給窗口中的Label將其顯示:

import tkinter as tk

window = tk.Tk()
window.title('My Scale')
window.geometry('300x300')

l = tk.Label(window, bg = 'blue', width = 20, text = 'empty')
l.pack()

# 這里參數v是用來記錄滾動條定位的數據(滑動到哪里了)
def job(v):
    l.config(text = 'you have choosen ' + v)

# 參數解釋:
# from_ = 1, to = 20:從1到20的意思,就是滾動條的起始刻度到終止刻度
# orient = tk.HORIZONAL是設置滾動條的方向,是縱向放,還是橫向放
# length是指整個滾動條在window上的長度(以px像素為單位)
# resolution = 0.01是設置滾動條的精度,移動一步按照兩位小數來計算
# showvalue = 1:表示滾動條的游標cur上方是否會顯示當前選中的滑動值
# tkinterval = 4:設置滾動條下方的坐標間隔,這里按照每4個單位來計算
s = tk.Scale(window, label = 'push me', from_ = 1, to = 20, orient = tk.HORIZONTAL,
             length = 200, showvalue = 1, tickinterval = 4, resolution = 0.01, command = job)
s.pack()

window.mainloop()

初始:

滑動后:

g. Tkinter中CheckButton(復選框):

我們常常會在表單中遇到如下的選擇框,讓您填寫會哪些編程語言,下面羅列了最常用的編程語言,你點擊一個框就選中了一門語言,你可以同時點擊多個選擇框,進行多選。所以稱復選框或者多選框。我們也模仿做一個常用語言復選框,每選擇一個讓Label顯示不同的內容:

import tkinter as tk

window = tk.Tk()
window.title('My CheckBox')
window.geometry('300x300')

l = tk.Label(window, bg = 'red', width = 20, text = 'empty')
l.pack()

# 通過判斷每個復選框是否被選擇來進行判斷。再將Label顯示內容進行替換
def job():
    if (var1.get() == 1) and (var2.get() == 0) and (var3.get() == 0):
        l.config(text = 'I love only C++')
    elif (var1.get() == 0) and (var2.get() == 1) and (var3.get() == 0):
        l.config(text = 'I love only Java')
    elif (var1.get() == 0) and (var2.get() == 0) and (var3.get() == 1):
        l.config(text = 'I love only Python')
    elif (var1.get() == 1) and (var2.get() == 1) and (var3.get() == 0):
        l.config(text = 'I love C++ and Java')
    elif (var1.get() == 1) and (var2.get() == 0) and (var3.get() == 1):
        l.config(text = 'I love C++ and Python')
    elif (var1.get() == 0) and (var2.get() == 1) and (var3.get() == 1):
        l.config(text = 'I love Java and Python')
    elif (var1.get() == 1) and (var2.get() == 1) and (var3.get() == 1):
        l.config(text = 'I love C++ and Java and Python')
    else :
        l.config(text = 'I love all lanuage')

var1 = tk.IntVar()
# 參數解釋: variable:表示將var1變量綁定到cb1上
# 參數onvalue和前面講的部件radiobutton中的value相似, 當我們選中了這個checkbutton,
# onvalue的值1就會放入到var1中, 然后var1將其賦值給參數variable,offvalue用法相似,
# 但是offvalue是在沒有選中這個checkbutton時,offvalue的值1放入var1,然后賦值給參數variable
# 這是創建一個checkbutton部件,以此類推,可以創建多個checkbutton
cb1 = tk.Checkbutton(window, text = 'C++', variable = var1, onvalue = 1, offvalue = 0, command = job)
var2 = tk.IntVar()
cb2 = tk.Checkbutton(window, text = 'Java', variable = var2, onvalue = 1, offvalue = 0, command = job)
var3 = tk.IntVar()
cb3 = tk.Checkbutton(window, text = 'Python', variable = var3, onvalue = 1, offvalue = 0, command = job)
cb1.pack()
cb2.pack()
cb3.pack()

window.mainloop()

初始:

選擇單個:

選擇多個:

h. Tkinter的Canvas(畫布):

Canvas畫布部件是指的是像一塊畫板類似的,可以在上面嵌套圖片,以及一些圖形。模擬一個實例:嵌套一個圖片在左上角,然后畫出一些幾何圖形,通過點擊button使得某一個圖形進行移動操作:

import tkinter as tk

window = tk.Tk()
window.title('My Carvans')
window.geometry('300x200')
# 定義一個畫布
canvas = tk.Canvas(window, bg='green', height=100, width=200)
# 讀取一個圖片,Mac系統只能讀取gif后綴圖片, 路徑最好可以使用絕對路徑,我的是放在同一個目錄下
image_file = tk.PhotoImage(file='inf.gif')
# 創造一個圖片變量
# 里面的參數10,10就是圖片放入畫布的坐標,
# 而這里的anchor=nw則是把圖片的左上角作為錨定點,在加上剛剛給的坐標位置,即可將圖片位置確定。
# 最后一個參數的意思大家應該都知道,就是將剛剛存入的圖片變量,賦值給image。
image = canvas.create_image(10, 10, anchor='nw', image=image_file)
x0, y0, x1, y1= 50, 50, 80, 80
line = canvas.create_line(x0, y0, x1, y1) # 創建一條直線
oval = canvas.create_oval(x0, y0, x1, y1, fill='red') # 創建一個圓,填充色為紅色
arc = canvas.create_arc(x0+30, y0+30, x1+30, y1+30, start=0, extent=180) # 創建一個角度從0到180的扇形
rect = canvas.create_rectangle(100, 30, 100+20, 30+20) # 創建一個矩形
canvas.pack()

# 定義每點擊一次按鈕正方形向下移動兩個單位操作
def moveit():
    canvas.move(rect, 0, 2)

b = tk.Button(window, text='move', command=moveit).pack()


window.mainloop()

初始:

點擊move每次向下移動兩個單位長度

i. Tkinter中的MenuBar(菜單欄):

窗口的菜單欄想必大家都見過,Mac上是固定在屏幕左上角的菜單欄,上面包括一些常用的設置和操作。

我們在Tkinter中可以使用MenuBar模仿做出類似效果的菜單欄:

import tkinter as tk

window = tk.Tk()
window.title('My MenuBar')
window.geometry('200x200')

l = tk.Label(window, text='', bg='red')
l.pack()
counter = 0

# 功能:每點擊一次'New''Open''Save'就將counter+1,然后設置到Label上
def do_job():
    global counter
    l.config(text='do '+ str(counter))
    counter+=1

# 定義一個MenuBar,在窗口上方
menubar = tk.Menu(window)
# 定義一個空的菜單欄單元
filemenu = tk.Menu(menubar, tearoff=0)
# 將定義的菜單欄單元命名為File
menubar.add_cascade(label='File', menu=filemenu)
# 給菜單欄添加小的菜單,就是我們平時窗口操作的下拉菜單,每一個小的菜單對應一個功能。
filemenu.add_command(label='New', command=do_job)
filemenu.add_command(label='Open', command=do_job)
filemenu.add_command(label='Save', command=do_job)
filemenu.add_separator() # 加一條分割線
filemenu.add_command(label='Exit', command=window.quit)

editmenu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label='Edit', menu=editmenu)
editmenu.add_command(label='Cut', command=do_job)
editmenu.add_command(label='Copy', command=do_job)
editmenu.add_command(label='Paste', command=do_job)

submenu = tk.Menu(filemenu)
filemenu.add_cascade(label='Import', menu=submenu, underline=0) # 在filemenu加入一個小菜單
submenu.add_command(label="Submenu1", command=do_job)

window.config(menu=menubar)

window.mainloop()

初始:

菜單欄:

可以點擊每個小菜單查看是否實現了計數功能退出功能等操作。

j. Tkinter中Frame(框架):

Frame 是一個在 窗口上分離小區域的部件, 它能將 窗口 分成不同的區,然后存放不同的其他部件. 同時一個 Frame 上也能再分成兩個 Frame, Frame 可以認為是一種容器.

我們現在將在窗口上添加一個主Frame,然后在主Frame上繼續pack子Frame在它的右邊或左邊。

import tkinter as tk

window = tk.Tk()
window.title('My Frame')
window.geometry('200x200')
tk.Label(window, text='on the window').pack()

# 創建一個主框架
frm = tk.Frame(window)
frm.pack()
# 基於frm框架創建一個左邊的子框架
frm_l = tk.Frame(frm)
# 基於frm框架創建一個右邊的子框架
frm_r = tk.Frame(frm)
frm_l.pack(side='left') # pack中的side方法是將frm_l,frm_r兩個子框架按照左或右的方向添加到frm上
frm_r.pack(side='right')

# 這里的三個label就是在我們創建的frame上定義的label部件,還是以容器理解,就是容器上貼了標簽,
# 來指明這個是什么,解釋這個容器。
tk.Label(frm_l, text='on the frm_l1').pack()
tk.Label(frm_l, text='on the frm_l2').pack()
tk.Label(frm_r, text='on the frm_r1').pack()
window.mainloop()

Result:

k. Tkinter中的MessageBox(彈窗框):

在網頁中我們點擊一些鏈接可能會出現彈窗提醒,提醒有警告提醒,錯誤提醒,以及通過提醒等。我們下面將用一個例子闡述Tkinter中的MessageBox中的幾種彈窗:

import tkinter as tk
import tkinter.messagebox

window = tk.Tk()
window.title('My MessageBox')
window.geometry('200x200')

def job():
    # tk.messagebox.showinfo(title='Hi', message='hahahaha')   # return 'ok'
    # tk.messagebox.showwarning(title='Hi', message='nononono')   # return 'ok' 警告框
    # tk.messagebox.showerror(title='Hi', message='No!! never')   # return 'ok' 錯誤框
    # print(tk.messagebox.askquestion(title='Hi', message='hahahaha'))   # return 'yes' , 'no' # 驗證yes or no框
     print(tk.messagebox.askyesno(title='Hi', message='hahahaha'))   # return True, False
    # print(tk.messagebox.asktrycancel(title='Hi', message='hahahaha'))  # return True, False
    # print(tk.messagebox.askokcancel(title='Hi', message='hahahaha'))  # return True, False
    # print(tk.messagebox.askyesnocancel(title="Hi", message="haha"))  # return, True, False, None

b = tk.Button(window, text = 'click me', bg = 'yellow', command = job)
b.pack()

window.mainloop()

Showinfo:

![](/Users/liyan/Library/Application Support/typora-user-images/image-20200714212513455.png)

Showwarning:

![](/Users/liyan/Library/Application Support/typora-user-images/image-20200714212736650.png)

Showerror:

Askyesno:

![](/Users/liyan/Library/Application Support/typora-user-images/image-20200714213022344.png)

l. Tkinter中的擺放組件的三種方法pack, grid, place:

import tkinter as tk

window = tk.Tk()
window.geometry('200x200')

# 使用pack(side = '')來放置組件的位置
'''
tk.Label(window, text='1').pack(side='top')
tk.Label(window, text='1').pack(side='bottom')
tk.Label(window, text='1').pack(side='left')
tk.Label(window, text='1').pack(side='right')
'''

# 使用grid進行位置擺放組件:padx:單元格左右間距 pdy:單元格上下間距
for i in range(4):
    for j in range(3):
        tk.Label(window, text=1).grid(row=i, column=j, padx=10, pady=10)

# 使用place進行位置擺放組件:anchor:錨點的位置nw:north west西北方向
# tk.Label(window, text=1).place(x=20, y=10, anchor='nw')

window.mainloop()

pack:

grid:

place:

到此,對於Tkinter中的一些基礎操作介紹完畢了。接下來我們將使用這些知識做一個example(about login window):

創建一個登陸注冊窗口,點擊登陸可以校驗用戶名密碼是否匹配進行判斷,可以通過注冊按鈕重新彈出一個注冊界面窗口,在里面進行注冊,可判斷兩次輸入密碼是否一致以及用戶名是否存在等操作。第一次沒有任何數據文件在使用用戶名和密碼登錄時會拋出文件不存在異常,將第一次輸入的用戶名密碼寫入一個新的 文件,這樣之后注冊,登陸就是讀取這個創建的文件。

import tkinter as tk
import pickle
import tkinter.messagebox

window = tk.Tk()
window.title('Login & Register Window')
window.geometry('450x300')

# 創建一個畫布,將圖片嵌入在畫布上,以左上角為原點,使用pack方法將畫布置於窗口頂部
canvas = tk.Canvas(window, height = 200, width = 500)
image_file = tk.PhotoImage(file = 'welcome.gif')
image = canvas.create_image(0, 0, anchor = 'nw', image = image_file)
canvas.pack(side = 'top')

# 在window上設置兩個label表示用戶名和用戶密碼
tk.Label(window, text = 'User_name:').place(x = 50, y = 150)
tk.Label(window, text = 'User_password:').place(x = 50, y = 200)

# 設置兩個輸入框,用戶名輸入框默認設置root,然后輸入框使用place在window上定位
var_name = tk.StringVar()
var_name.set('root')
entry_name = tk.Entry(window, textvariable = var_name)
entry_name.place(x = 170, y = 150)
var_pwd = tk.StringVar()
entry_pwd = tk.Entry(window, textvariable = var_pwd, show = '*')
entry_pwd.place(x = 170, y = 200)

# 定義了Login的一些操作,里面使用pyhton的pickle模塊進行對文件的操作,用dict存儲用戶名密碼
# 將dict序列化存儲到data.pickle中,再判斷用戶名密碼的時候使用pickle.load加載數據
def Login():
    user_name = var_name.get()
    user_pwd = var_pwd.get()
    try:
        with open ('data.pickle', 'rb') as f:
            user_info = pickle.load(f)
    except FileNotFoundError:
        with open('data.pickle', 'wb') as f:
            user_info = {'root': 'root'}
            pickle.dump(user_info, f)
    # 判斷用戶名是否注冊,用戶名對應的密碼是否一致
    if user_name in user_info:
        if user_pwd == user_info[user_name]:
            tk.messagebox.showinfo(title = 'Welcome', message = 'Welcome to ' + user_name)
        else:
            tk.messagebox.showerror(title = 'Error', message = 'your password is wrong, try again')
    else:
        is_register = tk.messagebox.askyesno('Welcome', 'You have not register yet. Register today?')
        # 如果還沒注冊,就跳轉窗口進行register
        if is_register:
            Register()
# 定義了Register的操作
def Register():
    # 用於處理Register的窗口中注冊button的功能
    def register():
        # 獲取輸入密碼和確認密碼,進行邏輯判斷
        np = new_pwd.get()
        npf = new_pwd_confirm.get()
        nn = new_name.get()
        with open('data.pickle', 'rb') as f:
            exist_usr_info = pickle.load(f)
        if np != npf:
            tk.messagebox.showerror('Error', 'Password and confirm password must be the same!')
        elif nn in exist_usr_info:
            tk.messagebox.showerror('Error', 'The user has already register!')
        else:
            exist_usr_info[nn] = np
            with open('data.pickle', 'wb') as f:
                pickle.dump(exist_usr_info, f)
            tk.messagebox.showinfo('Welcome', 'You have successfully register!')
            window_sign_up.destroy()
    # 創建一個新的窗口用於Register使用
    window_sign_up = tk.Toplevel(window)
    window_sign_up.geometry('350x200')
    window_sign_up.title('Register Window')

    new_name = tk.StringVar()
    new_name.set('root')
    tk.Label(window_sign_up, text='User name: ').place(x=10, y= 10)
    entry_new_name = tk.Entry(window_sign_up, textvariable=new_name)
    entry_new_name.place(x=150, y=10)

    new_pwd = tk.StringVar()
    tk.Label(window_sign_up, text='Password: ').place(x=10, y=50)
    entry_usr_pwd = tk.Entry(window_sign_up, textvariable=new_pwd, show='*')
    entry_usr_pwd.place(x=150, y=50)

    new_pwd_confirm = tk.StringVar()
    tk.Label(window_sign_up, text='Confirm password: ').place(x=10, y= 90)
    entry_usr_pwd_confirm = tk.Entry(window_sign_up, textvariable=new_pwd_confirm, show='*')
    entry_usr_pwd_confirm.place(x=150, y=90)

    btn_comfirm_sign_up = tk.Button(window_sign_up, text='Register', command = register)
    btn_comfirm_sign_up.place(x=150, y=130)

# 設置兩個button,一個用於login,一個用於register
button_login = tk.Button(window, text = 'login', command = Login)
button_login.place(x = 170, y = 250)
button_register = tk.Button(window, text = 'register', command = Register)
button_register.place(x = 270, y = 250)

window.mainloop()

整個教程的Code:請訪問code

至於Tkinter中各種組件的詳細的參數可以參考:refrence

感謝Morvan老師的教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM