亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營的一線實(shí)戰(zhàn)洞察。

Python GUI開發(fā):Tkinter從事件循環(huán)到布局管理實(shí)戰(zhàn)詳解

Python GUI開發(fā):Tkinter從事件循環(huán)到布局管理實(shí)戰(zhàn)詳解 如果你只想給手上的腳本配一個“能點(diǎn)點(diǎn)點(diǎn)”的界面Tkinter可能是最不折騰的選擇。最近我在收拾一個內(nèi)部數(shù)據(jù)整理工具需要把Excel篩選、批量重命名、參數(shù)配置全塞進(jìn)一個小窗口里第一反應(yīng)是上PyQt結(jié)果環(huán)境依賴和樣式表就折騰了半天改成Tkinter之后從窗口搭建到跑通只花了不到半小時。這篇文章把Tkinter這條鏈路的細(xì)節(jié)展開說說主窗口和事件循環(huán)怎么理解、布局該怎么選、常用控件怎么用、事件回調(diào)有哪些坑、最后再帶一個完整的批量重命名小工具。這篇詳解不打算把官方文檔里所有API抄一遍而是給出一條真正能落地的路徑你照著一個步驟走下來能做出一個看起來不寒酸、維護(hù)起來不痛苦的桌面小工具。如果你是Python新手第一次接觸GUI這篇文章也夠用我會把每個“為什么”都講清楚。1. 為什么到2025年了我還會把Tkinter當(dāng)成首選桌面小工具的務(wù)實(shí)選型1.1 標(biāo)準(zhǔn)庫這層優(yōu)勢比想象中更重要Tkinter是Python自帶的GUI標(biāo)準(zhǔn)庫底層封裝了Tk圖形庫。它最大的優(yōu)勢聽起來平平無奇不需要安裝任何第三方依賴。只要你的環(huán)境有Pythonimport tkinter就能跑。這意味著什么意味著你在任何一臺機(jī)器上都能直接運(yùn)行腳本不用擔(dān)心pip install失敗、網(wǎng)絡(luò)不通、或者某個庫和Python版本不兼容。對于一個“讓同事點(diǎn)一下就完成工作”的內(nèi)部小工具來說少一個依賴就是少一次事故。我見過很多初學(xué)者一上來就想用PyQt界面是漂亮了但Qt的設(shè)計理念比Tkinter復(fù)雜得多信號槽機(jī)制、布局系統(tǒng)、資源文件編譯、高DPI適配每一項(xiàng)都要額外學(xué)習(xí)。結(jié)果往往是工具沒做出來先和框架較了兩個星期的勁。Tkinter雖然是“老古董”但它能把“能用、夠用、可維護(hù)”這六個字做到位。1.2 各方案橫向?qū)Ρ萒kinter贏在性價比為了說清楚選型邏輯我把常見的幾種Python GUI方案擺在一起對比一下方案依賴安裝界面觀感上手難度打包體積學(xué)習(xí)成本Tkinter無需安裝偏傳統(tǒng)可用ttk改善低一般幾MB到十幾MB低PyQt6 / PySide6需要pip安裝現(xiàn)代、細(xì)膩較高幾十MB高wxPython需要pip安裝接近系統(tǒng)原生中較大中高Kivy需要pip安裝適合觸控/多媒體中高較大中高ElectronNode環(huán)境最靈活高巨大高這張表里的“打包體積”很值得注意。同樣一個簡單窗口Tkinter用PyInstaller打出來的exe通常只有10MB左右PyQt打出來可能大兩三倍。如果你的工具就是給幾個人用部署體積小一點(diǎn)分發(fā)成本就低很多。1.3 它不適合做什么邊界感比性能更重要夸了這么多也得說清楚Tkinter的邊界。它不適合做以下幾種東西復(fù)雜數(shù)據(jù)表格雖然可以用Treeview模擬表格但和Excel那種密集交互、復(fù)雜編輯體驗(yàn)比差距明顯。強(qiáng)動畫、3D、多媒體應(yīng)用Tkinter的繪圖能力基于Canvas做簡單圖表沒問題但流暢的動畫和游戲界面不是它的菜。需要皮膚級定制的商業(yè)化產(chǎn)品如果你要做對外售賣、強(qiáng)調(diào)視覺品牌的產(chǎn)品Tkinter的原生感可能不夠。這個邊界感很重要。選型錯誤比代碼寫差更致命Tkinter擅長的是“工具型界面”表單、列表、按鈕、狀態(tài)展示、文件選擇這幾樣占了企業(yè)內(nèi)部門工具的大頭也正是它的舒適區(qū)。2. 從零搭起主窗口mainloop的生命周期與窗口控制2.1 最小示例逐行拆開看先看一個最基礎(chǔ)的Tkinter窗口import tkinter as tk root tk.Tk() root.title(我的第一個Tkinter窗口) root.geometry(400x300) root.mainloop()這里面每一行都有它存在的意義tk.Tk()創(chuàng)建TK根窗口對象。這個對象一旦創(chuàng)建整個圖形界面環(huán)境就初始化了。root.title()設(shè)置窗口標(biāo)題欄文字。root.geometry(400x300)設(shè)置窗口初始大小格式是“寬x高”。root.mainloop()進(jìn)入事件循環(huán)。mainloop()是理解GUI的關(guān)鍵。它可以理解為一個內(nèi)部“死循環(huán)”但這個循環(huán)不是傻轉(zhuǎn)它在一遍遍處理三件事刷新界面、接收用戶的鼠標(biāo)鍵盤操作、執(zhí)行響應(yīng)回調(diào)。沒有這一行窗口會閃一下就消失。我用一個生活類比mainloop()就像商店開門后的營業(yè)員顧客進(jìn)來點(diǎn)擊、輸入營業(yè)員就響應(yīng)界面更新、回調(diào)函數(shù)執(zhí)行窗口關(guān)閉相當(dāng)于商店打烊循環(huán)退出程序結(jié)束。2.2 窗口屬性控制標(biāo)題、尺寸、置頂與透明實(shí)際做工具時窗口屬性經(jīng)常需要微調(diào)。下面是幾個高頻操作root.title(工具面板) root.geometry(480x36010050) # 寬480高360屏幕坐標(biāo)x100y50 root.resizable(False, False) # 禁止用戶拉伸窗口 root.minsize(400, 300) # 最小尺寸 root.maxsize(800, 600) # 最大尺寸需要讓窗口保持在最前層比如做一個“懸浮提醒面板”可以用root.attributes(-topmost, True)調(diào)整透明度也可以root.attributes(-alpha, 0.9)設(shè)置窗口圖標(biāo)在Windows上通常用iconbitmaproot.iconbitmap(icon.ico)注意如果你用PyInstaller打包后圖標(biāo)不顯示通常是路徑問題。后面第7節(jié)會專門說資源路徑的坑。2.3 子線程與UI更新不要在子線程里直接改控件很多人第一次寫GUI會遇到“窗口直接卡死”的經(jīng)典問題。原因是在mainloop里執(zhí)行了耗時操作比如循環(huán)去讀幾千個文件、調(diào)用網(wǎng)絡(luò)接口事件循環(huán)被阻塞窗口就會凍結(jié)。正確做法是把耗時任務(wù)放到子線程。但這里有一個Tkinter的硬性規(guī)則凡是操作控件、改變界面狀態(tài)必須在主線程里做子線程直接去調(diào)用label.config(text...)可能不報錯但會出現(xiàn)莫名其妙的不刷新、崩潰。常用的跨線程通信方案是“子線程放結(jié)果 主線程輪詢隊(duì)列”。示例import tkinter as tk import queue import threading def worker(q): # 模擬耗時計算 result 0 for i in range(1000000): result i q.put(result) q queue.Queue() threading.Thread(targetworker, args(q,), daemonTrue).start() def poll_queue(): try: result q.get_nowait() label.config(textf計算完成{result}) except queue.Empty: pass root.after(100, poll_queue) root.after(100, poll_queue)這里的關(guān)鍵是root.after(100, poll_queue)每100毫秒檢查一次隊(duì)列拿到結(jié)果就在主線程更新界面。這是我最常用的模式穩(wěn)定、容易理解。3. 布局管理詳解pack、grid、place怎么選混合布局怎么搭3.1 三種布局的思維模型Tkinter提供三種布局管理器很多人一開始分不清其實(shí)可以用一個比喻把它們當(dāng)成三種不同的“擺放策略”。布局管理器思維方式適合場景核心參數(shù)pack往容器里按順序堆疊從上往下、從左往右的簡單排列side, fill, expand, padx, padygrid切成行列網(wǎng)格再填格子表單、行列對齊的復(fù)雜布局row, column, rowspan, columnspan, stickyplace直接畫坐標(biāo)絕對定位、覆蓋層x, y, relx, rely如果你不確定選哪個我的建議是默認(rèn)用grid它是三種里最容易控制對齊的。pack適合做頂欄、底欄、狀態(tài)欄這類線性排列place除非做特殊覆蓋層否則盡量少用因?yàn)榇翱诖笮∫蛔兓^對坐標(biāo)很容易錯位。3.2 表格型布局用grid一個登錄表單實(shí)例制作表單是GUI工具里最頻繁的場景。用grid布局一個登錄表單import tkinter as tk root tk.Tk() root.title(登錄) root.geometry(300x160) tk.Label(root, text用戶名).grid(row0, column0, padx10, pady10, stickytk.W) tk.Entry(root).grid(row0, column1, padx10, pady10) tk.Label(root, text密碼).grid(row1, column0, padx10, pady10, stickytk.W) tk.Entry(root, show*).grid(row1, column1, padx10, pady10) tk.Button(root, text登錄).grid(row2, column0, columnspan2, pady10) root.mainloop()這里有兩個關(guān)鍵參數(shù)stickytk.W讓控件靠左對齊默認(rèn)是居中表單標(biāo)簽不加sticky會歪得很難看。columnspan2讓按鈕跨兩列實(shí)現(xiàn)居中效果。還有一個經(jīng)常被忽略的點(diǎn)grid_columnconfigure它決定了窗口拉伸時列會不會跟著變寬。如果希望“密碼輸入框”那一列隨窗口變寬root.grid_columnconfigure(1, weight1)weight的意思是“權(quán)重”值越大拉伸窗口時這一列分到的額外空間越多。這一步不做輸入框會一直保持固定寬度看起來很死板。3.3 嵌套Frame解決pack和grid混用問題很多人學(xué)到后面會發(fā)現(xiàn)一個容器里同時用pack和grid會直接報錯tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack因?yàn)橥粋€父容器只能用一種布局管理器。想同時用兩種就需要嵌套Frame。Frame可以理解成一個“虛擬容器”把一個區(qū)域再切一次。比如我經(jīng)常需要這種結(jié)構(gòu)頂部是操作按鈕區(qū)用pack橫向排列中間是表單區(qū)用grid對齊。做法是先拆Frametop_frame tk.Frame(root) top_frame.pack(sidetk.TOP, filltk.X) form_frame tk.Frame(root) form_frame.pack(filltk.BOTH, expandTrue) # top_frame內(nèi)用pack橫向排列按鈕 tk.Button(top_frame, text新建).pack(sidetk.LEFT, padx5, pady5) tk.Button(top_frame, text刪除).pack(sidetk.LEFT, padx5, pady5) # form_frame內(nèi)用grid排表單 tk.Label(form_frame, text名稱:).grid(row0, column0, stickytk.W) tk.Entry(form_frame).grid(row0, column1, stickytk.EW) form_frame.grid_columnconfigure(1, weight1)這個“一個容器只用一種布局想要混合就加Frame”的規(guī)則能解決大量界面錯亂的坑。3.4 布局調(diào)試技巧讓背景色幫你看見邊界如果你發(fā)現(xiàn)某個控件“跑到莫名其妙的角落”最直接的排查方式是給Frame或Label臨時加背景色。frame tk.Frame(root, bgred) frame.pack(filltk.BOTH, expandTrue)這樣能立刻看到Frame占了多大空間、子控件被放在哪里。定位完問題再刪掉bg參數(shù)。這個方法成本極低效率極高我每次布局異常都會先放大招。3.5 pack的填充邏輯fill和expand怎么配合很多人用pack時分不清fill和expand導(dǎo)致控件沒有鋪滿窗口。這里給一個結(jié)論filltk.X橫向填滿父容器。filltk.BOTH寬高都盡量填滿。expandTrue允許控件占據(jù)父容器分配的多余空間但這個多余空間要配合fill才會真正被用上。常見正確寫法是content tk.Frame(root) content.pack(filltk.BOTH, expandTrue)這表示“這個區(qū)域占滿窗口并且窗口變大時它也變大”。少了expandTrue窗口拉伸時內(nèi)容區(qū)不會跟著擴(kuò)大。4. 常用控件與Variable聯(lián)動從靜態(tài)界面到交互狀態(tài)4.1 控件速查表核心參數(shù)與適用場景Tkinter的控件體系不大但足夠覆蓋工具型界面的需求。我整理了最常用的一張表控件核心參數(shù)用途tk.Labeltext, font, bg, fg, anchor靜態(tài)文本、說明文字tk.Buttontext, command觸發(fā)操作tk.Entrytextvariable, show, state單行輸入show*做密碼框tk.Text無直接文本參數(shù)用insert/get多行文本、日志輸出tk.Listboxlistvariable, selectmode列表選擇、預(yù)覽ttk.Comboboxvalues, textvariable, state下拉選擇可手動輸入tk.Checkbuttontext, variable, onvalue, offvalue開關(guān)、多選tk.Radiobuttontext, variable, value互斥單選tk.Scalefrom_, to, orient, variable滑塊調(diào)節(jié)數(shù)值tk.Spinboxfrom_, to, textvariable數(shù)值微調(diào)ttk.Progressbarmaximum, value, mode進(jìn)度條tk.Canvaswidth, height繪圖、自定義圖形的載體tk.Menuadd_command, add_separator菜單欄、右鍵菜單ttk.Separatororient分隔線4.2 變量對象StringVar綁定控件的“狀態(tài)通道”Tkinter的控件默認(rèn)是靠text參數(shù)顯示內(nèi)容的但如果要動態(tài)讀取、修改最好用StringVar、IntVar、DoubleVar、BooleanVar這些變量對象。name_var tk.StringVar() entry tk.Entry(root, textvariablename_var) name_var.set(默認(rèn)值) print(name_var.get())它們的價值在于一個變量對象可以同時綁定多個控件一處變化處處更新。比如做一個實(shí)時顯示“當(dāng)前輸入了多少字符”的提示text_len_var tk.StringVar() label tk.Label(root, textvariabletext_len_var) def update_len(*args): text_len_var.set(f已輸入 {len(name_var.get())} 字符) name_var.trace_add(write, update_len)trace_add(write, callback)會在變量每次變化時觸發(fā)回調(diào)這是在Tkinter里實(shí)現(xiàn)“輸入即反饋”的常用手段。4.3 Combobox、Checkbutton、Radiobutton交互狀態(tài)管理下拉框的選中事件比較特殊它用ComboboxSelected來綁定combo ttk.Combobox(root, values[選項(xiàng)A, 選項(xiàng)B, 選項(xiàng)C]) combo.bind(ComboboxSelected, lambda e: print(combo.get()))注意這里不能用command參數(shù)Combobox沒有command。多選開關(guān)和單選按鈕要配合變量使用is_keep_ext tk.BooleanVar(valueTrue) ck tk.Checkbutton(root, text保留原擴(kuò)展名, variableis_keep_ext, onvalueTrue, offvalueFalse) mode_var tk.StringVar(valuereplace) tk.Radiobutton(root, text替換模式, variablemode_var, valuereplace).pack() tk.Radiobutton(root, text追加模式, variablemode_var, valueappend).pack()讀取狀態(tài)就是is_keep_ext.get()和mode_var.get()非常簡單直接。4.4 菜單欄與右鍵菜單很多教程漏掉的交互菜單欄寫法menubar tk.Menu(root) file_menu tk.Menu(menubar, tearoff0) file_menu.add_command(label打開, commandopen_file) file_menu.add_command(label保存, commandsave_file) file_menu.add_separator() file_menu.add_command(label退出, commandroot.quit) menubar.add_cascade(label文件, menufile_menu) root.config(menumenubar)右鍵菜單和菜單欄類似但要用tk_popup彈出context_menu tk.Menu(root, tearoff0) context_menu.add_command(label復(fù)制, commandlambda: print(復(fù)制)) context_menu.add_command(label剪切, commandlambda: print(剪切)) def show_context_menu(event): context_menu.tk_popup(event.x_root, event.y_root) widget.bind(Button-3, show_context_menu)tk_popup接收的參數(shù)是屏幕坐標(biāo)所以要用event.x_root, event.y_root而不是event.x, event.y這是新手最容易踩的細(xì)節(jié)。4.5 內(nèi)置對話框messagebox、filedialog與colorchooser做工具類界面文件選擇、確認(rèn)彈窗幾乎是剛需Tkinter自帶這些能力不用額外下載庫from tkinter import filedialog, messagebox, colorchooser folder filedialog.askdirectory(title選擇文件夾) filepath filedialog.askopenfilename(title選擇文件, filetypes[(文本文件, *.txt), (所有文件, *.*)]) ok messagebox.askyesno(確認(rèn), 確定要刪除這個文件嗎) if ok: pass rgb, hex_color colorchooser.askcolor(title選擇顏色, initialcolor#ff0000)保存文件的對話框常用save_path filedialog.asksaveasfilename(defaultextension.json, filetypes[(JSON文件, *.json)])filedialog.askdirectory和askopenfilename返回的是路徑字符串拿到后可以直接做業(yè)務(wù)處理。dialog彈窗雖然是“阻塞”的但不會凍結(jié)整個程序因?yàn)門kinter的對話框內(nèi)部有自己的事件循環(huán)這和使用root.mainloop()不沖突。5. 事件綁定深入command、bind、lambda陷阱與after定時5.1 command參數(shù)和bind方法的本質(zhì)區(qū)別Tkinter里有兩個常用的事件綁定入口很多人會搞混command按鈕、菜單等少數(shù)控件特有的回調(diào)參數(shù)綁定的是“設(shè)計好的命令”回調(diào)函數(shù)不接收事件對象。bind通用事件綁定可以綁定任意控件、任意事件回調(diào)函數(shù)會接收一個事件對象。一個常見問題是兩者同時使用時按鈕點(diǎn)一下會觸發(fā)兩次def on_click(eventNone): print(clicked) btn tk.Button(root, text點(diǎn)我, commandon_click) btn.bind(Button-1, on_click)所以我的建議是用command就只用command用bind就只用bind不要混著寫。除非你確實(shí)需要同時捕獲不同的鼠標(biāo)狀態(tài)比如點(diǎn)擊和松開。5.2 lambda陷阱為什么所有按鈕都得到同一個值Tkinter教程里到處都能看到lambda但lambda有一個著名的坑??纯催@個例子btns [] for i in range(3): btn tk.Button(root, textstr(i), commandlambda: print(i)) btn.pack() btns.append(btn)運(yùn)行后不管點(diǎn)哪個按鈕輸出的都是2。原因是lambda捕獲的是變量引用不是創(chuàng)建時的值。循環(huán)結(jié)束后i變成了2所有l(wèi)ambda讀取到的都是2。正確寫法是把值綁定為默認(rèn)參數(shù)commandlambda ii: print(i)或者用functools.partialfrom functools import partial commandpartial(print, i)這個坑我見過無數(shù)次凡是“在循環(huán)里創(chuàng)建按鈕”的場景幾乎必踩。5.3 事件對象的常用屬性bind回調(diào)傳遞的事件對象里經(jīng)常用到的屬性有事件屬性含義event.widget觸發(fā)事件的控件對象event.x, event.y鼠標(biāo)相對控件左上角的坐標(biāo)event.x_root, event.y_root鼠標(biāo)相對屏幕的坐標(biāo)event.keysym按鍵名稱如Return、aevent.char按鍵對應(yīng)的字符event.delta鼠標(biāo)滾輪滾動量比如做一個回車鍵觸發(fā)登錄entry.bind(Return, lambda e: login())又比如捕獲雙擊列表項(xiàng)并打開listbox.bind(Double-1, lambda e: open_item())Double-1表示雙擊左鍵這是GUI工具里非常高頻的操作但很多文檔里沒寫清楚。5.4 用after做定時任務(wù)別用time.sleep很多需求是“每間隔一段時間刷新一次界面”比如監(jiān)控日志、顯示當(dāng)前時間。錯誤寫法是在主循環(huán)里加time.sleep(1)結(jié)果是窗口卡死。正確寫法是用afterdef update_clock(): label.config(texttime.strftime(%H:%M:%S)) root.after(1000, update_clock) root.after(1000, update_clock)after的本質(zhì)是“把函數(shù)加入事件循環(huán)在指定毫秒后執(zhí)行”它不是開新線程也不會阻塞界面。有些需要取消的定時任務(wù)可以拿到after的返回值并調(diào)用after_canceltask_id root.after(1000, func) root.after_cancel(task_id)結(jié)合前面的隊(duì)列方案after是Tkinter多線程場景里最重要的“回到主線程”的工具。6. 實(shí)戰(zhàn)一個帶配置保存的批量文件重命名小工具6.1 需求拆解與界面結(jié)構(gòu)理論知識講完來一個能直接抄作業(yè)的完整案例。我這邊的場景是某個目錄下有幾百個文件需要按規(guī)則重命名規(guī)則包括前綴、后綴、起始序號而且要保留擴(kuò)展名還要把配置保存下來這樣下次打開不用重新設(shè)。界面結(jié)構(gòu)其實(shí)很簡單第一行文件夾路徑輸入框 “瀏覽”按鈕第二行文件名前綴輸入框第三行文件名后綴輸入框第四行起始序號、序號步長、“保留原擴(kuò)展名”復(fù)選框第五行操作按鈕區(qū)預(yù)覽、執(zhí)行、保存配置、加載配置中間列表預(yù)覽區(qū)Listbox 滾動條底部狀態(tài)欄Label6.2 核心邏輯實(shí)現(xiàn)與界面聯(lián)動先看核心代碼框架我會把關(guān)鍵點(diǎn)都標(biāo)注出來。import tkinter as tk from tkinter import ttk, filedialog, messagebox from pathlib import Path import json class RenameTool: def __init__(self, root): self.root root self.dir_var tk.StringVar() self.prefix_var tk.StringVar() self.suffix_var tk.StringVar() self.start_var tk.StringVar(value1) self.step_var tk.StringVar(value1) self.keep_ext_var tk.BooleanVar(valueTrue) self.files [] self.pending [] # 預(yù)覽計算結(jié)果 [(舊Path, 新名稱字符串), ...] self.build_ui() def build_ui(self): self.root.title(批量重命名工具) self.root.geometry(560x520) # 第一行目錄選擇 row1 tk.Frame(self.root) row1.pack(filltk.X, padx10, pady5) tk.Entry(row1, textvariableself.dir_var).pack(sidetk.LEFT, filltk.X, expandTrue) tk.Button(row1, text瀏覽, commandself.browse_folder).pack(sidetk.LEFT, padx(5, 0)) # 表單區(qū) form tk.Frame(self.root) form.pack(filltk.X, padx10, pady5) tk.Label(form, text前綴).grid(row0, column0, stickytk.W) tk.Entry(form, textvariableself.prefix_var).grid(row0, column1, stickytk.EW, padx5) tk.Label(form, text后綴).grid(row1, column0, stickytk.W) tk.Entry(form, textvariableself.suffix_var).grid(row1, column1, stickytk.EW, padx5) tk.Label(form, text起始序號).grid(row2, column0, stickytk.W) tk.Entry(form, textvariableself.start_var).grid(row2, column1, stickytk.W, padx5) tk.Label(form, text步長).grid(row3, column0, stickytk.W) tk.Entry(form, textvariableself.step_var).grid(row3, column1, stickytk.W, padx5) tk.Checkbutton(form, text保留原擴(kuò)展名, variableself.keep_ext_var).grid(row4, column0, columnspan2, stickytk.W) form.grid_columnconfigure(1, weight1) # 按鈕區(qū) btns tk.Frame(self.root) btns.pack(filltk.X, padx10, pady5) tk.Button(btns, text預(yù)覽, commandself.preview).pack(sidetk.LEFT, padx5) tk.Button(btns, text執(zhí)行, commandself.apply_rename).pack(sidetk.LEFT, padx5) tk.Button(btns, text保存配置, commandself.save_config).pack(sidetk.LEFT, padx5) tk.Button(btns, text加載配置, commandself.load_config).pack(sidetk.LEFT, padx5) # 預(yù)覽列表 list_frame tk.Frame(self.root) list_frame.pack(filltk.BOTH, expandTrue, padx10, pady5) scrollbar tk.Scrollbar(list_frame) scrollbar.pack(sidetk.RIGHT, filltk.Y) self.listbox tk.Listbox(list_frame) self.listbox.pack(sidetk.LEFT, filltk.BOTH, expandTrue) self.listbox.config(yscrollcommandscrollbar.set) scrollbar.config(commandself.listbox.yview) self.status_var tk.StringVar(value就緒) tk.Label(self.root, textvariableself.status_var, anchortk.W).pack(filltk.X, padx10, pady5)這段代碼里布局用的是“外層pack 表單區(qū)內(nèi)部grid”的組合也就是前面說的嵌套Frame技巧。Listbox配Scrollbar是標(biāo)準(zhǔn)寫法滾動條和列表通過兩個方向的命令互相配合。核心處理邏輯def browse_folder(self): folder filedialog.askdirectory() if folder: self.dir_var.set(folder) self.refresh_files() def refresh_files(self): folder self.dir_var.get().strip() if not folder: return path Path(folder) self.files [f for f in path.iterdir() if f.is_file()] self.status_var.set(f發(fā)現(xiàn) {len(self.files)} 個文件) self.listbox.delete(0, tk.END) for f in self.files: self.listbox.insert(tk.END, f.name) def build_new_name(self, f, idx, start, step): ext f.suffix if self.keep_ext_var.get() else base f.stem prefix self.prefix_var.get().strip() suffix self.suffix_var.get().strip() serial start idx * step new_base f{prefix}{base}{suffix} return f{serial:03d}_{new_base}{ext} def preview(self): if not self.files: messagebox.showwarning(提示, 請先選擇目錄) return try: start int(self.start_var.get()) step int(self.step_var.get()) except ValueError: messagebox.showerror(錯誤, 序號和步長必須是整數(shù)) return self.pending [] self.listbox.delete(0, tk.END) for idx, f in enumerate(self.files): new_name self.build_new_name(f, idx, start, step) self.pending.append((f, new_name)) self.listbox.insert(tk.END, f{f.name} - {new_name}) self.status_var.set(f預(yù)覽完成共 {len(self.pending)} 項(xiàng))f.stem是文件名去掉擴(kuò)展名的部分f.suffix是擴(kuò)展名這兩個pathlib屬性是重命名邏輯的關(guān)鍵。序號前面用:03d格式化能保證排序正確不然1和10會排在一起。執(zhí)行重命名時有幾個前置檢查必須做否則可能會出現(xiàn)數(shù)據(jù)錯亂def apply_rename(self): if not self.pending: messagebox.showwarning(提示, 請先點(diǎn)擊預(yù)覽) return if not messagebox.askyesno(確認(rèn), 確定執(zhí)行重命名嗎該操作不可撤銷。): return # 檢查新舊名是否沖突 new_names [f.with_name(new_name) for f, new_name in self.pending] if len(set(p.name for p in new_names)) ! len(new_names): messagebox.showerror(錯誤, 存在重名文件請調(diào)整規(guī)則) return for f, new_name in self.pending: target f.with_name(new_name) if not target.exists(): f.rename(target) else: messagebox.showerror(錯誤, f目標(biāo)文件已存在: {target.name}) return self.refresh_files() self.pending [] messagebox.showinfo(完成, 重命名完成)6.3 配置文件讀寫與界面回填這個小工具配置保存的價值在于下次打開不用重新填一堆規(guī)則。用json就夠輕量def save_config(self): data { dir: self.dir_var.get(), prefix: self.prefix_var.get(), suffix: self.suffix_var.get(), start: self.start_var.get(), step: self.step_var.get(), keep_ext: self.keep_ext_var.get(), } try: with open(renamer_config.json, w, encodingutf-8) as fp: json.dump(data, fp, ensure_asciiFalse, indent2) messagebox.showinfo(成功, 配置已保存) except Exception as e: messagebox.showerror(失敗, f保存失敗: {e}) def load_config(self): config_file renamer_config.json if not Path(config_file).exists(): messagebox.showinfo(提示, 沒有找到配置文件將使用默認(rèn)值) return with open(config_file, r, encodingutf-8) as fp: data json.load(fp) self.dir_var.set(data.get(dir, )) self.prefix_var.set(data.get(prefix, )) self.suffix_var.set(data.get(suffix, )) self.start_var.set(data.get(start, 1)) self.step_var.set(data.get(step, 1)) self.keep_ext_var.set(data.get(keep_ext, True)) self.refresh_files() self.status_var.set(配置已加載)ensure_asciiFalse保證中文配置打開后正常顯示indent2只是為了方便人工查看。讀取數(shù)據(jù)時用data.get()而不是data[]避免舊版本配置文件缺字段時報錯。啟動時自動加載配置只需要在__init__里調(diào)用load_config但是要兼容“第一次啟動沒有配置”的情況所以load_config里做了文件存在性判斷。到這里這個小工具的完整鏈路就通了選目錄、填規(guī)則、預(yù)覽、執(zhí)行、保存配置、下次自動加載。7. 實(shí)測中踩過的坑與修復(fù)從布局錯亂到打包異常7.1 pack和grid混用導(dǎo)致的崩潰現(xiàn)場我在初學(xué)階段遇到過最經(jīng)典的報錯tkinter.TclError: cannot use geometry manager grid inside . which already has slaves managed by pack原因已經(jīng)在前文講過同一父容器只能用一種布局管理器。但很多人的實(shí)際錯誤是——往同一個頂層窗口里上一行代碼用了pack下一行又用了grid。解決思路只有一種按區(qū)域拆Frame每個Frame內(nèi)部只用一種布局管理器。在寫代碼之前先畫一個簡單的區(qū)域草圖把哪些區(qū)域放哪一層想清楚比寫錯了再調(diào)要高效得多。7.2 關(guān)閉窗口后進(jìn)程不退出后臺線程還掛在那里如果你的程序里有子線程直接點(diǎn)右上角關(guān)閉窗口可能會發(fā)現(xiàn)進(jìn)程還在后臺運(yùn)行或者關(guān)閉后一段時間又報錯。原因是子線程默認(rèn)是非守護(hù)線程它不結(jié)束Python進(jìn)程就不會退出。標(biāo)準(zhǔn)解法是兩步子線程創(chuàng)建時加上daemonTrue。用protocol(WM_DELETE_WINDOW)接管關(guān)閉事件做清理后再銷毀窗口。def on_close(): self.running False self.root.destroy() self.root.protocol(WM_DELETE_WINDOW, on_close)如果有定時任務(wù)可以在清理時用一個標(biāo)志位通知循環(huán)退出把事件循環(huán)收干凈再進(jìn)行銷毀。7.3 PyInstaller打包后資源路徑找不到圖標(biāo)不顯示打包exe之后最常遇到“圖標(biāo)不顯示”“配置文件找不到”的問題。原因是在PyInstaller打包環(huán)境里__file__指向的臨時目錄和實(shí)際腳本目錄不同。正確做法是動態(tài)判斷運(yùn)行環(huán)境import sys from pathlib import Path def get_base_dir(): if getattr(sys, frozen, False): return Path(sys._MEIPASS) # PyInstaller解包臨時目錄 return Path(__file__).parent然后把圖標(biāo)、字體等資源路徑都基于get_base_dir()拼接比如icon_path get_base_dir() / icon.ico打包命令常用的是pyinstaller -F -w -i icon.ico rename_tool.py其中-F打成單文件-w隱藏控制臺窗口-i指定圖標(biāo)。注意-w模式下print的輸出不可見調(diào)試時要分開處理。7.4 Windows高DPI下界面發(fā)虛的修正在Windows上Tkinter程序經(jīng)常遇到字體發(fā)虛、控件錯位的問題。這是因?yàn)檫M(jìn)程沒有聲明DPI感知Windows用位圖拉伸縮放。修復(fù)方法是在創(chuàng)建窗口前設(shè)置DPI感知但要注意放在import tkinter之后、創(chuàng)建Tk()之前import ctypes try: ctypes.windll.shcore.SetProcessDpiAwareness(1) except Exception: pass root tk.Tk()加上之后字體清晰度會有明顯改善。這個寫法在macOS和Linux上會因?yàn)閏types.windll不存在而進(jìn)入except所以不需要額外區(qū)分平臺。7.5 ttk控件和tk控件的狀態(tài)常量不一致我在混合用ttk.Button和tk.Button時發(fā)現(xiàn)件狀態(tài)切換的寫法不同# tk.Button btn[state] tk.DISABLED # ttk.Button btn[state] disabled # 恢復(fù) btn[state] normal雖然結(jié)果都是禁用但常量來源不同寫混了會報錯或者不生效。更麻煩的是ttk組件很多屬性不再支持bg、fg這樣的傳統(tǒng)寫法改走Style配置。如果你要深入定制最好統(tǒng)一用ttk并且對Style單獨(dú)學(xué)習(xí)style ttk.Style() style.configure(TButton, padding6, font(微軟雅黑, 9)) style.map(TButton, foreground[(pressed, red), (active, blue)], background[(pressed, !disabled, black)])7.6 打包后配置文件的位置別默認(rèn)放在臨時目錄有一個細(xì)節(jié)很多人在打包后才遇到配置文件明明生成了重啟程序卻讀不到。原因在于-F單文件模式下Path(renamer_config.json)默認(rèn)寫在了系統(tǒng)臨時解包目錄里程序退出后臨時目錄被清空配置就丟了。解決辦法是把配置路徑指向exe同級的目錄def get_app_dir(): if getattr(sys, frozen, False): return Path(sys.executable).resolve().parent return Path(__file__).parent寫配置時用get_app_dir() / renamer_config.json讀取時也用它。這樣配置就穩(wěn)穩(wěn)地待在exe旁邊用戶看得見、刪得掉、有需要還能手動編輯。結(jié)尾最后分享一個小習(xí)慣最后說一個我做了很多GUI工具后養(yǎng)成的習(xí)慣任何會耗時超過一秒的操作先禁用相關(guān)按鈕、把狀態(tài)欄切到“處理中”任務(wù)結(jié)束后再恢復(fù)。Tkinter的響應(yīng)機(jī)制決定了不能直接用多線程改界面但這個小小的狀態(tài)反饋能避免掉大半“程序是不是死了”的疑問尤其當(dāng)處理幾百個文件時這個習(xí)慣比優(yōu)化代碼本身更管用。配置保存這招是通用性很高的——不管你是做批量重命名、數(shù)據(jù)處理、參數(shù)配置凡是“用戶設(shè)置了一堆東西”的界面都值得加一個json.dump和json.load。這個成本很低帶來的體驗(yàn)提升卻非常明顯下次打開工具不用重新填一遍參數(shù)那種“被工具尊重”的感覺用戶嘴上不一定會說但心里一定記得。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
欧美人妻精品一区二区| 久操电影| 麻豆a'v电影| 日曰骚久久精品| 一区二区中文| 中亚精品极乱| 九九九九精| 黄片色区软件| AV丝袜少妇| 91美| 一本一道vs波多野结衣| 一区二区三区色综合| 日韩欧美麻豆 | 人妻内射一区二区在线视频| 精品国产嫩穴视频| 天堂男人网| 欧美日韩性爱电影在线| 麻豆激情综合| 日本操逼aaaaa| 91美女在线观看| 欧美成人AⅤ大片在线观看| 亚洲日韩AV视色| 精品无码一区二区三区| 欧美激情激情xxxx欧美专区| 色婷婷狠狠| 日日干夜夜欢| 日韩精品 视频一区二区| 清纯唯美亚洲综合| 蜜臀久久在线视频| 男男H黄动漫啪啪无遮挡网站| 91超碰丝袜制服| 污污汅18禁网站在线永久免费观看 | 婷婷在线精品| 激情黄色片在线观看| 亚洲第二页| 亚洲天堂色图| 翔田千里AV无码秘 三区| 亚洲九九视频在线观看| 午夜αv| 91大学精品激情戏| 无码人妻精品一区二区中文| 超碰色老头| 欧美久久毛片基地| AV不卡在线| 超碰欧美COM| 98超碰日本| 久久精品国产精品亚洲艾通辽熟妇| 熟女人妇一区二区三区| 人人摸人人叼| 亚洲色交| 91中出在线| 婷婷精品国产欧美精品亚洲人人爽| 免费超碰97久久| 亚洲色图在线视频| 国产中文字幕在线点播| 久久精品 六十路 熟女 欧美| 欧美日韩狠狠爱| 人妻天天夜夜爽一区二区| 亚洲 日本 国产 综合| 啊啊啊好大好深| 女人香蕉久久毛毛片精品| 精品射1999| 肏逼视频日本| 免费a v| 五月天久久综合网| 人人爱人人操人人性| AV污污污污| 噜噜在线| 国产亚洲精品玖玖玖在线观看| 伊人影院日本| 日本精品一级二级三级| 国产肏逼网站| 东京热一区二区中文字幕| 职场同事知名国产国产精品久久欧美日韩| 大香蕉手机在线| 美女诱惑一区| 国产日韩区| 国产精品女aA片爽爽视频| 密臀在线一区尤物| 亚洲 欧美 日韩 国产一区二区| 四虎国产精品永久在线囯在线| 99热啪啪| 国产精品久久久吖| 久精品无码av一区二免费国产在线观看| 影音先锋日本一区二区| 久9无限国产| 亚欧美色图| 青草园大香蕉| {男男暴菊gay无套网站| 嗯嗯啊啊好爽| 干婷婷综合网| 人妻AV在线| 人人考人人摸人人干| 粉嫩av在线一区二区| 熟女精品日韩一区二区三区| 色www精品视频在线观看| 中文字幕第页| julia中文字幕在线观看| 午夜后入| 欧美96在线|欧| 欧美亚洲涩涩| 高潮精品| 欧美成人A天堂片在线观看| 精品国产精品一区二区| 国产黄片在线免费观看| 国产精品一区二区三区,亚洲综合 性开放中文AV高清无码免费看 | 久久 国产 无码| 爽 好舒服 无码刺激久久| 国语国产操逼伊人AV网| 51一区二区三区| 少妇一线天久久久久久| 老师充足的奶水小说| 激情五月综合| 欧美97av| 成全动漫视频观看免费下载| 久久男女激情视频网站| 东北女人的毛片| 日本三级大片| 熟妇人妻精品一区二区| 色青青久久影视| 日本男人插女人的逼黄色| 99.色网| 精品一级| 欧美国产欧美在线观看| 久久侵犯人妻爽爽爽| 亚洲精品九九九九九九| www.yw尤物| 干b在线性社区| 国产午夜福利合集| 国产精品一区二区三区四区五区| 思思热在线视频精品| 99久久com免费视频′| 国产伦精品| 日韩乱伦AⅤ| 女人爽到高潮潮喷18禁网站| 97视频一区| 国产亚州高清国产拍精| 第二页中文字幕| 综合大香蕉美。| 91欧美亚洲| 91女在线观看| 黄呦呦在线| www.亚洲黄色| 日本天天人人狠狠在线日美女| 美女露胸露奶头| 国产AB视频| 亚洲影院成人| 91高跟美女在线播放| 午夜国产综合视频在线观看| 色男人色天堂东京热| 久草午夜| 尻女朋友一夜| 激情五月丁香五月| 日韩A优精品在线观看| 午夜性| 97视频观看| 天天看天天日天天操| 免费毛片在线播放| 青青操日韩| 少妇一区二区三区高速| 992大香蕉| 亚洲 国产 精品一区| 爱干爱射网啊啊啊| 日本视频一区二区三区| 精品性爱久久视频| 激情小说日韩无码| 天天色综合图片| 国产精品人人爽人人做可爱福利| 色色色欧美| 久久夜嗨| 天天躁日日躁AAAXX| 夜夜嗨免费视频| 久久精品国产亚洲AV无码做| 99少妇内射| 青青久操| 老熟妇综合| 五月天婷婷久久| 伊人黄色片| 欧美情色贴图| 国产成人无码高清| 密臀成人视频久久久| 天天摸,夜夜摸| 亚洲导航深夜福利| 在线中文字幕视频| 手机av天堂久久久久| 日婷婷| 亚洲狠| 一本一道人妻久久一区二区三区| 欧美性爱视频免费一区一A| 免费精品国偷自产在线在线| 神马麻豆福利院| 精品国产综合久久福利,热99这里有精品综合久久,99热这里只有免费国产精品,精 | 婷婷六月天| 人妻欧美| 日日夜夜青青草母狗| 亚洲天堂 视频你懂的| 蜜臀99久久精品| 狠狠热这里都是精品| 日本99视频| 国产400孕妇孕交群| 亚洲中文字幕一区| 一区黄二区黄| 欧美制服另类丝袜| 日韩午夜国产| 亚州欧美总和| 婷婷色网| 韩国久久97| 五月天激情小说| 内射老妇BBWX0C0CK| 91精品老女人| 日本熟女免费視颖| 色婷婷视频| 思思热久久成人| 26uuu国产亚洲综合| 一区二区三区免费视频入口| 国产欧洲精品亚洲午夜拍精品| 女人爽到高潮潮喷18禁网站 | 欧美青青视频| 91国产丝袜足交精品视频| 国产中文大片资源中文字幕| 一本一道vs波多野结衣| 在线日韩精品一区二区三区| 亚洲人精品午夜不卡| 五月天激情小说网| 久久社区一区二区三区| 強姦亂倫a| 性色av大全| 日韩精品一区二区高清 | 超碰人妻久久人妻中文97| 屌妞视频久久久久久久久久久久| 午夜精品久久久久久久男人的天堂 | 中国一级αV| asc国产精品| 国产熟女无套内射| 激情熟女12P| 夜夜无码| 午夜精品久久久久久久99| 色av中文字| 夜夜夜夜夜夜夜夜夜狠狠狠狠狠狠狠| 热久久九九热| 亚洲性综合11| 96精品久久久| 好爽视频在线观看视频| 欧美性爱第一页久久| 中文字幕aⅴ在线视频| 抽插无码高清一区| 青青草伊人久久| 亚洲有码第一页| 夜夜春夜夜操| 亚洲欧洲日韩天堂av| 久久专区| 十八禁成人网站在线观看| 国产亚洲深夜激情| 亚洲综合91| 91欧美网| 太久视频| 超碰在线人妻不卡| 久久久久久久久久久久97| 人妻天天爽天天爽三区| 精品无码久久久久久久久果冻糖心 | 伊人久久亚洲中文字幕| 日韩精品中文字幕一| 偷拍亚洲熟女视频播放| 国产无马av| 久久深夜无码| 午夜毛片高清免费不卡| 日韩欧无码一区二区三区免费不卡| 揉揉揉夜夜| 高清有码一区二区| 在线无码操| 欧美超碰96| 看黑丝美女操逼青青网站| 久久有码视频| 久久性爱城| 夜夜操狠狠操| 丝袜AV一二三区| 色在线69堂| 性感美女啊啊啊在线| 99最新日韩偷拍视频| 另类图片欧美激情综合| 婷婷久草一区二区三区| 999久久芭蕾| 亚洲图片日本AⅤ欧美在线| 精品日韩中文在线| 熟女六十路| 蜜屁Av| 96精品一区| 亚洲高清无毛一区二区| 欧美老妇综合网| 久久婷婷欧美| 人妻精品一区二区三区| 一中国女人毛片水真多| 麻豆视频test| 国产人妻精品一区二区三区秋霞 | 爱av免费| 欧美日韩中国x| 在线免费观看日韩一区| 免费久久9999| 人妻少妇久久中文字幕一区二区 麻豆| 天天干人人看综合| 国产白嫩精品久久| 亚洲AV无码翔田千里网站| 久草色悠悠在线视频| 热久久无毒不卡| 亚洲熟妇A V黑人| 超碰91在线| 中文字幕十五区| 亚川综合视频| 夜夜做夜夜爽精品视频| 91九色在线| 求求你操操我| 手机在线视频国内精品| 天天欧美97| 亚洲超碰AV| 大香蕉 222| 99re99视频在线免费观看| 国产精品久久久啊| 天综合网欧美| 极品极品色影院| 国内外内射高清视频| 丝袜美腿制服人妻二区中文字幕| 爱爱动态120秒| 在线二区不卡| 免费视频a级毛片免费视频| 欧美亚洲清纯| 日韩乱码av| 精品无码产区一区二| 精品一级毛片在线观看| 91粉芽高清在线一区二区| 国产白领连续中出在线播放| 九九性视频| 欧美96在线|欧| 久久久久久国产精品| 新亚洲无码| 9精品久久| 超碰日韩人妻| 午夜人妻精品综合在线| 久久亚洲日韩熟女精品| 超碰成人国产| 破处bbq| 五月天激情四射| 东北毛片| 精品十三区| 国产精品成人福利在线| 国产热av| 日韩成人大片在线观看| 欧美日韩制服| 国产妇女精品视频青青草| 国产精品视频91久久| 无码人妻一区二区一牛影视| 日韩一级特黄av毛片| 欧美成人性活片| 成人资源中文字幕在线观看天天| 丝袜亚洲综合| 中文字幕一区 二 区 三 四 五 区日 日 骚| 亚洲成人在线高清| 久久久久9| 国产精品探花在线| 国产精品一区二区三区四区五区| 亚洲中文字幕噜噜噜久久久| 国语对白在线播放视频| 狠狠色噜噜狠狠狠狠狠色综合久久| 亚洲视频一二区| 日韩乱插| 97色97干| 综合少妇网| 九一国产精品| 天天天天天天天天综合| 日韩中文字幕2020| 91色图片| 青青草黑寡妇男人天堂| 秋霞蝌科网日本一区| 久久久久久久综合,国产| 无码一区二区三区四区五区六区七区八区九区十区视频 | 99性视频| 欧美成熟性爱精品| 亚洲 中文 欧美 日韩 在线| 97天天摸天天碰| 天天视频黄| 操逼999| 中文字幕性感少妇av| 亚洲在线91| 日日干男人的天堂| 五月天久久婷婷亚洲 | 操b网站亚洲无码| 日本精品人妻少妇一区二区| 午夜久久一区二区无码中出| 一区二区三区精品黑丝白丝酒店对鸡| 99ri在线视频| 玖玖97综合| 色精品极品| 99国产精品人妻人伦| 亚洲人妻在线一区| 成人aⅴ一区二区三区| 色在线亚洲视频www| 亚洲欧美日韩免费电影| 亚洲毛片一级带毛片基地| www..com操老师| 清纯唯美亚洲综合| 亚洲中文字幕在线视频一区二区 | 97超碰碰碰| 日韩性爱再线视频| 亚洲无码超碰免费| 中文字幕奈奈美被公侵犯| 国产精品久久久无码AV网站| se吧提供国产乱老熟视频胖女人| 亚洲精品欧洲色| 九月伊人中文字幕| 成人97人人超碰人人| 麻豆天美在线| 亚洲综合另类色图| 97超碰9| 精品美女人人干| 宗合情欲网| 国产久久男人天堂| 欧美激情1区| 久草毛片| 亚洲AV秘无码一区..| 凹凸视频在线一区二区| 97综合国产| 成人97人人超碰人人| 亚洲制服欧美另类内射| 97色欧州| 欧美日韩亚洲少妇寂寞影院正在播放 | 97国产|免费| 午夜精品久久久久久久99| 久久精9| 破处bbq| 精品人妻一区二区三区日产乱码| 免费精品中文字幕| 乱伦AVxx| 大香蕉 222| julia ann久久| 91五十路| 强奸a片网| 大香蕉中文aV在线| 久久99精品国产| 日韩欧美水蜜桃人妻| 北京美女一区二区| 夜色91| 伦伦成年午夜免费视频| 大鸡吧尹人在线| 中文乱码99| 97超碰热线| 日日夜夜国产综合| 欧美综合传媒| 吖在线不卡一区二区国产剧情| 婷婷五月天激情四射| 香蕉在线一区二区三区| 超碰欧美97资源| 麻豆精品.欧美精品.日韩精品.| 九久精品| 污污汅18禁网站在线永久免费观看 | 99热精品在线观看| 偷拍亚洲高清图片| 99热日| 日本不卡在线二区三区| 国产第25页在线观看| 中日韩久久人妻一区二区| 日影院久久婷婷夜夜网| 免费国产电影一区二区| 青青11操操操操操操操操| 亚洲AV永久无码精品成人调教| 伊人黄色片| 亚洲城人男人的天堂| 91五月天| 强奸乱伦亚洲第一页| 亚洲精品欧洲精品| 老熟女阿 国产91| 88xx成人精品视频| 男男H黄动漫啪啪无遮挡网站| 婷婷五月在线视频| yazhououmeizongya| 成人五月天丁香激情综合| 美女午夜福利免费视频| 91精品久久久久久久久久| 亚洲丝袜诱惑| 情色日播放AV| 综合伊人激情| 精品无码一二三四区| 99999久久精| 婷婷九月| 怡红院网站在线视频| 日韩三级在线观看网站| 欧美综合色站| 天堂中文日本在线观看| 日日骚网站| 丰满人妻一区二区三区| 91天天| 中文字幕丝袜人妻| 日逼视频日本| 国产精品久久泡妞网站| 日韩伦理视频| 污污汅18禁网站在线永久免费观看| 亚洲有薄码区日本系列中文字幕| av一区二区三区不卡| 双插在线| 91性高朝久久久久久久久| 日本久久精品| 97精品一区二区视频| 操操AV电影| 97久久综合网| 一区二区三区国产精产| 亚洲精品国产精品成人| 久草老司机| 熟女五十路一区二区三| 天天躁日日躁狠狠狠躁| 亚州精品丝袜-不卡成人免费| 亚洲色图欧美色图日韩色图| 婷婷丁香一区二区三区| 免费福利视频中文字幕| 熟女少妇一区二区三区| 99999精品成人| 国产三级多多影院2022国产AA一级毛片无码| 极品出轨视频网站| 少妇69中文| 久久婷婷影院| 九九九九国产| 久久久精品久久| 女人 A一级| 亚洲少妇在线观看| 精品国产网站| 国产CHASE男男GAYGA 毛多色婷婷| 日韩精品三级片长长久久| 色优久久| 26uuu久久| 在线天堂999| 亚洲一区中文字幕一区| 人妻干天天| 日本大香蕉综合网| wwwcaobibi| 天天看夜夜看日日干| 久久婷婷伊人| 91精品国产91久久久久久久久久久久| 美国aaaaa一级黄片| 亚洲熟妇综合久久久久久| 殴美牲| 国产CHASE男男GAYGA 毛多色婷婷| 国产精品另类一区大香蕉| 九九Av| 网页导航五月天免费一二三区 | 婷婷六月色| 丁香九月婷婷| 国色综合天| 欧亚不卡| 久久老子无码午夜伦不卡| 中文字幕一区二区在线日韩精品| 校园春色 亚洲| 伊人亚洲综合| 欧美嗯啊……在线观看视频免费| 激情抓乳插进去啪啪啪日韩| 欧美操人视频| 秋霞一级鲁丝片A片| 欧美偷偷网| 人妻天天夜夜爽一区二区| 免费无码国产精品v片在线观看| 在线小说视频一区| 熟女久久久| 啊啊啊不要嗯嗯在线观看| 亚洲熟妇自偷自拍另欧美| 偷窥自拍亚洲天堂网爆| 嫖老熟女A片一二三区| 欧亚乱色熟女一区二区| 成人免费福利在线观看| 亚洲黄网在哪免费看| 激情接吻视频久久久久久| 欧美亚洲小说| 啊啊啊啊,啊啊好多水 | 妺妺跟我一起洗澡没忍住| 黄片aaaaa一区| 日韩激情啪啪| 大香蕉伊人久久| 亚洲人妻AV| 熟妇人妻精品一区二区视频色欲| 国产区91柔拿会所技师| 五月天玖玖资源站| 亚洲无码免费看| 午夜寂寞欧美| 日韩性爱啪啪视频| 国产精品白丝在线播放| 亚洲麻豆精品二区三区| 亚洲人精| 99综合视频一体| 97天天爽| 综合色图区| 九九激情网| 久妇网| 人妻人人澡人人爽人人| 亚洲脚交| 成人国产视频在线观看| 精品人妻一区二区三区日产| 韩日色费| 97超碰磁| 久久久精品电影| av影片在线观看不卡| 久草精品国产99| 亚洲不卡三级手机播放| 亚洲AV无码AV吞精久久久久| 天天做日日做| 大香蕉专区| 日韩人妻大香蕉| 久久久久久国产精品| 亚洲天堂自拍| 99www.bibizy香蕉资源国产一区二区三区高清| 少妇无码太爽| 日韩精品人妻中文字幕有码午| 综合av影片| 91精品91久久久久77777俄罗斯老妇姓x| 日韩中文字幕视频| 激情丁香五月婷婷| 亚洲日韩XXX| 3PAV乱伦视频| 久久久久9999| 人妻熟女午夜精品在线| 久久久久斤小| 少妇天堂| 免费精品国偷自产在线在线| 91大神精品长腿在线观看网站| 国产无码三级视频在线观看| 午夜视频好爽啊| 麻豆天美国美国产AV| 日本三级韩国三级美三级91| 97爱爱官网| 97 色综合| 强奸a片网| 无码免费一区二区三区啪啪| 天天热精品| 91精品网站| 黄网色一区二区三区四区精品| 五月天大香蕉| 欧美性五月| 97精品久久| 色五月婷婷网| 亚洲第二页| 牛牛AV人人夜夜澡人人爽| 99热在线观看| 99国产精品久久久久久久成人热| 欧美综合色综合| 色黄色美女大长腿午夜视频| 久久综合五月天| 青青操日韩| 97精品一区二区视频| 特污免视频| 91嫩草在线| 精品无码久久久久久久久果冻糖心| 国产欧美精选自拍一区| 五月天综合在线| 亚洲欧洲久久天堂| 另类欧美色| 红杏大香蕉| 91丨人妻丨国产丨丝袜| 美女露胸露屁股| 国产91丝袜在线播放蜜月| 男人高清无码一区二区| WWW4虎| 免费无码婬片AAAA片直播色戒| 欧美日韩性爱操大逼| 后入福利视频| 岛国精品视频在线观看| 大香蕉人妻久久| 无码精品久久久天天影视| 天天日日夜夜| 亚洲欧美内射| 亚洲av影音先锋| 精品国产乱码久久久久久日本公司| 青娱乐福利99| 99热这里只有是精品10| 一区AV| 日欧毛片久久| 怡红院一区二区熟女人妻| 欧美色997| 丰满人妻无码一区二区三区| 激情婷婷丁香网| 久久久久免费少妇| 先锋影音av先锋一区| 天天射,天天操,天天爽-国内精品一区二区三区-成人AV | 桃花色涩综合影院| 精吧天堂| 长长久久免费视频| 国产精品99精品视频网站| 天天干夜夜肏| 永久免费发布性爱网| 久久老熟女| 色婷婷综合视频| 黄片视频观看| 亚洲影视第一页| 色一色综合网| 美女骚尻视频| 国产福利av精彩对白| 中文乱码字幕观看视频| 亚洲淫色网中文| 亚洲AV免费在线| 久综合国内精品自在自线| 精品无人区麻豆乱码1区2区图片| 日韩国产品视频中文字| 97超碰精品| 99999久久久久9国产精品| www.黄色在线| 一二三四区操操Av| av国产无码| 亚洲中文字幕一区二区| 国产二区三区粉嫩在线| 人妻少妇视频在线播放| 天天做天天爱| 亚洲综人网| 丁香六月天| 超碰97色| 自拍二页| 麻豆久久视频在线地址| 精品一区二区成人动漫| 黄色av网站在线播放| 久热一区二区| 啊啊啊好舒服好爽啊啊啊视频| 小日子操bb在线看| 91综合在线| 欲香欲色综合天天伊人| 国产精品小视频一区二区三区| JIZZJIZZ亚洲女人被躁| 久久久久78| 人人爽夜夜操| 日韩激情中文字幕有码| 久思思热视频在线观看| 国产精品内射婷婷一级二| 色九久| 欧美青青视频| 国产精品色| 强奸乱亚洲| 懂色AV蜜臀无码精品APP| 亚洲伊人a线观看视频| 欧美图片校园春色| 精品人妻1237| 天美传媒国产原创中文字幕亚洲欧美另类 | 美女极品一区二区三区| 美女裸体无遮挡永久免费观看网站| 99999久久精| 英伦大奶子熟妇吊带| 久久亚洲欧美一区二区三区-亚洲国产精品第一区二区 | 欧美视频在线视频免费va| 99热这里只有精品8| 亚洲第一视频 欧美风情 日韩| 美女黑人91神马| 色色热| 93人人操人人| 熟女精品va中文字幕| 凹凸久久人人| 精品人妻美妇91job| 国产 三级自拍| 伊人一级免费黄片| 国产在线综合福利网站| 国产AAAAAABBBBB| 日天天九九天堂666| 久久久久9999妇女| 亚洲欧美setu| 东京热熟女亚洲视频网站| 精品少妇一区二区三区免费观看| 91在线色综合| 91精品大奶人妻| 狠日操| 黄色免费一级在线毛片| 日韩中文字幕国产| 亚洲高清国产理伦片| 色综合网1| 青青草日韩无码| 熟妇熟女一区二三区| 久久99精品国产| av橘色网站| 国产精品久久久久久久久久久久| 欧美视频一| 2019天天干| 日韩成人精品| 手机看片1024你懂的国产| 开心五月婷婷激情| 中文字幕制服欧美久久一区| 中国的操老妇女| 97久久国产精品女不卡| 亚洲黄片免费在线播放| 国产成年女黄特黄| 欧美经典一区二区三区| 五月激情天| 色色99| 99啪啪| 999久久芭蕾| 日韩二区三四区五区六区在线看| 97超碰免费人人性爱| 伊人欧美大香蕉视频| 亚洲伊人久久综合97| 国产剧情AV不卡在线观看| 日本熟女中文字幕一区| 思思热免费在线视频| www.久久| 亚州欧美总和| 亚欧无码线免费观看视频| 亚洲乱码尤物193YW| 国产18精品亚洲精品| 亚洲另类久操网| 2019男人的天堂| 夜夜黄| 日韩乱伦AⅤ| www.狠狠干.coom | 国产午夜精品理论片一二三区区| 国产精品高潮久久久无码| 欧美激情激情xxxx欧美专区| 午夜福利免费精品视频| 不卡免费av在线播放| 99操逼| 亚洲的天堂网| 97亚洲自在精品在线观看| 97资源视频| 高清无码 国产精品| 黄片www.| 国产乱人妻精品入口| 蜜桃精品视频一区二区三区| 97ai亚洲| 亚洲欧洲日韩国产自在线| 99久久综合| 97视频在线免费| 久艹日日日| 狠狠色综合网| 欧美 综合| 亚洲色天堂九9| 97精| 亚洲乱码国产乱码精网站| 久插综合| 亚洲精品一区二区精品| 婷婷丁香五月天综合东京热| 91伊人大香蕉| 中文字幕日韩专区精品系列| 成人三级片无码| 欧美激情久久久久| 韩国黄片aaaa| 东京太热久久久| julia ann久久| 2024黄色视频| 91女人的网站| 国产精品另类| 日本免费中文字幕在线| 开心五月天激情网| 大香蕉伊人75| 看日韩美女二区三区免费操逼视频 | 97超碰欧美中文字幕| 天天插天天射| se..亚洲欧美| 久久精品店| 97超碰欧美手机在线| 性爱视频免费网址| 亚洲区限制级| 香蕉欧美| 天天日天天舔东京热| 久久女人| 少妇无码太爽| 亚洲图片 欧美电影| 亚洲免费在线探花| 婷婷伊人一区| 国产精品爱欲| 91九九九吃| 一级二级三级黑人无码| 欧亚日韩三区| 热99这里只有精品| 麻豆av一区二区| 艹少妇网站| 婷婷精品久久av影视| 中国大陆国产高清AⅤ毛片| Aa东京男人的天堂| 91丨九色丨熟女高潮| 人妻熟女一区二区| 免费观看的av| 超碰97综合在线| 黄aaaaaaaaaaaaaaaaaa色网站| 国产91丝袜 在线播放| 嫖老熟女A片一二三区| 77国产精品| 久操精品网| 九九九久久久| 操91| 人妻系列无码专区中文有码| 狠狠色五月亚洲91| AV老汉| 尹人免费观看视频在线| 久久久工口| 成人aⅴ一区二区三区| 亚洲色资源| 婷婷九月| 国产精品一区av在线| 欧美A√综合网 | 蜜臀99久久国产| 91天天综合网,天天综合网| 性色AV蜜色av色欲av| 裸体美女久久久| 亚洲国产精品成人无码久久久| 少妇色综合| 日韩亚洲Av人人夜夜澡人人爽| 激情人妻另类| 国产99久久99热这里只有精品15| 国产剧情在线| 天天日天天干天天操| 丰满人妻一区二区三区四| 欧美丝袜美女电影一二三四区| 久久久精品成人国产| 干B| 91久久久久久| 国产精品人妻熟女aⅴ| 亚洲激情色片 | 欧美双插| 嗯嗯啊在线视频| 大香网站| 日韩一区二区精彩视频| 欧美视频一区二区三区| 色啪网| 日韩猛交| 蜜桃久久久久久久| 一区二区三区亚洲| 激情久久日韩精品中文字幕麻豆| 白丝1区2区3区| 久操网址| 91欧美经典| nuu12国产麻豆精品| 国产精品高潮久久AV| 日韩国产成人自拍视频| 91色人妻| 中文操逼字幕| 国产极品馒头逼| 人妻人人澡人人爽人人| 国产精品成人蜜臀AV在线| 日韩中文字幕视频| aaa亚无码专区| 99热99re6国产在线播放| 玖玖在线视频| 成人自拍三级在线观看| 高清孕妇孕交| 日本一级不卡一二区| 夜色五月天| 亚洲精品国产熟女久久久久久| 高清视频一区| 一区,二区,三区视频| 91色综合激情| 国产污视频麻豆传媒一区二区 | 精品成人女人久久| 色九九九综合| 丝袜av一区二区三区| 天天综合精品| 婷婷五月在线视频| 亚洲激情久久| 欧美性爱www免费版| 久干9操| 日本高清_区二区三区| 超碰无码加勒比| 黑人在线91| 高清肉丝中文无码| 小草三级久久观看| 俺去俺来也在线www| 天天上日日上日韩精品| AV乱伦国产| 黄页| 天天视频黄| 亚洲国产av中文字幕久久| 三级AV入口| 日韩亚洲国产视频| 欧美成人黄网色网站| 在线观看综合精品亚洲| 91婷婷| 国精精品无码一二三区水多多| 97九色| BBBBB97COM| 亚州欧美色图| 日韩大香蕉AV影片| 日本一道在线播放高清| 啪啪啪男女亚洲中文字幕99| 91精品网站| 欧美情色亚洲| 亚欧操逼片在线观看| 99热这里都是精品| 91精品国产91久久福利| 黄色一区二区秘书性感| 日韩性爱视频在线免费观看| 91高清无码下载| 99色婷婷| 麻豆天美传媒在线视频天堂| 91美女视屏| 韩国一区二区精品亚洲| 伊人网在线观看| 老熟女熟妇| 久久 久久国内精品亚洲| www欧美91| 人人操我人人干| 13小男生GAY自慰脱裤子| 日本视频一区二区三区| 青青草日韩无码| 欧美成人综合| 91强在线播放| 亚洲图片第一页| 久久超碰97| 清纯唯美亚洲综合| 91天天综合| 久久成年片色大黄全免费网站| 一区二区三区探花在线观看| 免费公开人人操| 日韩一性一交一A片俄罗斯| 啊啊啊啊一区| 有码免费观看| 亚洲另类色综合网站| 欧美成人性爱视频在线播放 | 99热线麻豆| 9国产超碰| 日韩精品人妻一| 殴美,日韩国产伦精品| 91女网站| 欧美精品偷拍| 夜夜欢天天干| 思思热免费视频观看| 日产狠狠干| 亚洲一区制服诱惑| 78精品在线| 日韩一区二区三区四区五区 | 久久精品日韩| 久久久久骚| 另类欧美色| 日本中文字幕在线电影| 素人播放一区| 国产精品高潮久久AV| 国产深夜福利| 9色在线| 女人天堂网| 日韩欧无码一区二区三区免费不卡| aaa一级黄片| 97精品一二区| 偷拍五区| 日逼逼免费看| 青娱乐大香蕉| 国产精品久久aV| 日韩AV无码中文一区二区| 色99在线| 天美传媒AV国产在线| 精品无码一区二区三区| 欧美亚男人的天堂| 神马久久久久久久| 狠狠色狠狠色狠狠五月| 欧美高清性猛交| 国产熟女二区| 久草资源在线| 操人91| 欧美性生活内射| 好吊色综合| 免费观看有码高清视频| 嗯,啊。舔我逼| 亚洲综合另类小说色区亚洲成av人片在www | 中文字幕 一区二区 亚洲无码| 91天美| 人妻精品视频一区二区| 久久久精品九| 黄色电影在线播放综合网站| 日韩懂色网| 国产熟女精品一区二区| 黄色欧美性爱视频| 亚洲脚交| 丁香六月激情| 97欧美久久久久久久| 一本色道无码DVD中文字幕| 激情图片伦理国产一区二区日韩| 91欧美情色| 亚洲色图日韩精品| 99精品无码| 国产A v无码专区| 精品一区二区久久| 另类TS人妖一区二区三区| 啊啊啊操一区| 精品人妻高清麻豆av| 国产人妖视频一区在线观看| 2019亚洲男人天堂| 免费啪啪av| 久久视频,这里只有精品| 亚洲国产激情国产av| 试看60秒| 五月天丁香| 大香蕉淫人| 精品乱子一区二区三区99| 国产传媒操逼视频| 国语精品对白| 色婷婷综合网站| 骚日日av| 亚洲国产欧美中日韩成人综合视频| 天堂射| 99热官网| 日韩精品一区二区高清| 亚洲AV高潮| 人人操人人摸人 | 亚洲砖码砖专无区2023| 夜夜精品视频| 超碰三级秋霞| yellow网站免费观看日韩高清无码| 97精品视频免费| 超碰在线看| 2017天天插| 国产美女激情| 五月丁香综合激情| 99999精品| 99啪| 偷看洗澡一二三区美女| 亚洲欧美一区二区网址| 亚州高清AV| 人妻少妇久久久| 国产亚洲日韩在线三区黑人| 久九色| 亚洲好色人妻| 四虎免费看黄| 理论久久婷婷网 8| 欧美在线永久天堂| 日逼五月天| 国产女人高潮视频| 美国日韩黄片| 欧美色图20P| 精品.99999| 欧美日日操| 亚洲国产综合视频| 最新中文字幕av| 狼人综合婷婷激情四射 | 亚洲一区二区麻豆影院| 亚洲古典另类欧美在线| 国产亚洲欧美每日在线| 日韩亚洲97| 丰满搜索结果 -第18页- 久久高清无码 | 五月婷婷色| 性爱精品一区| 狠狠爱综合网| 久久国产精品熟女人妻| 丰满人妻一区二区三区大胸懂色| 国产美女高潮视频| 操淫穴亚洲五月丁香| 日韩钢筋无码高清啾啾啾| 99国内精品| 91在线一起| 久久 久久国内精品亚洲| 色91综合网| 日本一区二区三区欧美日韩中文字幕| 欧美中文字幕日韩在线| 激情欧美97| 我中文字幕6区| 最新精品久久蜜桃 | 午夜电影在线观看无码专区| 少妇一区二区三区高速| 亚洲春色欧美激情自拍| 视频一区二区免费在线| 97视频在线免费观看| 天天摸天天舔天天操| 欧美一级三级| 999亚洲国产视频| 久久久久免费看少妇A片特黄| 揉揉揉夜夜| 大香蕉中文201| 欧洲视频在线| 99在线精品视频| 九九亚洲| 亚洲欧美一区二区网址| 九九九九九九综合| 欧美少妇性乱| 亚洲欧洲无码一区夜| 嗯~啊~快点 死我视频免费看网站| 东京太热久久久| 亚洲欧美综合色| 天天干天天爽| 台欧久久精品视频|