2016-01-07 7 views
1

Я совершенно новичок в Python, и я работаю над следующим кодом, который я сделал с большой помощью другого пользователя stackflow.Как отобразить переменную в окне tkinter?

После запуска сценария откроется окно tkinter, в котором вы можете выбрать файл gcode (это файл со многими строками инструкций для 3D-принтера), а затем будет найдено определенное значение из этого файла.

То, что я хотел бы достичь заключается в следующем:

1) Отобразить это значение под кнопкой загрузки GCode в окне Tkinter с описанием/этикетке.

2) Произведите вычисления в этом значении и покажите их в окне tkinter.

3) Finaly сделать исполняемый файл этого сценария, чтобы каждый мог его использовать, даже без установленного Python.

Я не уверен, что это очень просто, или это большая работа, поскольку я совершенно новичок в Python (и не очень хорош в программировании в целом). Надеюсь, я достаточно хорошо объяснил ситуацию и благодарю вас за любой вклад!

GCode файл для тестирования кода: GCODE FILE

Finaly код:

from tkinter import * 
import re 
from tkinter import messagebox 
from tkinter import filedialog 

# Here, we are creating our class, Window, and inheriting from the Frame 
# class. Frame is a class from the tkinter module. (see Lib/tkinter/__init__) 
class Window(Frame): 

    # Define settings upon initialization. Here you can specify 
    def __init__(self, master=None): 

     # parameters that you want to send through the Frame class. 
     Frame.__init__(self, master) 

     #reference to the master widget, which is the tk window     
     self.master = master 

     #with that, we want to then run init_window, which doesn't yet exist 
     self.init_window() 

    # Load the gcode file in and extract the filament value 
    def get_filament_value(self, fileName): 
     with open(fileName, 'r') as f_gcode: 
      data = f_gcode.read() 
      re_value = re.search('filament used = .*? \(([0-9.]+)', data) 

      if re_value: 
       value = float(re_value.group(1)) 
       return('Volume of the print is {} cm3'.format(value)) 
      else: 
       value = 0.0 
       return('Filament volume was not found in {}'.format(fileName)) 
     return value 

    def read_gcode(self): 
     root.fileName = filedialog.askopenfilename(filetypes = (("GCODE files", "*.gcode"), ("All files", "*.*"))) 
     self.value.set = self.get_filament_value(root.fileName) 
#  self.value.set('Button pressed') 

    def client_exit(self): 
     exit() 

    def about_popup(self): 
     messagebox.showinfo("About", "Small software created by Bartosz Domagalski to find used filament parameters from Sli3er generated GCODE") 

    #Creation of init_window 
    def init_window(self): 

     # changing the title of our master widget  
     self.master.title("Filament Data") 

     # allowing the widget to take the full space of the root window 
     self.pack(fill=BOTH, expand=1) 

     # creating a menu instance 
     menu = Menu(self.master) 
     self.master.config(menu=menu) 

     # create the file object) 
     file = Menu(menu) 
     help = Menu(menu) 

     # adds a command to the menu option, calling it exit, and the 
     # command it runs on event is client_exit 
     file.add_command(label="Exit", command=self.client_exit) 
     help.add_command(label="About", command=self.about_popup) 

     #added "file" to our menu 
     menu.add_cascade(label="File", menu=file) 
     menu.add_cascade(label="Help", menu=help) 


     #Creating the labels 
     self.value = StringVar() 
     l_instruction = Label(self, justify=CENTER, compound=TOP, text="Load GCODE file to find volume, \n weight and price of used filament.") 
     l = Label(self, justify=CENTER, compound=BOTTOM, textvariable=self.value) 
#  l.place(x=85, y=45) 
     l_instruction.pack() 
     l.pack() 

     #Creating the button 
     gcodeButton = Button(self, text="Load GCODE", command=self.read_gcode) 
     gcodeButton.pack() 
#  gcodeButton.place(x=140, y=10) 

     #status Bar 
     status = Label(self, text="Waiting for file...", bd=1, relief=SUNKEN, anchor=W) 
     status.pack(side=BOTTOM, fill=X) 

# root window created. Here, that would be the only window, but you can later have windows within windows. 
root = Tk() 
root.resizable(width=False,height=False); 
root.geometry("220x300") 


#creation of an instance 
app = Window(root) 

#mainloop 
root.mainloop() 

ответ

0

Вы должны поместить Label(s) внутри той же Frame, как у вас есть кнопки. И когда я скопировал код, мне пришлось импортировать модуль filedalog (from tkinter import filedalog), импорт звездочки, похоже, не покрыл его.

Вы можете использовать переменную StringVar() (от tkinter) и назначить ее этикетке. Эта переменная вы можете указать .set() и .get(). Создать переменную и присвоить ей ярлык:

self.value = StringVar('', value=" Load GCODE file to find volume, \n weight and price of used filament.") 
l = Label(self, textvariable=self.value) 

Alter значение переменной:

self.value.set(self.get_filament_value(root.fileName)) 

