鼠标悬停在Tkinter按钮上之前不会显示

时间:2019-03-27 21:11:40

标签: python button tkinter

有一个函数,我每次调用时都会添加一行,其中包含一个Entry,Combobox和一个Button。当我第一次调用该函数时,直到将鼠标光标移至该按钮的假定位置后该按钮才可见。 Before cursor hover After cursor hover

如果我一次调用该函数,则除第一行外,其他所有行均明显包含该按钮。我在框架内使用网格布局。

namevar = StringVar()
cbvar = StringVar()
entry = Entry(self.createTableFrame, textvariable = namevar)           
cb = ttk.Combobox(self.createTableFrame, textvariable = cbvar, values= self.sqlDatatypes,
                   state='readonly'
                   )
cb.bind("<<ComboboxSelected>>", self.datatypeSelect)
cb.bind("<Return>", self.datatypeSelect)

#this segment contains the error
btn = Button(self.createTableFrame, text='Remove')
btn.bind('<Button-1>', self.deleteRowNT)

entry.grid(row=self.rowcountNT, column = 0)
cb.grid(row=self.rowcountNT, column = 1)
btn.grid(row = self.rowcountNT, column = 2)

以下是完整的代码供参考: (该错误发生在def nextEntryTable(self)中的函数class Tables(Scan)中)

from tkinter import * 
import tkinter as tk
from tkinter import ttk
import mysql.connector


class Scrollable(ttk.Frame):

#       Make a frame scrollable with scrollbar on the right.
#       After adding or removing widgets to the scrollable frame, 
#       call the update() method to refresh the scrollable area.


    def __init__(self, frame, width=16):

        scrollbar = tk.Scrollbar(frame, width=width)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y, expand=False)

        self.canvas = tk.Canvas(frame, yscrollcommand=scrollbar.set)
        self.canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        scrollbar.config(command=self.canvas.yview)

        self.canvas.bind('<Configure>', self.__fill_canvas)

        # base class initialization
        tk.Frame.__init__(self, frame)         

        # assign this obj (the inner frame) to the windows item of the canvas
        self.windows_item = self.canvas.create_window(0,0, window=self, anchor=tk.NW)


    def __fill_canvas(self, event):
        "Enlarge the windows item to the canvas width"

        canvas_width = event.width
        self.canvas.itemconfig(self.windows_item, width = canvas_width)        

    def update(self):
        "Update the canvas and the scrollregion"

        self.update_idletasks()
        self.canvas.config(scrollregion=self.canvas.bbox(self.windows_item))

class Scan(Frame):
    def __init__(self, master):
        self.flag = 0 # to stop multiple instances opening 
        self.master = master
        self.master.geometry('300x200+500+300')
        self.master.title('Scan Page')
        self.frame = Frame(self.master)
        lablist = ['Host','User name','Password', 'Database']
        self.lables, self.entries, self.svars = self.addlables(self.frame, lablist)
        self.b1=Button(self.frame,text='SCAN',command=self.tableselect)
        self.b1.grid(row= len(lablist))
        self.master.bind('<Return>',self.tableselect)
        self.message = Message(self.frame, text='Connection status',
                               bg ='Grey', width= 100)
        self.message.grid(row = 5, column = 1)
        self.frame.pack(fill='x',expand= True)
        self.tables = None

    def tableselect(self, event=None):
        try:
            self.tables.destroy()
        except:
            print('Nothing to destroy')
        conn = self.databaseconnect()
#        print( self.entries[0]["textvariable"] )
        if conn != -1:
            self.tables = Toplevel(self.master)
            self.app = Tables(self.tables, conn)

    def addlables(self, lableroot, lablelist):
        lables = []
        entries = []
        svars = []
        for labs, i in zip(lablelist, range(len(lablelist))):
            l = Label(lableroot, text = labs)
            l.grid(row=i)
            e = Entry(lableroot)
            e.grid(row=i, column = 1, columnspan = 5)
            s = StringVar()
            e['textvariable'] = s
            lables.append(l)
            entries.append(e)
            svars.append(s)
        svars[0].set('localhost')
        svars[1].set('myproject')
        svars[2].set('myproject')
        return [lables, entries, svars]    
    def printvals(self, event):
        for s in self.svars:
            print(s.get())
    def databaseconnect(self):
        s = self.svars
        try:
            if s[3].get()=='':
                conn = mysql.connector.connect(host=s[0].get(), user = s[1].get(), 
                                   passwd = s[2].get())
            else:
                conn = mysql.connector.connect(host=s[0].get(), user = s[1].get(), 
                                   passwd = s[2].get(), 
                                   database = s[3].get())
            self.message.config(text='Connected', bg ='Lightgreen')
            return conn
        except Exception as e:
            for x in e.args:
                print(x)
            self.message.config(text="Error Connecting", bg='Red')
