2016-05-27 2 views
-1

Я пытаюсь сделать два окна ввода и кнопку «ОК», которая обрабатывает обе записи: Я не понимаю функцию init() или причину «self» должен быть включен в это. Я хочу получить доступ к элементам вне этого класса и mainloop. Записи должны быть строковыми.виджеты с несколькими элементами и один виджет кнопки в tkinter

from tkinter import * 
root = Tk() 
root.geometry("550x145+500+300") 

class myDose: 
    def __init__(self): 

     l1 = Label(text="Enter the prescription dose to three (3) decimal places [cGy]").pack() 
     e1 = Entry(root) 
     e1.pack() 

     l2 = Label(text="Save new excel file as...").pack() 
     e2 = Entry(root) 
     e2.pack() 

     l3 = Label(text="click 'OK', and then close window.").pack() 

     b = Button(root, text="OK", command=submit) 
     b.pack() 

    def submit(self): 
     print(e1.get()) 
     print(e2.get()) 

D = myDose() 
root.mainloop() 

#I want to access the entries, e1 and e2, outside the mainloop 
print(D.e1) 
print(D.e2) 
+0

От «вне главного окна», что означает «после разрушения окна». Вы знаете об этом? Или вы спрашиваете, как запустить код после 'mainloop', но с окном все еще видно? –

+0

Я написал функции выше этого класса. Они зависят от этой переменной e1. Вот почему я хочу получить номер входа пользователя 1. Ниже этого класса в моей программе у меня есть код, похожий на функцию main() (то есть, где мой код начинает запускаться), и это зависит от e2. – Michael

+0

Зависит ли они от e1 _widget_ или значения, введенного в виджет? –

ответ

1

Проблема в том, что mainloop не выходит до тех пор, пока не будет уничтожено корневое окно. Как только корневое окно будет уничтожено, вы больше не сможете обращаться к виджетам внутри корневого окна. Однако вы можете получить доступ к атрибутам без виджета объекта.

Если это то, что вы хотите - уничтожить окно и получить доступ к значениям в виджетах - вам нужно сохранить значения перед уничтожением окна.

Например, в вашем представить вы можете сохранить значения, как это:

def submit(self): 
    self.data = {"e1": self.e1.get(), "e2": self.e2.get()} 

После того, как окно будет уничтожен, вы все еще есть ссылка на объект приложения, так что вы можете получить доступ к не-виджет атрибуты класса:

... 
D = myDose(root) 
root.mainloop() 

print D.data["e1"] 
print D.data["e2"] 

на основе комментариев к первоначальному вопросу, вы говорите, что в коде вам необходимо использовать askopenfilename. если это так, вы должны пересмотреть необходимость запуска кода после mainloop. Tkinter предназначен для создания корневого окна, созданного ровно один раз, и для выхода программы сразу после выхода mainloop.

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

+0

это отлично. Вы знаете, что я имею в виду. – Michael

+0

@ Майкл. Пожалуйста, помните, что знание того, что вы имеете в виду, не эквивалентно согласию, что вы строите свою программу разумным образом. Я рекомендую исследовать приложения Tkinter - в частности, как получить доступ к модели данных с такими приложениями, чтобы вы могли правильно писать свою программу. Это упростит работу с вашим кодом позже. – TigerhawkT3

+0

@ TigerhawkT3, но он работает так, как я хочу ... – Michael

0

Ваш подход в корне ошибочен. mainloop() делает то, что он говорит: запускает цикл. Строки, которые следуют за ним, не будут выполняться до тех пор, пока этот цикл не закончится - это означает, что ваше приложение не будет закрыто. Поскольку у вас уже есть класс с Tkinter вещи в нем, просто закончить переход к ОО подхода:

from tkinter import * 

class myDose: 
    def __init__(self, root): 
     root.geometry("550x145+500+300") 

     self.l1 = Label(root, text="Enter the prescription dose to three (3) decimal places [cGy]") 
     self.l1.pack() 
     self.e1 = Entry(root) 
     self.e1.pack() 

     self.l2 = Label(root, text="Save new excel file as...") 
     self.l2.pack() 
     self.e2 = Entry(root) 
     self.e2.pack() 

     self.l3 = Label(root, text="click 'OK', and then close window.") 
     self.l3.pack() 

     self.b = Button(root, text="OK", command=self.submit) 
     self.b.pack() 

    def submit(self): 
     print(self.e1.get()) 
     print(self.e2.get()) 

root = Tk() 
D = myDose(root) 
root.mainloop() 

Я рекомендую посмотреть более подробно о том, как фундаментальные понятия, как объекты и классы работают до создания полного приложения с графическим интерфейсом.

+0

Что вы подразумеваете под подходом OO? Мне нужно получить доступ к этим записям ниже строки «root.mainloop», мой другой код зависит от получения этих значений @ TigerhawkT3 – Michael

+0

going print (D.e1) ниже root.mainloop дает мне некоторое случайное значение, например .6745325 – Michael

+0

@Michael Попробовал ли вы делать 'print (D.e1.get())' после 'root.mainloop()' в версии вашего скрипта TigerhawkT3? –

0

Вот быстрое решение.

Проблема с вашей версией и модифицированной версией TigerhawkT3 заключается в том, что при закрытии окна виджеты Entry больше не действительны, поэтому вам необходимо сохранить данные перед закрытием окна. Один из способов сделать это - подключить Tkinter StringVar s к виджетам Entry. Значения в StringVar s будут доступны после закрытия окна.

import tkinter as tk 

class myDose: 
    def __init__(self, root): 
     root.geometry("550x145+500+300") 

     l = tk.Label(root, text="Enter the prescription dose to three (3) decimal places [cGy]") 
     l.pack() 
     self.dosage = tk.StringVar() 
     e = tk.Entry(root, textvariable=self.dosage) 
     e.pack() 

     l = tk.Label(root, text="Save new excel file as...") 
     l.pack() 
     self.savename = tk.StringVar() 
     e = tk.Entry(root, textvariable=self.savename) 
     e.pack() 

     l = tk.Label(root, text="Enter the data and then close window.") 
     l.pack() 

     root.mainloop() 

D = myDose(tk.Tk()) 

print(D.dosage.get()) 
print(D.savename.get()) 

Обратите внимание, что я изменил заявление import. Это намного чище, чтобы не сделать

from tkinter import * 

, что и загромождает пространство имен с более чем 100 имен, что приводит к потенциальным коллизий имен.


__init__() функция представляет собой метод myDose класса. Метод класса __init__() вызывается, когда создается экземпляр этого класса. В своем коде, что происходит, когда вы делаете

D = myDose() 

В моей версии это, когда эта линия выполнена:

D = myDose(tk.Tk()) 

который первым создает окно Tkinter корень, который затем передается myDose; это корневое окно затем доступно для моего __init__() как его аргумент root.

В классе используется имя self, чтобы ссылаться на текущий экземпляр класса. Вне класса нам нужно использовать фактическое имя, которому мы присвоили экземпляр, который в этом случае равен D.

+0

Когда вы говорите «проблема с более ранней версией», о чем «более ранняя версия» вы говорите? Ответы могут быть в другом порядке, чем при написании ответа. Вы имеете в виду версию в вопросе или в одном из других ответов? Можете ли вы быть более конкретным в своем ответе? –