1

だから私はtkinterでいくつかの基本的なGUIを作ろうとしてきました(Tkinterと混同しないでください)、私は解決策がわからず、全能のGoogleで実際に何も見つけることができない問題に遭遇しました...私のPC上のディレクトリのテーブルを備えた小さなSQLiteデータベース。すべてのディレクトリパスをラベルに描画し、そのラベルの横に「rempve」ボタンを追加したいと思います。このボタンは、データベースからディレクトリを削除し、GUI からも削除できる必要があります。データベースにディレクトリを追加できる「追加」ボタンもあり、この新しいディレクトリは GUI に表示されます。これは私の基本的なレイアウトです:

---------------
| ADD         |
|dir1   REMOVE|
|dir2   REMOVE|
---------------

ボタンとラベルを表示するには gridlayout を使用します。ほとんどのものは機能し、データベース関連のものはすべて機能します。また、GUI を起動すると、現在のディレクトリと「削除」ボタンが適切に表示されます。しかし...「削除」ボタンを使用すると、データベースに存在しなくなってもディレクトリがGUIから消えません。もちろん、GUIを再起動すると修正されます。ラベルを追加することはできます...しかし、正しく行っているかどうかはわかりません...
新しい情報でGUIを「再描画」するにはどうすればよいですか? これは、GUI の私のコードです。

class GUI():

def __init__(self,db):
    self.root = Tk()
    self.root.title("Example")
    self.frame = ttk.Frame(self.root, padding="3 3 12 12")
    self.frame.rowconfigure(5, weight=1)
    self.frame.columnconfigure(5, weight=1)
    self.frame.grid(sticky=W+E+N+S)

    lbl = ttk.Label(self.frame, text="", width=17)
    lbl.grid(row=0, column=2, sticky=W)
    ttk.Button(self.frame, text="Add directory", command=lambda:self.load_file(db), width=30).grid(row=0, column=0, sticky=W, padx=(500,50))
    ttk.Button(self.frame, text="Sort files", command=lambda:self.sort(db,lbl), width=17).grid(row=0, column=1, sticky=W)
    self.draw(db)
    self.root.mainloop()

def load_file(self,db):
    fname = filedialog.askdirectory()
    db.addPath(fname)
    self.draw(db)

def remove_dir(self,db,pid):
    db.removePath(pid)
    self.draw(db)

def sort(self,db,lbl):
    lbl['text'] = 'Sorting...'
    sortFiles.moveFiles(db)
    lbl['text'] = 'Done!'


def draw(self,db):
    i = 0
    paths = db.getPaths()
    for path in paths:
        ttk.Label(self.frame,text=path[1]).grid(row=1+i,column=0,sticky=W)
        ttk.Button(self.frame, text="Remove directory", command=lambda:self.remove_dir(db,path[0]), width=17).grid(row=1+i,column=1, sticky=E)
        i = i+1
    for child in self.frame.winfo_children(): child.grid_configure(padx=5, pady=5)
    if i == 0:
        ttk.Label(self.root,text='No directories added yet').grid(row=1,column=0,sticky=W)
4

1 に答える 1

4

何かを追加または削除するたびに GUI を再描画したい場合は、新しいウィジェットを作成する前に古いウィジェットを破棄する必要があります。例えば:

def draw(self, db):
    # first, delete any existing widgets
    for child in self.frame.winfo_children():
        child.destroy()
    # next, redraw all the widgets
    paths = db.getPaths()
for path in paths:
        ...

別のバグがあります。これは、ラムダの使用方法です。問題のコードのとおり、すべてのコールバックで同じ値が表示されます。値をラムダへのキーワード引数として指定することで、正しい値が得られます:

ttk.Button(..., command=lambda p=path[0]:self.remove_dir(db, p)...)

実際の問題とは関係ありませんが、うろうろする必要はないと思いますdb。単一のデータベースのみを使用すると仮定すると、コンストラクターで行うことをお勧めself.db = dbしますGUI。これにより、メソッド シグネチャが簡素化されるため、コードの保守が少し簡単になります。

最後に、1 つの項目を削除するときに GUI を完全に再描画する必要はありません。一度に削除できるラベルとボタンは 1 つだけです。これには、プログラムでデータをどのように管理するかについて、もう少し時間をかけて考える必要があります。たとえば、各ラベルとボタンへの参照を保持している場合は、データベースからパスを削除するときに削除できます。関数removeDirは次のようになります。

def removeDir(self, pid):
    label, button = self.widgets(pid)
    label.destroy()
    button.destroy()
于 2012-10-19T16:51:20.530 に答える