首页 > 解决方案 > 有没有办法可以在 tkinter 多窗口的两个不同窗口上使用两个相同的自动完成输入框?

问题描述

这段代码的问题是我有两个自动完成输入框,一个在 Win1 中,另一个在 Win3 中。虽然它在 Win1 中工作,但问题是当我点击 Win3 时,新的输入框出现在 win1 中。self.entername_e 用于接收 Win3 上的条目,self.name_e 用于接收 Win1 上的条目

import tkinter as tk
from tkinter import *
import sqlite3
import tkinter.messagebox
import datetime
import math
import os
import random
import re

AutocompleteEntry 是 Windows Win1 和 Win3 都使用的类

#This is the Autocomplete class both the entries will use
class AutocompleteEntry(Entry):
    def __init__(self, autocompleteList, *args, **kwargs):

        # Listbox length
        if 'listboxLength' in kwargs:
            self.listboxLength = kwargs['listboxLength']
            del kwargs['listboxLength']
        else:
            self.listboxLength = 8

        # Custom matches function
        if 'matchesFunction' in kwargs:
            self.matchesFunction = kwargs['matchesFunction']
            del kwargs['matchesFunction']
        else:
            def matches(fieldValue, acListEntry):
                pattern = re.compile('.*' + re.escape(fieldValue) + '.*', re.IGNORECASE)
                return re.match(pattern, acListEntry)
                
            self.matchesFunction = matches

        
        Entry.__init__(self, *args, **kwargs)
        self.focus()

        self.autocompleteList = autocompleteList
        
        self.var = self["textvariable"]
        if self.var == '':
            self.var = self["textvariable"] = StringVar()

        self.var.trace('w', self.changed)
        self.bind("<Right>", self.selection)
        self.bind("<Up>", self.moveUp)
        self.bind("<Down>", self.moveDown)
        
        self.listboxUp = False

    def changed(self, name, index, mode):
        if self.var.get() == '':
            if self.listboxUp:
                self.listbox.destroy()
                self.listboxUp = False
        else:
            words = self.comparison()
            if words:
                if not self.listboxUp:
                    self.listbox = Listbox(width=self["width"], height=self.listboxLength)
                    self.listbox.bind("<Button-1>", self.selection)
                    self.listbox.bind("<Right>", self.selection)
                    self.listbox.place(x=self.winfo_x(), y=self.winfo_y() + self.winfo_height())
                    self.listboxUp = True
                
                self.listbox.delete(0, END)
                for w in words:
                    self.listbox.insert(END,w)
            else:
                if self.listboxUp:
                    self.listbox.destroy()
                    self.listboxUp = False
        
    def selection(self, event):
        if self.listboxUp:
            self.var.set(self.listbox.get(ACTIVE))
            self.listbox.destroy()
            self.listboxUp = False
            self.icursor(END)

    def moveUp(self, event):
        if self.listboxUp:
            if self.listbox.curselection() == ():
                index = '0'
            else:
                index = self.listbox.curselection()[0]
                
            if index != '0':                
                self.listbox.selection_clear(first=index)
                index = str(int(index) - 1)
                
                self.listbox.see(index) # Scroll!
                self.listbox.selection_set(first=index)
                self.listbox.activate(index)

    def moveDown(self, event):
        if self.listboxUp:
            if self.listbox.curselection() == ():
                index = '0'
            else:
                index = self.listbox.curselection()[0]
                
            if index != END:                        
                self.listbox.selection_clear(first=index)
                index = str(int(index) + 1)
                
                self.listbox.see(index) # Scroll!
                self.listbox.selection_set(first=index)
                self.listbox.activate(index) 

    def comparison(self):
        return [ w for w in self.autocompleteList if self.matchesFunction(self.var.get(), w) ]

这是代码开始的地方

class Win1:
    def __init__(self, master):
        self.master = master
        self.master = master 
        autocompleteList = [ 'Milo tin', 'Shito small', 'Deodorant', 'Spray']
        def matches(fieldValue, acListEntry):
            pattern = re.compile(re.escape(fieldValue) + '.*', re.IGNORECASE)
            return re.match(pattern, acListEntry)
        
        self.master.geometry("400x300")
        self.show_widgets()

这是Win1上的AutocompleteEntry

        #Autocomplete Entry
        self.name_e = AutocompleteEntry(autocompleteList, listboxLength=10, width=25, font=('arial 18 bold'), bg='lightblue', matchesFunction=matches)
        self.name_e.place(x=260, y=150)
 
    def show_widgets(self):
        self.frame = tk.Frame(self.master)
        self.master.title("Window n.1")
        self.create_button("Click to open Window 2", Win2)
        self.create_button("Click to open Window 3", Win3)
        self.frame.pack()
 
    def create_button(self, text, _class):
        "Button that creates a new window"
        tk.Button(self.frame, text=text,command=lambda: self.new_window(_class)).pack()
 
    def new_window(self, _class):
        self.win = tk.Toplevel(self.master)
        _class(self.win)
 
 
class Win2(Win1):
    def __init__(self, master):
        self.master = master
        self.master.title("Window n.2")
        self.master.geometry("400x100+200+200")
        self.show_widgets()
 
    def show_widgets(self):
        "A frame with a button to quit the window"
        self.frame = tk.Frame(self.master, bg="red")
        self.quit_button = tk.Button(self.frame, text=f"Quit this window n. 2",command=self.close_window)
        self.quit_button.pack()
        self.create_button("Open window 3 from window 2", Win3)
        self.frame.pack()
 
    def close_window(self):
        self.master.destroy()
 
 
class Win3(Win1):
    def __init__(self, master):
        self.master = master
        self.master = master
 
        #This is the list of the autocomplete entry
        autocompleteList = [ 'Milo tin', 'Shito small', 'Deodorant', 'Spray' ]
        def matches(fieldValue, acListEntry):
            pattern = re.compile(re.escape(fieldValue) + '.*', re.IGNORECASE)
            return re.match(pattern, acListEntry)
        
        self.master.title("Window n.3")
        self.master.geometry("400x200+200+200")
        self.show_widgets()

这也是 Win3 上的 AutocompleteEntry

        #Autocomplete Entry
        self.entername_e = AutocompleteEntry(autocompleteList, listboxLength=10, width=25, font=('arial 18 bold'), bg='white', matchesFunction=matches)
        self.entername_e.place(x=260, y=150)
 
    def show_widgets(self):
        self.frame = tk.Frame(self.master, bg="green")
        self.quit = tk.Button(self.frame, text=f"Quit this window n. 3",command=self.close_window)
        self.quit.pack()
        self.label = tk.Label(self.frame, text="THIS IS ONLY IN THE THIRD WINDOW")
        self.label.pack()
        self.frame.pack()
 
    def close_window(self):
        self.master.destroy()
 
 
root = tk.Tk()
app = Win1(root)
root.mainloop()

标签: pythonpython-3.xpython-2.7tkinter

解决方案


推荐阅读