我正在尝试创建一个tkinter GUI,该GUI实际上将用作到远程linux计算机的SSH连接。 GUI必须在Windows操作系统上可以运行。 GUI有几个按钮,允许用户启动和停止linux计算机上的程序,但是我在从此远程程序向tkinter打印连续输出时遇到问题。我本质上希望在tkinter GUI中有一个嵌入式窗口,该窗口显示远程桌面的命令行输出。
在下面的代码中,我成功调用了我的GUI类并构建了tkinter GUI。使用paramiko,我可以成功建立SSH连接,但是问题是当我按下“启动脚本”时。启动脚本通过SSH连接成功启动了该程序,但是我无法在GUI上打印连续的输出(要测试这一点,main_script.py是一个基本程序,每3秒只会输出一个递增的数字)。我相信问题是我拖延了tkinter主循环,但是我不知道如何解决这个问题。延迟后,我可以使用tkinter.after命令更新窗口,但是由于我读取stdout的方式,我的脚本仍然停滞。有没有更好的方法来读取stdout?我是否需要调用子进程或使用多线程(如果是这样,当main_window打开时我想建立SSH连接时该怎么做)。还是我错过了一种简单得多的方法,该方法实际上具有带有几个GUI按钮的远程桌面命令行输出?感谢您的帮助。
import paramiko
import tkinter as tk
class main_window():
def __init__(self, root2, ip, user, pword):
self.root2 = root2
# Connection Label
conn_label = tk.Label(root2, text=str('CONNECTED TO: ' + user + ' ' + 'ON: ' + ip))
conn_label.grid(row=0, columnspan=6, sticky=tk.W)
# Frequency Entery
freq_label = tk.Label(root2, text='Tag Frequency:')
freq_entry = tk.Entry(root2)
self.freq_enter_button = tk.Button(root2, text='Enter')
freq_label.grid(row=1, column=1, sticky=tk.E, padx=(5, 0))
freq_entry.grid(row=1, column=2, sticky=tk.W)
self.freq_enter_button.grid(row=1, column=3, padx=5)
# Scroll Bar and Command Line Ouput
self.scrollbar = tk.Scrollbar(root2)
self.scrollbar.grid(row=3, column=5, rowspan=1, sticky=tk.N+tk.S)
self.mylist = tk.Listbox(root2, yscrollcommand=self.scrollbar.set)
self.mylist.grid(row=3, column=0, columnspan=5, sticky=tk.W+tk.E+tk.N+tk.S)
# SSH Connection
self.ssh = paramiko.SSHClient()
self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.ssh.connect(ip, port=22, username=user, password=pword)
# stdin, stdout, stderr = ssh.exec_command('ls')
# for line in stdout:
# mylist.insert(tk.END, str('... ' + line.strip('\n')))
# ssh.close()
# Start Script Button
self.script_btn = tk.Button(root2, text="Start Script", command=self.toggle)
self.script_btn.grid(row=2, column=1, columnspan=3, sticky=tk.W+tk.E, padx=(10, 8), pady=2)
# Customize Grid Expansion
root2.columnconfigure(0, weight=1)
root2.columnconfigure(4, weight=1)
root2.rowconfigure(3, weight=1)
# Visual Touches
root2.title("Terminal Connection")
root2.wm_iconbitmap('logo_blue.ico')
def toggle(self):
def_color = self.freq_enter_button.cget('bg')
if self.script_btn.config('text')[-1] == 'Start Script':
stdin, self.stdout, stderr = self.ssh.exec_command('python main_script.py', get_pty=True)
self.mylist.insert(tk.END, str('Starting Script\n'))
self.script_btn.config(text='End Script', bg='red')
self.update_window()
else:
stdin, self.stdout, stderr = self.ssh.exec_command(chr(3))
self.mylist.insert(tk.END, str('Ending Script\n'))
self.script_btn.config(text='Start Script', bg=def_color)
def update_window(self):
for line in iter(lambda: self.stdout.readline(), ""):
self.mylist.insert(tk.END, str(line))
self.scrollbar.config(command=self.mylist.yview)
# self.root2.after(1000, self.update_window)
def main():
root = tk.Tk()
IP = '*********'
user = '*******'
pswd = '*******'
runGUI = main_window(root, IP, user, pswd)
root.title("Connect to Drone")
root.wm_iconbitmap('logo_blue.ico')
root.mainloop()
if __name__ == "__main__":
main()