#            self.message.grid(row = 5)
            return -1

class Tables(Scan):
    def __init__(self, master, connector):
        self.conn = connector
        self.cursor = self.conn.cursor()
        self.master = master
        self.master.geometry('600x400+150+20')
        self.master.title('Table Selection')
        if self.conn.database == None:
            print('Connected without a database')
            self.dbRadiobuttonState = 'normal'
        else:
            print('Conneccted using ',self.conn.database,' database')
            self.dbRadiobuttonState = 'disabled'
            self.master.title('Database: ' + self.conn.database)
        self.f1 = Frame(self.master, padx=5) ## Main frame

        self.entry = Entry(self.f1)
        self.data = StringVar()   ##Variable to get value from the Entry bar
        self.entry['textvariable'] = self.data
        self.entry.pack(fill = X, pady = 10)


        ##Button creations segment 
        self.f2root = Frame(self.f1)  ##Main left frame, fixed size
        self.f2 = Frame(self.f2root)  ##top bar for 'Open tables'
        self.b1 = Button(self.f2, text =   '   Open Table', command= self.openTableClick)
        self.b1.pack(side = 'left') 
        self.b1.bind('<Return>', self.openTableClick)
        self.b2 = Button(self.f2, text =   ' Select Databse ', command = self.selectDatabaseClick)
        self.b2.bind('<Return>', self.selectDatabaseClick)
        self.b2.pack(side = 'left', expand=True)
        self.f2.pack(side = 'top')

        self.f22 = Frame(self.f2root)  ##Bar frame below self.f2
        self.b12 = Button(self.f22, text = 'Create Table ', command = self.createTableClick)
        self.b12.pack(side = 'left')
        self.b22 = Button(self.f22, text = 'Create Database')
        self.b22.pack(side = 'left')
        self.f22.pack(side = 'top')

        self.f2root.pack(fill='y', side='left')
        ##Button creation ended


        self.nb = ttk.Notebook(self.f1)
        self.dbPage = ttk.Frame(self.nb)
        self.setDBList()

        self.tablesPage = ttk.Frame(self.nb)
        self.tableList= [] #Contains a list of all the tables
        self.tableFrameBuffer = [] #Contains a list of all the Frames
        self.currentFrameSelected = -1
        self.tableLayoutSet()
        if self.dbRadiobuttonState == 'disabled':
            self.createTableBuffer()
            self.dbval.set( self.dbList.index( self.conn.database))



        self.nb.add(self.dbPage, text = 'Databse')
        self.nb.add(self.tablesPage, text = 'Tables')
        self.nb.pack(expand=1, fill='both')

        self.f1.pack(fill='both', expand= True)


    def selectDatabaseClick(self, event=None):
        print('Database: ',self.data.get())
        try:
            index = self.dbList.index(self.data.get())
            print('Index: ', index)
            self.dbval.set(index)
            self.connectDB()
        except:
            print('Error in clicking DB Select button')
    def openTableClick(self, event=None): ##Called whenever we click 'Open table'
        print(self.data.get())
        try:
            index = self.tableList.index(self.data.get())
            print('Table index: ',index)
            self.tabVar.set(index+1)
            self.tableSelect()            
        except:
            print('Could not find entered table')

    def createTableClick(self):
        ##Uses button self.b12 
        print('Create Table clicked')
        if self.nb.winfo_ismapped():
            print('Notebook state: ', self.nb.winfo_ismapped())
            self.nb.pack_forget()
            self.b12.config(text = 'Cancel')
            self.b22.config(state='disabled')
            self.createNewTableLayout()
            self.newTableMF.pack(fill='both', expand=True, anchor = 'n')

        else:
            self.newTableMF.pack_forget()
            print('Notebook state: ', self.nb.winfo_ismapped())
            self.nb.pack(expand=1, fill='both')
            self.b12.config(text='Create Table ')
            self.b22.config(state='normal')

    def setDBList(self):
        self.dbList = []
        self.cursor.execute("SHOW DATABASES")
        self.dbval = IntVar()
        self.dbval.set(-1)
        i=0
        for (x,) in self.cursor:
            self.dbList.append(x)
            rb = tk.Radiobutton(self.dbPage, 
                  text=x,
                  padx = 20, 
                  variable=self.dbval, 
                  command=self.connectDB,
                  state = self.dbRadiobuttonState,
                  value=i)
            rb.pack(anchor="nw")
            i=i+1

    def connectDB(self): 
        self.cursor.execute("USE " + self.dbList[self.dbval.get()])
        print("Databse selected: " + self.conn.database)
        self.master.title('Database: ' + self.conn.database)
        self.createTableBuffer()

    def createTableBuffer(self):
        self.cursor.execute("show tables")
        self.tabVar = IntVar()
        ##CLeanup code
        for destroyableFrame in self.tableFrameBuffer:
            destroyableFrame.destroy()
        self.currentFrameSelected = -1
        self.tableFrameBuffer = [] ##Contains the list of Frames 
        self.tableList = [] 
        for (x,) in self.cursor:
            if (self.cursor.rowcount -1)  % 10 == 0:
#                print(self.cursor.rowcount,'Frame buffer ',' added ')
                tempFrame = Frame(self.tablesTopFrame)
                self.tableFrameBuffer.append(tempFrame)
                self.currentFrameSelected = len(self.tableFrameBuffer)-1
            rb = Radiobutton(self.tableFrameBuffer[-1], 
                             text = x,
                             padx=20,
                             pady=2,
                             variable = self.tabVar, 
                             command = self.tableSelect, 
                             value = self.cursor.rowcount)
            rb.pack(anchor='w')
            self.tableList.append(x)    ## List of all the names of tables
        if len(self.tableFrameBuffer) >0:
            self.tableFrameBuffer[0].pack()
            self.currentFrameSelected = 0


    def tableLayoutSet(self):
        self.tablesTopFrame = Frame(self.tablesPage)
        self.tablesBottomFrame = Frame(self.tablesPage)

        self.nextTableButton = Button(self.tablesBottomFrame, text = 'Next',
                                command = self.nextTableFrame, padx=10)
        self.prevTableButton = Button(self.tablesBottomFrame, text = 'Previous',
                                command = self.prevTableFrame, padx=10)
        self.prevTableButton.pack(side = 'left')
        self.nextTableButton.pack( side = 'left')

        self.tablesBottomFrame.pack(side = 'bottom', fill='x')
        self.tablesTopFrame.pack(side = 'top', anchor = 'w') 
    def nextTableFrame(self):
        if self.currentFrameSelected < len(self.tableFrameBuffer) -1:
            self.tableFrameBuffer[self.currentFrameSelected].pack_forget()
            self.tableFrameBuffer[self.currentFrameSelected + 1].pack()
            self.currentFrameSelected += 1

    def prevTableFrame(self):
        if self.currentFrameSelected > 0:
            self.tableFrameBuffer[self.currentFrameSelected].pack_forget()
            self.tableFrameBuffer[self.currentFrameSelected - 1].pack()
            self.currentFrameSelected -= 1

    def tableSelect(self):
        val = self.tabVar.get()
        print(self.tableList[val - 1])
        try:
            self.newTableWindow.destroy()
        except:
            pass
        self.newTableWindow = Toplevel(self.master)
        self.app = TablesData(self.newTableWindow, self.cursor,
                              self.tableList[val - 1])


    def createNewTableLayout(self):

        self.sqlDatatypes = ['int', 'tinyint', 'smallint', 'mediumint', 'bigint',
                             'float', 'double', 'decimal',
                             'date','datetime','timestamp','time','year',
                             'char','varchar','text', 'tinytext','mediumtext','longtext','enum']
        self.ntRowList = []
        self.ntVarList = []   ##New Table var list

        self.newTableMF = Frame(self.f1) ## New table main frame

        ##Top frame containing the sql command
        self.topFrameNT = Frame(self.newTableMF)
        lable = Label(self.topFrameNT, text='SQL Command')
        self.newtableSQLcommand = StringVar()
        entry = Entry(self.topFrameNT, textvariable = self.newtableSQLcommand)
        lable.pack(side='left')
        entry.pack(side='left', fill='x', expand=True)
        self.topFrameNT.pack(side='top', fill='x')

        ##Bottom frame containing table names and dattatypes
        self.createTableFrame = Frame(self.newTableMF, bg='red') ##Bottom frame 
        lable = Label(self.createTableFrame, text = 'Table name')
        lable.grid(column=0, row=0, sticky='w')
        self.newTableName = StringVar()
        entryNewTable = Entry(self.createTableFrame, textvariable = self.newTableName)
        entryNewTable.grid(row=0, column=1, sticky='w')
        plusButton = Button(self.createTableFrame, text = '+', command = self.nextEntryTable)
        plusButton.grid(row=0, column=2)

        lable = Label(self.createTableFrame, text = 'Column Name')
        lable.grid(column=0, row=1, sticky= 'w')
        lable = Label(self.createTableFrame, text = 'Datatype')
        lable.grid(column=1, row=1, sticky= 'w')     
        self.rowcountNT = 1
        self.nextEntryTable()
        self.createTableFrame.pack(side='bottom', fill='both', expand=True)
    def nextEntryTable(self):
        self.rowcountNT += 1
        namevar = StringVar()
        cbvar = StringVar()
        entry = Entry(self.createTableFrame, textvariable = namevar)           
        cb = ttk.Combobox(self.createTableFrame, textvariable = cbvar, values= self.sqlDatatypes,
                           state='readonly'
                           )
        cb.bind("<<ComboboxSelected>>", self.datatypeSelect)
        cb.bind("<Return>", self.datatypeSelect)

        btn = Button(self.createTableFrame, text='Remove')
        btn.bind('<Button-1>', self.deleteRowNT)

        entry.grid(row=self.rowcountNT, column = 0)
        cb.grid(row=self.rowcountNT, column = 1)
        btn.grid(row = self.rowcountNT, column = 2)

        l = [btn.winfo_id(), entry, cb, btn]
        self.ntRowList.append(l)
        l = [namevar, cbvar]
        self.ntVarList.append(l)


    def datatypeSelect(self, event):
        state = list (map(lambda var: [var[0].get(), var[1].get()], self.ntVarList))
        print(state)

    def deleteRowNT(self, event):
        bid  = event.widget.winfo_id()
        for rows in self.ntRowList:
            if rows[0] == bid:
                index = self.ntRowList.index(rows)
                break
        print('Row number: ', index+1)
        row = self.ntRowList[index]
        row[3].destroy()
        row[2].destroy()
        row[1].destroy()
        del(self.ntRowList[index])
        print('Row deleted')

