2017-02-22 36 views
0

Я собираюсь начать новый проект Python3/tkinter, и я хочу убедиться, что получаю как можно больше кода. Я создаю приложение, которое будет иметь, на данный момент, одно окно состоит из 3-х областей:в Python3/tkinter можно создать панель инструментов в отдельный класс, но все же разрешить ей взаимодействовать с основным приложением?

  • Toolbar
  • центр/главная площадь
  • Statusbar

Я пытаюсь сохранить основной класс приложения как можно более чистый, разгружая код другим вспомогательным классам. Итак, следуя некоторым учебным пособиям и адаптировавшись к тому, что я делал до сих пор, я уже смог установить внешний класс панели инструментов, который можно изменить по требованию, из основного приложения. Теперь я пытаюсь создать класс для панели инструментов, но я боюсь, что будет невозможно создать кнопки и их соответствующие обратные вызовы в отдельном классе, так как я не знаю, как заставить их вызывать функции, которые в главном приложении. Возможно ли это?

Это то, что я получил прямо сейчас:

#!/usr/bin/python3 

from tkinter import * 
from tkinter import ttk 


class App: 
    """ main class for the application """ 
    def __init__(self,master): 
     mainframe = ttk.Frame(master) 
     topframe = ttk.Frame(mainframe) 
     centerframe = ttk.Frame(mainframe) 
     bottomframe = ttk.Frame(mainframe) 

     my_toolbar = Toolbar(topframe) 

     my_statusbar = StatusBar(mainframe) 
     my_statusbar.set("This is the statusbar") 

     centerlabel = ttk.Label(centerframe, text="Center stuff goes here") 
     centerlabel.pack() 

     topframe.pack(side=TOP, fill=X) 
     centerframe.pack(side=TOP, fill=BOTH) 
     bottomframe.pack(side=BOTTOM, fill=X)   
     mainframe.pack(side=TOP, expand=True, fill=BOTH) 


    def button_function(self, *event): 
     print("filter") 


class StatusBar(ttk.Frame): 
    """ Simple Status Bar class - based on Frame """ 
    def __init__(self,master): 
     ttk.Frame.__init__(self,master) 
     self.label = ttk.Label(self,anchor=W) 
     self.label.pack() 
     self.pack(side=BOTTOM, fill=X) 

    def set(self,texto): 
     self.label.config(text=texto) 
     self.label.update_idletasks() 
    def clear(self): 
     self.label.config(text="") 
     self.label.update_idletasks() 


class Toolbar: 
    """ Toolbar """ 
    def button_one(self): 
     print("button 1 pressed") 

    def button_two(self): 
     print("button 2 pressed") 

    def __init__(self,master): 
     self.button1 = ttk.Button(master,text="One",command=self.button_one()) 
     self.button2 = ttk.Button(master,text="Two",command=self.button_two()) 
     self.button1.grid(row=0,column=0) 
     self.button2.grid(row=0,column=1) 


if __name__ == "__main__": 
    root = Tk() 
    app = App(root) 
    root.mainloop() 

Допустим, что мне нужно сделать, чтобы вызвать button1button_function() для того, чтобы обновить некоторую информацию показывается там. Должен ли я просто перемещать панель инструментов в класс App, например, в методе класса, называемом из его __init__()? Или есть лучший способ?

Возможно, я должен добавить, что позже я добавлю некоторые окна Toplevel, которые, вероятно, могут использовать некоторые из этих общих классов. Я хочу хорошо проложить дорогу.

ответ

1

Это, безусловно, возможно. Здесь есть две возможности. Первый, чтобы приложение наследовалось от ttk.Frame вместо использования мэйнфрейма. Затем вы можете передать приложение в качестве ведущего на панели инструментов и т.д. Вот код переделан:

#!/usr/bin/python3 

import tkinter as tk 
from tkinter import ttk 


class App(ttk.Frame): 
    """ main class for the application """ 
    def __init__(self,master,*args,**kwargs): 
     super().__init__(master,*args,**kwargs) 


     self.my_toolbar = Toolbar(self) 

     self.my_statusbar = StatusBar(self) 
     self.my_statusbar.set("This is the statusbar") 

     self.centerframe = CenterFrame(self) 

     self.pack(side=tk.TOP, expand=True, fill=tk.BOTH) 


    def button_function(self, *event): 
     print("filter") 


