У меня есть следующее приложение Tkinter, которое в основном помогает вам настроить новую сеть, просто вставив в поле ввода новое значение. Это значение, введенное пользователем, сохраняется где-то в файле с использованием шаблона. Этот сценарий работает хорошо, но проблема в том, что я вижу поле ввода Арендатора, а не окно "Имя сетевого имени". То же самое происходит с их ярлыками. Затем, когда мы нажимаем на Add Network и получаем еще 2 окна ввода, отображаются очень странно.
Как я могу выровнять метки + поля ввода и как я могу отобразить каждую группу ярлыков + поле ввода один ниже другого?
Что-то вроде:
Арендатор [entrybox] Сеть [входная]
Арендатор [entrybox] Сеть [входная]
....................................
import Tkinter as tk
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.networks = []
self.switch_frame(StartPage)
def switch_frame(self, frame_class):
"""Destroys current frame and replaces it with a new one."""
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
start_label = tk.Label(self, text="This is the start page")
network_button = tk.Button(self, text="Create the networks", command=lambda: master.switch_frame(Networks))
start_label.pack(side="top", fill="x", pady=10)
deployment_button.pack()
network_button.pack()
subnet_button.pack()
neutronports_button.pack()
script_button.pack()
class Networks(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.entries=[]
self.create_widgets(master)
def create_widgets(self, master):
label = tk.Label(self, text="Insert the name of the networks")
start_button = tk.Button(self, text="Return to start page", command=lambda: master.switch_frame(StartPage))
new_network_button = tk.Button(self, text="Add network", command=self.add_network)
new_network_button.bind("<Return>", self.add_network)
new_network_button.grid(row=len(self.master.networks), column=3, padx=4, pady=6, sticky="W")
next_button=tk.Button(self, text="Submit", command=self.networks)
next_button.grid(row=1500, column=5,padx=4, pady=6, sticky="W")
label.pack(side="top", fill="x", pady=10)
start_button.pack()
new_network_button.pack()
next_button.pack()
for index, network in enumerate(self.master.networks):
self.render_network_field(network, index)
def add_network(self):
requirements={'variable': tk.StringVar(self.master), 'cloudvariable': tk.StringVar(self.master)}
if requirements:
self.master.networks.append(requirements)
self.master.switch_frame(Networks)
else:
tkMessageBox.showerror("tk", "No networks defined!")
self.master.switch_frame(Networks)
def render_network_field(self, network, index):
labelText=tk.StringVar()
labelText.set("Tenant name")
labelDir=tk.Label(self,textvariable=labelText, height=4)
labelDir.pack(side="top")
nw_entry_field = tk.Entry(self, textvariable=network['variable'])
nw_entry_field.grid(row=index, column=0, columnspan=2, padx=4, pady=6, sticky="NEWS")
nw_entry_field.pack(side="right")
labelText=tk.StringVar()
labelText.set("Network name")
labelDir=tk.Label(self,textvariable=labelText, height=4)
labelDir.pack(side="top")
cloud_entry_field = tk.Entry(self, textvariable=network['cloudvariable'])
cloud_entry_field.grid(row=index, column=0, columnspan=2, padx=4, pady=6, sticky="NEWS")
cloud_entry_field.pack(side="right")
self.entries.append((network['cloudvariable'],network['variable']))
def networks(self):
with open("/home/dante/networks.yml", "w") as f:
f.write("--- #" + "\n")
for ent, cloudent in self.entries:
network_value=ent.get()
cloud_value=cloudent.get()
if network_value:
if cloud_value:
f.write("- { cloud: "+cloud_value+", network: "+network_value+ " }"+ "\n")
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
Ниже приведен простой код, который я только что решил решить вашу проблему. Вам просто нужно поместить функцию register() в свой класс, которая выполняется, когда вы нажимаете кнопку регистрации (помещаете ее в один класс).
import tkinter as tk
from tkinter import *
def register():
username = x1.get()
password = y1.get()
if username!="" and password=="":
file = open("accountfile.txt","a")
file.write(username)
file.write(" ")
file.write(password)
file.write("\n")
file.close()
root=Tk()
# String variables
x1=StringVar()
y1=StringVar()
Us=Entry(root,textvariable=x1)
Us.grid()
Ps=Entry(root, textvariable=y1)
Ps.grid()
Reg=Button(root,text="Register",command=lambda:register())
Reg.grid()
root.mainloop()
Редактировать:
Чтобы решить вашу ошибку, сделайте глобальную переменную sa. Это определит s для всех блоков кода в файле. Кроме того, вы можете установить для него новое значение, а затем использовать новое значение в другом месте
global s
s=""
def networks(self):
with open("/home/dante/networks.yml", "w") as f:
f.write("--- #" + "\n")
f.write("networks:" + "\n")
for ent in s:
if ent:
f.write("- { cloud: cloud1, network: "+str(ent)+ " }"+ "\n")
def render_network_field(self, network, index):
entry_field = tk.Entry(self, textvariable=network['variable'])
entry_field.grid(row=index, column=0, columnspan=2, padx=4, pady=6, sticky="NEWS")
entry_field.pack()
global s
s=entry_field.get()
Надеюсь это поможет
controller
дляButton
, но этот виджет не имеет опциюcontroller
. Как вы думаете, что собирается сделатьButton(..., controller=self)
?controller=
при создании одной из ваших кнопок, я думаю, вы хотели использоватьcommand=
:button1 = tk.Button(self, text="Next", controller=self.networks