На клиенте есть маршрут до сервера, где локальный (российский) конец туннеля.
import sys
from pathlib import Path
# __file__ и sys.argv[0] могут не совпадать для скриптов из нескольких файлов.
script_path = Path(sys.argv[0]).resolve()
dotenv_path = script_path.parent / '.env'
script_name = script_path.stem
log_dir = script_path.parent
log_file = log_dir / (script_name + '.log')
rects_to_send = []
for rect in rectangles:
rects_to_send.append( [rect.x, rect.y, rect.w, rect.h] )
from tkinter import *
from tkinter import ttk
class App(Tk):
def __init__(self, parent):
super().__init__()
self.title('Main window')
self.geometry('400x350+800+400')
self.__put_frames()
def __put_frames(self): # наш, приватный метод - не надо выставлять его наружу
self.statusbar = Statusbar(self)
self.statusbar.grid(row=1, column=0, columnspan=3)
self.footerbar = Footterbar(self)
# передаём метод, который надо вызвать
# footerbar всё равно не имеет понятия, чей это метод
# он только знает, что его надо вызвать по клику на кнопку 6
# мы могли бы создать метод в App и передать его, это бы тоже сработало
# собственно, задача App - связать два компонента между собой
self.footerbar.button6_clicked = self.statusbar.refresh
self.footerbar.grid(row=2, column=0, columnspan=3)
class Statusbar(Frame):
"""Этот класс реализует строку состояния, которая умеет показывать текст."""
def __init__(self, parent):
super().__init__(parent)
self.__put_widgets()
def __put_widgets(self): # наш, приватный метод - не надо выставлять его наружу
self.txt = Text(self, height=15, width=35)
self.txt.grid(row=1, column=0, columnspan=3)
def refresh(self):
self.txt.delete(1.0, END)
self.txt.insert(END, "Updated content")
class Footterbar(Frame):
"""Этот класс реализует панель с нажимаемыми кнопками, и позволяет отреагировать на их нажатие"""
def __init__(self, parent): # мы ничего не знаем про статусбар
super().__init__(parent)
self.button6_clicked = None # тут будет храниться ссылка на метод
self.__put_widgets()
def __button6_click(self):
if self.button6_clicked is not None: # у нас есть что вызывать?
self.button6_clicked() # да - вызываем
def __put_widgets(self): # наш, приватный метод - не надо выставлять его наружу
self.btn4 = ttk.Button(self, text='4')
self.btn4.grid(row=10, column=0)
self.btn5 = ttk.Button(self, text='5')
self.btn5.grid(row=10, column=1)
self.btn6 = ttk.Button(self, text='6', command=self.__button6_click)
self.btn6.grid(row=10, column=2)
app = App(Tk)
app.mainloop()