Этикетка вы будете размещать, как вы хотите, как вы сделали с помощью кнопки с quitButton.place. Существуют и другие способы обработки макета, сетки и пакета. Но, насколько мне известно, рекомендуется выбрать один стиль макета для всех элементов.

Создание исполняемого файла, «замораживание» вашего кода, является более широкой темой. Возьмите look here для некоторых опций, на которые вы можете больше смотреть.


редактировать:

Обновленный рабочий код. Изменение размещения виджетов вы выясните;) Не смотрели на какие-либо новые элементы в вашем коде.

from tkinter import * 
import re 
from tkinter import messagebox, filedialog 


# Here, we are creating our class, Window, and inheriting from the Frame 
# class. Frame is a class from the tkinter module. (see Lib/tkinter/__init__) 
class Window(Frame): 
    # Define settings upon initialization. Here you can specify 
    def __init__(self, master=None): 

     # parameters that you want to send through the Frame class. 
     Frame.__init__(self, master) 

     # reference to the master widget, which is the tk window 
     self.master = master 

     # with that, we want to then run init_window, which doesn't yet exist 
     self.init_window() 

    # Load the gcode file in and extract the filament value 
    def get_filament_value(self, fileName): 
     with open(fileName, 'r') as f_gcode: 
      data = f_gcode.read() 
      re_value = re.search('filament used = .*? \(([0-9.]+)', data) 

      if re_value: 
       value = float(re_value.group(1)) 
       return 'Volume of the print is {} cm3'.format(value) 
      else: 
       return 'Filament volume was not found in {}'.format(fileName) 

    def read_gcode(self): 
     root.fileName = filedialog.askopenfilename(filetypes=(("GCODE files", "*.gcode"), ("All files", "*.*"))) 
     self.value.set(self.get_filament_value(root.fileName)) 

    def client_exit(self): 
     exit() 

    def about_popup(self): 
     messagebox.showinfo("About", 
          "Small software created by Bartosz Domagalski to find used filament parameters from Sli3er generated GCODE") 

    # Creation of init_window 
    def init_window(self): 

     # changing the title of our master widget 
     self.master.title("Filament Data") 

     # allowing the widget to take the full space of the root window 
     self.pack(fill=BOTH, expand=1) 

     # creating a menu instance 
     menu = Menu(self.master) 
     self.master.config(menu=menu) 

     # create the file object) 
     file = Menu(menu) 
     help = Menu(menu) 

     # adds a command to the menu option, calling it exit, and the 
     # command it runs on event is client_exit 
     file.add_command(label="Exit", command=self.client_exit) 
     help.add_command(label="About", command=self.about_popup) 

     # added "file" to our menu 
     menu.add_cascade(label="File", menu=file) 
     menu.add_cascade(label="Help", menu=help) 

     # Creating the labels 
     self.value = StringVar() 
     l_instruction = Label(self, justify=CENTER, compound=TOP, 
           text=" Load GCODE file to find volume, \n weight and price of used filament.") 
     l = Label(self, justify=CENTER, compound=BOTTOM, textvariable=self.value) 
     #  l.place(x=85, y=45) 
     l_instruction.pack() 
     l.pack() 

     l_instruction.pack() 
     self.value = StringVar() 
     l = Label(self, textvariable=self.value) 
     l.pack() 

     # Creating the button 
     gcodeButton = Button(self, text="Load GCODE", command=self.read_gcode) 
     gcodeButton.pack() 
     #  gcodeButton.place(x=140, y=10) 

     # status Bar 
     status = Label(self, text="Waiting for file...", bd=1, relief=SUNKEN, anchor=W) 
     status.pack(side=BOTTOM, fill=X) 


# root window created. Here, that would be the only window, but you can later have windows within windows. 
root = Tk() 
root.resizable(width=False, height=False); 
# root.geometry("400x300") 


# creation of an instance 
app = Window(root) 

# mainloop 
root.mainloop() 
+0

Привет, спасибо за ответ, я попытался реализовать его, как вы предлагаете, но без хороших результатов (я обновил код в главном вопросе). Я не уверен в этом модуле filedalog, как при компиляции, у меня нет подсказок об этом. Спасибо также за ссылку, которую я посмотрю на нее после того, как код будет готов. – Bart

+0

Я заметил, что у меня была опечатка на ярлыке, в качестве родительского вместо root. Исправлено.Также добавлено, как это выглядит, когда вы вставляете свой код. –

+0

Хорошо, я медленно понимаю это. Итак, ваш пример с жестко закодированным сообщением «кнопка нажата». Но все же я не могу отобразить мое значение, найденное в файле gcode. Кроме того, я понял, что таким образом новое сообщение («кнопка нажата» в вашем примере) отображается поверх метки и эта метка исчезает. Я хотел бы добиться того, что после загрузки gcode в значение отображается в окне tkinter под кнопкой, а не вместо метки. Я надеюсь, что мои объяснения достаточно ясны;) – Bart