我正在构建一个GUI,该GUI需要我通过ssh登录到远程计算机。我正在使用paramiko来做到这一点。
我想要实现的是启动应用程序时显示一个登录窗口。用户必须输入一些凭证。如果登录成功,则显示应用程序的主窗口。如果登录失败,请保留在登录窗口。
如果登录成功,我希望将ssh_client对象传递给MainWindow类,以便可以使用已建立的连接在远程计算机上执行任务。但是,如何将ssh_client对象传递给MainWindow?
以下代码将运行,但不会尝试使用已建立的ssh_client。要如何在MainWindow的Login中使用ssh_client?
也许我应该只在MainWindow中重新建立连接-然后我需要将凭据传递给MainWindow,这似乎是我现在遇到的同类问题。
import Tkinter as tk
import paramiko
import time
class Application(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.grid(row=0, column=0, sticky="nsew")
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (Login, MainWindow):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(Login)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class Login(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.ssh_client = paramiko.SSHClient()
self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.parent = parent
self.controller = controller
self.grid(row=0, column=0)
self.user = tk.StringVar()
self.user.set("my_username") # Default user
self.host_options = ["host1", "host2"]
self.host = tk.StringVar()
self.host.set(self.host_options[0]) # Default hostname
l_user = tk.Label(self, text="Username: ")
l_user.grid(row=0, column=0, sticky=tk.E)
self.entry_user = tk.Entry(self)
self.entry_user.grid(row=0, column=1, sticky=tk.W)
self.entry_user.insert(0, self.user.get())
l_pwd = tk.Label(self, text="Password: ")
l_pwd.grid(row=1, column=0, sticky=tk.E)
self.entry_pwd = tk.Entry(self, show="*")
self.entry_pwd.grid(row=1, column=1, sticky=tk.W)
l_host = tk.Label(self, text="Hostname: ")
l_host.grid(row=2, column=0, sticky=tk.E)
optionmenu_host = tk.OptionMenu(self, self.host, *self.host_options)
optionmenu_host.grid(row=2, column=1, sticky=tk.W)
b_login = tk.Button(self, text="Log in", command=self.authorize)
b_login.grid(row=3, column=0, sticky=tk.W)
b_quit = tk.Button(self, text="Quit", command=self.parent.destroy)
b_quit.grid(row=4, column=0, sticky=tk.W)
def authorize(self):
try:
self.ssh_client.connect(hostname=self.host.get(), username=self.entry_user.get(), password=self.entry_pwd.get())
self.controller.show_frame(MainWindow)
except paramiko.AuthenticationException:
l_error = tk.Label(self, text="Login failed...", fg="red")
l_error.grid(row=4, column=1, sticky=tk.W)
l_error.after(2000, l_error.destroy)
class MainWindow(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.grid(row=0, column=0)
l = tk.Label(self, text="Log in was successful!")
l.grid(row=0, column=0, sticky=tk.W)
###################################
# run application
if __name__ == "__main__":
app = Application()
app.mainloop()
###################################
答案 0 :(得分:0)
这就是我的意思,还有其他一些改进:
self.master = master
,因此您不需要该行。 我无法对此进行测试,所以请告诉我它是如何工作的。
import Tkinter as tk
import paramiko
import time
class Application(tk.Tk):
def __init__(self, **kwargs):
tk.Tk.__init__(self, **kwargs)
self.ssh_client = paramiko.SSHClient()
self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.login_window = Login(self)
self.main_window = MainWindow(self)
self.show_login() # set starting point
def show_login(self):
self.main_window.pack_forget()
self.login_window.pack()
def show_main(self):
self.login_window.pack_forget()
self.main_window.pack()
class Login(tk.Frame):
def __init__(self, parent, **kwargs):
tk.Frame.__init__(self, parent, **kwargs)
self.user = tk.StringVar()
self.user.set("my_username") # Default user
self.host_options = ["host1", "host2"]
self.host = tk.StringVar()
self.host.set(self.host_options[0]) # Default hostname
l_user = tk.Label(self, text="Username: ")
l_user.grid(row=0, column=0, sticky=tk.E)
self.entry_user = tk.Entry(self)
self.entry_user.grid(row=0, column=1, sticky=tk.W)
self.entry_user.insert(0, self.user.get())
l_pwd = tk.Label(self, text="Password: ")
l_pwd.grid(row=1, column=0, sticky=tk.E)
self.entry_pwd = tk.Entry(self, show="*")
self.entry_pwd.grid(row=1, column=1, sticky=tk.W)
l_host = tk.Label(self, text="Hostname: ")
l_host.grid(row=2, column=0, sticky=tk.E)
optionmenu_host = tk.OptionMenu(self, self.host, *self.host_options)
optionmenu_host.grid(row=2, column=1, sticky=tk.W)
b_login = tk.Button(self, text="Log in", command=self.authorize)
b_login.grid(row=3, column=0, sticky=tk.W)
b_quit = tk.Button(self, text="Quit", command=self.quit)
b_quit.grid(row=4, column=0, sticky=tk.W)
def authorize(self):
try:
self.master.ssh_client.connect(hostname=self.host.get(), username=self.entry_user.get(), password=self.entry_pwd.get())
self.master.show_main()
except paramiko.AuthenticationException:
l_error = tk.Label(self, text="Login failed...", fg="red")
l_error.grid(row=4, column=1, sticky=tk.W)
l_error.after(2000, l_error.destroy)
class MainWindow(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
l = tk.Label(self, text="Log in was successful!")
l.grid(row=0, column=0, sticky=tk.W)
# you can use the ssh client like this:
print(self.master.ssh_client)
# or like this:
self.ssh_client = self.master.ssh_client
print(self.ssh_client)
###################################
# run application
if __name__ == "__main__":
app = Application()
app.mainloop()
###################################