class CenterFrame(ttk.Frame): 

    def __init__(self,master,*args,**kwargs): 
     super().__init__(master,*args,**kwargs) 
     self.master = master 
     self.pack(side=tk.BOTTOM, fill=tk.X) 
     self.centerlabel = ttk.Label(self, text="Center stuff goes here") 
     self.centerlabel.pack() 


class StatusBar(ttk.Frame): 
    """ Simple Status Bar class - based on Frame """ 
    def __init__(self,master): 
     ttk.Frame.__init__(self,master) 
     self.master = master 
     self.label = ttk.Label(self,anchor=tk.W) 
     self.label.pack() 
     self.pack(side=tk.BOTTOM, fill=tk.X) 

    def set(self,texto): 
     self.label.config(text=texto) 
     self.label.update_idletasks() 
    def clear(self): 
     self.label.config(text="") 
     self.label.update_idletasks() 


class Toolbar(ttk.Frame): 
    """ Toolbar """ 
    def button_one(self): 
     print("button 1 pressed") 

    def button_two(self): 
     print("button 2 pressed") 
     self.master.button_function() 

    def __init__(self,master): 
     super().__init__(master) 
     self.master = master 
     self.pack(side=tk.TOP, fill=tk.X) 
     self.button1 = ttk.Button(self,text="One",command=self.button_one) 
     self.button2 = ttk.Button(self,text="Two",command=self.button_two) 
     self.button1.grid(row=0,column=0) 
     self.button2.grid(row=0,column=1) 


if __name__ == "__main__": 
    root = tk.Tk() 
    app = App(root) 
    root.mainloop() 

Второй является просто передать приложение в качестве аргумента к другим классам.

1

Вам не хватает self., назначение команд кнопкам не требуется, и после этого вы можете вызвать конфигурацию кнопок из любой точки вашей программы. Таким образом, для команды button1 это будет:

app.my_toolbar.button1.config(command=app.button_function) 

Я фиксируя ваши ошибки, как есть, не сделать программу лучше:

#!/usr/bin/python3 

from tkinter import * 
from tkinter import ttk 


class App: 
    """ main class for the application """ 
    def __init__(self,master): 
     self.mainframe = ttk.Frame(master) 
     self.topframe = ttk.Frame(self.mainframe) 
     self.centerframe = ttk.Frame(self.mainframe) 
     self.bottomframe = ttk.Frame(self.mainframe) 

     self.my_toolbar = Toolbar(self.topframe) 

     self.my_statusbar = StatusBar(self.mainframe) 
     self.my_statusbar.set("This is the statusbar") 

     self.centerlabel = ttk.Label(self.centerframe, text="Center stuff goes here") 
     self.centerlabel.pack() 

     self.topframe.pack(side=TOP, fill=X) 
     self.centerframe.pack(side=TOP, fill=BOTH) 
     self.bottomframe.pack(side=BOTTOM, fill=X) 
     self.mainframe.pack(side=TOP, expand=True, fill=BOTH) 


    def button_function(self, *event): 
     print("filter") 


class StatusBar(ttk.Frame): 
    """ Simple Status Bar class - based on Frame """ 
    def __init__(self,master): 
     ttk.Frame.__init__(self,master) 
     self.label = ttk.Label(self,anchor=W) 
     self.label.pack() 
     self.pack(side=BOTTOM, fill=X) 

    def set(self,texto): 
     self.label.config(text=texto) 
     self.label.update_idletasks() 
    def clear(self): 
     self.label.config(text="") 
     self.label.update_idletasks() 


class Toolbar: 
    """ Toolbar """ 
    def button_one(self): 
     print("button 1 pressed") 

    def button_two(self): 
     print("button 2 pressed") 

    def __init__(self,master): 
     self.button1 = ttk.Button(master,text="One",command=self.button_one) 
     self.button2 = ttk.Button(master,text="Two",command=self.button_two) 
     self.button1.grid(row=0,column=0) 
     self.button2.grid(row=0,column=1) 


if __name__ == "__main__": 
    root = Tk() 
    app = App(root) 

    app.my_toolbar.button1.config(command=app.button_function) 

    root.mainloop()