class TablesData(Tables):
    def __init__(self, master, cursor, table):
        self.master = master
        self.cursor = cursor
        self.tablename = table
        self.master.geometry('500x500+50+30')
        self.master.title(str(table))

        self.buttonFrame = Frame(self.master)
        self.buttonLayoutSet()
        self.buttonFrame.pack(side='bottom', fill='x')

        self.topFrame = Frame(self.master)
        self.scrollableFrame = Scrollable(self.topFrame)
        self.entriesframe = Frame(self.scrollableFrame)
        self.entriesframe.grid()
        self.displayTables()
        self.topFrame.pack(fill='both', side='top', anchor='w', expand=True)


    def buttonLayoutSet(self):
        self.delete = Button(self.buttonFrame, text='Delete', command=self.deleteClick)
        self.delete.pack(side='left')
        self.edit = Button(self.buttonFrame, text='Edit', command=self.editClick)
        self.edit.pack(side='left')
        self.insert = Button(self.buttonFrame, text='Insert', command=self.insertClick)
        self.insert.pack(side='left', padx=20)
        self.delete.config(state='disabled')
        self.edit.config(state='disabled')        
    def insertClick(self):
        print('Insert')
    def deleteClick(self):
        print('Delete')
    def editClick(self):
        print('Edit')  
    def allSelect(self):
        allVal = self.allCheck.get()
        for var in self.entryVarList:
            var.set(allVal)
        if allVal == 1:
            self.delete.config(state='normal')
        else:
            self.delete.config(state='disabled')
        self.edit.config(state='disabled')

    def displayTables(self):
        self.cursor.execute('DESC '+ str(self.tablename))
        self.allCheck = IntVar()
        cb = Checkbutton(self.entriesframe, 
                         onvalue=1, offvalue=0,
                         variable = self.allCheck, 
                         command = self.allSelect)
        cb.grid(row=0, column=0)
        for heading in self.cursor:
            L = Label(self.entriesframe, text=heading[0])
            L.grid(row=0, column = self.cursor.rowcount)

        self.cursor.execute('select * from ' + str(self.tablename))
        self.entryVarList = []
        for tableEntries in self.cursor:
            entryVar = IntVar()
            cb = Checkbutton(self.entriesframe, 
                             onvalue=1, offvalue= 0,
                             variable = entryVar,
                             command= self.selectEntry)           
            cb.grid(row=self.cursor.rowcount, column=0)

            self.entryVarList.append(entryVar)
            for val, col in zip(tableEntries, range(1,len(tableEntries) + 1)):
                L = Label(self.entriesframe, text = val)
                L.grid(row=self.cursor.rowcount, column = col)
        self.scrollableFrame.update()
    def selectEntry(self):
        state = list (map(lambda var: var.get(), self.entryVarList))
        if sum(state) == 0:
            self.delete.config(state='disabled')
            self.edit.config(state='disabled')
        elif sum(state) == 1:
            self.delete.config(state='normal')
            self.edit.config(state='normal')
        else:
            self.delete.config(state='normal')
            self.edit.config(state='disabled')    
        if len(state) == sum(state):
            self.allCheck.set(1)
        else:
            self.allCheck.set(0)

def main():
    root = Tk()
    app = Scan(root)
    root.mainloop()

if __name__ == '__main__':
    main()

0 个答案:

没有答案
相关问题