2025, Sep 28 09:31

Tkinter में Scrollbar को Listbox से फ्लश बैठाने के तरीके

Tkinter में Listbox–Scrollbar के बीच गैप क्यों बनता है और इसे कैसे हटाएँ: grid व sticky से फ्लश फिट करें या Frame में समूहित करें. कारण, टिप्स और छोटे कोड उदाहरण.

Tkinter में Scrollbar को Listbox के साथ बिल्कुल सटा कर बिठाना

कभी‑कभी Tkinter में दिखने में सरल लेआउट भी लाइनअप नहीं होता। एक आम उदाहरण — क्षैतिज Scrollbar, जो Listbox से कसकर नहीं लगता और highlightthickness, padding और sticky के मान सही होने पर भी बीच में अनचाहा गैप छोड़ देता है। हालात तब और पेचीदा हो जाते हैं, जब उसी grid में Canvas जैसे अन्य विजेट भी हों, क्योंकि वे पंक्तियों का आकार तय करने को प्रभावित करते हैं।

समस्या दिखाने वाला न्यूनतम सेटअप

नीचे दिया उदाहरण बाईं ओर Canvas और दाईं ओर Listbox व क्षैतिज Scrollbar रखता है। जब Listbox की ऊँचाई फिक्स होती है तो यह गैप अक्सर दिखाई देता है, और इस कॉन्फ़िगरेशन में अलग‑अलग प्लेटफ़ॉर्म पर भी नज़र आता है।

import tkinter as tk
app = tk.Tk()
lb = tk.Listbox(app)
hbar = tk.Scrollbar(app)
cnv = tk.Canvas(app, width=205, height=205)
img = tk.PhotoImage(file="password_img.png")
cnv.img_ref = img
cnv.create_image(102, 102, image=img)
cnv.config(highlightthickness=0)
cnv.grid(column=0, row=0, rowspan=2)
lb.config(height=4, xscrollcommand=hbar.set)
lb.grid(column=1, row=0, sticky="EW")
hbar.config(orient="horizontal", command=lb.xview)
hbar.grid(column=1, row=1, sticky="EW")
app.mainloop()

गैप बनने का असली कारण

Listbox की ऊँचाई को स्थिर मान देने के बाद यह व्यवहार साफ दिखता है। grid जियोमेट्री मैनेजर कॉलमों में पंक्तियों की ऊँचाई को संरेखित करता है, और जब विजेट एक‑दूसरे की ओर एंकर नहीं होते तो उनके आकार का संयोजन एक ऊर्ध्वाधर ऑफ़सेट बना सकता है। ऊपर के उदाहरण में Listbox अपने grid सेल के निचले किनारे तक नहीं धकेला गया है और Scrollbar अपने सेल के ऊपरी किनारे तक नहीं खींचा गया, इसलिए उनके बीच एक पतली सी जगह दिखती है।

समाधान: sticky से दोनों ओर एंकर करें

Listbox को दक्षिण (S) किनारे से और Scrollbar को उत्तर (N) किनारे से चिपकाएँ, और दोनों को पूर्व–पश्चिम (E–W) दिशा में फैला रहने दें। इससे दोनों किनारे मिल जाते हैं और गैप हट जाता है।

import tkinter as tk
app = tk.Tk()
lb = tk.Listbox(app)
hbar = tk.Scrollbar(app)
cnv = tk.Canvas(app, width=205, height=205)
img = tk.PhotoImage(file="password_img.png")
cnv.img_ref = img
cnv.create_image(102, 102, image=img)
cnv.config(highlightthickness=0)
cnv.grid(column=0, row=0, rowspan=2)
lb.config(height=4, xscrollcommand=hbar.set)
lb.grid(column=1, row=0, sticky="EWS")
hbar.config(orient="horizontal", command=lb.xview)
hbar.grid(column=1, row=1, sticky="NEW")
app.mainloop()

यह समायोजन, जहाँ आप अन्य ऊर्ध्वाधर अंतराल बनाए रखना चाहते हैं, उन्हें प्रभावित किए बिना सब कुछ अपनी जगह पर रखता है।

विकल्प: Frame के साथ अलग करें

एक और भरोसेमंद तरीका है Listbox और Scrollbar को एक Frame में समूहित करना और उनके संबंध को उसी कंटेनर के भीतर प्रबंधित करना। इस तरह वे विंडो के बाकी हिस्से में इस्तेमाल किए गए grid से प्रभावित नहीं होते। इस वैरिएंट में Canvas को rowspan की ज़रूरत नहीं पड़ती।

import tkinter as tk
app = tk.Tk()
cnv = tk.Canvas(app, width=205, height=205)
img = tk.PhotoImage(file="password_img.png")
cnv.img_ref = img
cnv.create_image(102, 102, image=img)
cnv.config(highlightthickness=0)
cnv.grid(column=0, row=0)
holder = tk.Frame(app)
holder.grid(column=1, row=0)
lb = tk.Listbox(holder)
hbar = tk.Scrollbar(holder)
lb.config(xscrollcommand=hbar.set, height=4)
lb.grid(column=1, row=0, sticky="EW")
hbar.config(orient="horizontal", command=lb.xview)
hbar.grid(column=1, row=1, sticky="EW")
app.mainloop()

यह लेआउट दोनों को साथ रखता है और वही दृश्य परिणाम देता है, जबकि बाकी UI स्वतंत्र रहती है।

यह क्यों मायने रखता है

grid द्वारा प्रबंधित पंक्तियाँ कॉलमों में ऊँचाई साझा करती हैं, कुछ‑कुछ स्प्रेडशीट के व्यवहार जैसी। किसी एक कॉलम में अधिक ऊँचा विजेट पंक्ति की ऊँचाई को प्रभावित कर सकता है और यदि तत्व सही तरह से एंकर न हों तो कहीं और गैप उजागर हो सकते हैं। sticky को स्पष्ट रखना और ज़रूरत होने पर संबंधित विजेट्स को Frame में अलग करना, UI के बढ़ने‑घटने या नए कॉम्पोनेंट जुड़ने पर होने वाले सूक्ष्म लेआउट खिसकाव को रोकता है।

निष्कर्ष

जब Scrollbar, Listbox के साथ फ्लश नहीं बैठता, तो दोनों ओर एंकर करें: Listbox के sticky में S और Scrollbar के sticky में N जोड़ें, साथ ही उन्हें पूर्व–पश्चिम दिशा में फैला रहने दें। अगर आपकी विंडो में ऐसे अन्य विजेट हैं जो grid का आकार प्रभावित करते हैं, तो Listbox और Scrollbar को एक Frame में समूहित करें और उनका लेआउट उसी कंटेनर के अंदर करें। ये दोनों पैटर्न लेआउट को पूर्वानुमेय रखते हैं और आगे चलकर बेवजह दिखने वाले गैप के झंझट से बचाते हैं।

यह लेख StackOverflow के प्रश्न पर आधारित है, जिसे Nabodita Gangully ने पूछा था, और furas के उत्तर पर।