init: начало работы над приложением с использованием wxPython
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
from mind_reader.app import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,39 @@
|
||||
import sys
|
||||
|
||||
import wx
|
||||
|
||||
from mind_reader.ui.main_frame import MainFrame
|
||||
|
||||
|
||||
def enable_high_dpi_support():
|
||||
if sys.platform == "win32":
|
||||
try:
|
||||
import ctypes
|
||||
|
||||
ctypes.windll.shcore.SetProcessDpiAwareness(2)
|
||||
except Exception:
|
||||
try:
|
||||
import ctypes
|
||||
|
||||
ctypes.windll.user32.SetProcessDPIAware()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
class MindReaderApp(wx.App):
|
||||
def OnInit(self) -> bool:
|
||||
self.frame = MainFrame()
|
||||
self.frame.Show(True)
|
||||
self.SetTopWindow(self.frame)
|
||||
return True
|
||||
|
||||
|
||||
def main():
|
||||
enable_high_dpi_support()
|
||||
|
||||
app = MindReaderApp(redirect=False)
|
||||
app.MainLoop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,7 @@
|
||||
from mind_reader.ui.dialogs.client_dialog import ClientConnectDialog
|
||||
from mind_reader.ui.dialogs.server_dialog import ServerStartDialog
|
||||
|
||||
__all__ = [
|
||||
"ClientConnectDialog",
|
||||
"ServerStartDialog",
|
||||
]
|
||||
@@ -0,0 +1,84 @@
|
||||
import wx
|
||||
|
||||
|
||||
class ClientConnectDialog(wx.Dialog):
|
||||
def __init__(self, parent: wx.Window):
|
||||
super().__init__(
|
||||
parent=parent,
|
||||
title="Подключение к серверу",
|
||||
style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
|
||||
)
|
||||
|
||||
self._init_ui()
|
||||
|
||||
self.Fit()
|
||||
calculated_size = self.GetSize()
|
||||
self.SetMinSize(calculated_size)
|
||||
self.CenterOnParent()
|
||||
|
||||
def _init_ui(self):
|
||||
main_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
grid_sizer = wx.FlexGridSizer(rows=2, cols=2, vgap=10, hgap=10)
|
||||
grid_sizer.AddGrowableCol(1, 1)
|
||||
|
||||
label_name = wx.StaticText(self, label="Ваше имя:")
|
||||
self.text_name = wx.TextCtrl(self, value="Игрок1")
|
||||
|
||||
grid_sizer.Add(label_name, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
grid_sizer.Add(self.text_name, 1, wx.EXPAND)
|
||||
|
||||
label_ip = wx.StaticText(self, label="IP адрес сервера:")
|
||||
self.text_ip = wx.TextCtrl(self, value="127.0.0.1")
|
||||
|
||||
grid_sizer.Add(label_ip, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
grid_sizer.Add(self.text_ip, 1, wx.EXPAND)
|
||||
|
||||
main_sizer.Add(grid_sizer, 0, wx.EXPAND | wx.ALL, 15)
|
||||
|
||||
main_sizer.Add(
|
||||
wx.StaticLine(self), 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 10
|
||||
)
|
||||
|
||||
button_sizer = wx.StdDialogButtonSizer()
|
||||
self.button_connect = wx.Button(self, wx.ID_OK, label="Подключиться")
|
||||
self.button_cancel = wx.Button(self, wx.ID_CANCEL, label="Отмена")
|
||||
|
||||
button_sizer.AddButton(self.button_connect)
|
||||
button_sizer.AddButton(self.button_cancel)
|
||||
button_sizer.Realize()
|
||||
|
||||
main_sizer.Add(button_sizer, 0, wx.EXPAND | wx.ALL, 10)
|
||||
|
||||
self.SetSizer(main_sizer)
|
||||
|
||||
self.button_connect.Bind(wx.EVT_BUTTON, self._on_connect)
|
||||
|
||||
def _on_connect(self, event):
|
||||
name = self.text_name.GetValue().strip()
|
||||
ip = self.text_ip.GetValue().strip()
|
||||
|
||||
if not name:
|
||||
wx.MessageBox(
|
||||
"Пожалуйста, введите ваше имя",
|
||||
"Ошибка",
|
||||
wx.OK | wx.ICON_WARNING,
|
||||
self,
|
||||
)
|
||||
return
|
||||
|
||||
if not ip:
|
||||
wx.MessageBox(
|
||||
"Пожалуйста, введите IP адрес сервера",
|
||||
"Ошибка",
|
||||
wx.OK | wx.ICON_WARNING,
|
||||
self,
|
||||
)
|
||||
return
|
||||
|
||||
event.Skip()
|
||||
|
||||
def get_data(self) -> tuple[str, str]:
|
||||
return (
|
||||
self.text_name.GetValue().strip(),
|
||||
self.text_ip.GetValue().strip(),
|
||||
)
|
||||
@@ -0,0 +1,99 @@
|
||||
import socket
|
||||
|
||||
import wx
|
||||
|
||||
|
||||
def get_available_ip_addresses() -> list[str]:
|
||||
ip_list = [
|
||||
"127.0.0.1",
|
||||
]
|
||||
|
||||
try:
|
||||
hostname = socket.gethostname()
|
||||
for ip in socket.gethostbyname_ex(hostname)[2]:
|
||||
if ip not in ip_list:
|
||||
ip_list.append(ip)
|
||||
except Exception:
|
||||
pass
|
||||
return ip_list
|
||||
|
||||
|
||||
class ServerStartDialog(wx.Dialog):
|
||||
def __init__(self, parent: wx.Window):
|
||||
super().__init__(
|
||||
parent=parent,
|
||||
title="Запуск сервера",
|
||||
style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER,
|
||||
)
|
||||
|
||||
self._init_ui()
|
||||
|
||||
self.Fit()
|
||||
calculated_size = self.GetSize()
|
||||
self.SetMinSize(calculated_size)
|
||||
self.CenterOnParent()
|
||||
|
||||
def _init_ui(self):
|
||||
main_sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
grid_sizer = wx.FlexGridSizer(rows=2, cols=2, vgap=10, hgap=10)
|
||||
grid_sizer.AddGrowableCol(1, 1)
|
||||
|
||||
label_name = wx.StaticText(self, label="Ваше имя:")
|
||||
self.text_name = wx.TextCtrl(self, value="Игрок2")
|
||||
grid_sizer.Add(label_name, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
grid_sizer.Add(self.text_name, 1, wx.EXPAND)
|
||||
|
||||
label_ip = wx.StaticText(self, label="IP адрес для запуска:")
|
||||
available_ips = get_available_ip_addresses()
|
||||
self.combo_ip = wx.ComboBox(
|
||||
self,
|
||||
choices=available_ips,
|
||||
style=wx.CB_READONLY,
|
||||
)
|
||||
if available_ips:
|
||||
self.combo_ip.SetSelection(0)
|
||||
|
||||
grid_sizer.Add(label_ip, 0, wx.ALIGN_CENTER_VERTICAL)
|
||||
grid_sizer.Add(self.combo_ip, 1, wx.EXPAND)
|
||||
|
||||
main_sizer.Add(grid_sizer, 0, wx.EXPAND | wx.ALL, 15)
|
||||
|
||||
main_sizer.Add(
|
||||
wx.StaticLine(self), 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 10
|
||||
)
|
||||
|
||||
button_sizer = wx.StdDialogButtonSizer()
|
||||
self.button_start = wx.Button(
|
||||
self, wx.ID_OK, label="Ожидать подключение"
|
||||
)
|
||||
self.button_cancel = wx.Button(self, wx.ID_CANCEL, label="Отмена")
|
||||
|
||||
button_sizer.AddButton(self.button_start)
|
||||
button_sizer.AddButton(self.button_cancel)
|
||||
button_sizer.Realize()
|
||||
|
||||
main_sizer.Add(button_sizer, 0, wx.EXPAND | wx.ALL, 10)
|
||||
|
||||
self.SetSizer(main_sizer)
|
||||
|
||||
self.button_start.Bind(wx.EVT_BUTTON, self._on_start)
|
||||
|
||||
def _on_start(self, event):
|
||||
name = self.text_name.GetValue().strip()
|
||||
|
||||
if not name:
|
||||
wx.MessageBox(
|
||||
"Пожалуйста, введите ваше имя",
|
||||
"Ошибка",
|
||||
wx.OK | wx.ICON_WARNING,
|
||||
self,
|
||||
)
|
||||
return
|
||||
|
||||
event.Skip()
|
||||
|
||||
def get_data(self) -> tuple[str, str]:
|
||||
return (
|
||||
self.text_name.GetValue().strip(),
|
||||
self.combo_ip.GetValue(),
|
||||
)
|
||||
@@ -0,0 +1,53 @@
|
||||
import wx
|
||||
|
||||
from mind_reader.ui.dialogs import ClientConnectDialog, ServerStartDialog
|
||||
from mind_reader.ui.menu_bar import AppMenuBar
|
||||
|
||||
|
||||
class MainFrame(wx.Frame):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
parent=None,
|
||||
id=wx.ID_ANY,
|
||||
title="Mind Reader",
|
||||
size=wx.Size(700, 500),
|
||||
style=wx.DEFAULT_FRAME_STYLE,
|
||||
)
|
||||
self.Center()
|
||||
|
||||
self.menu_bar = AppMenuBar(self)
|
||||
self.SetMenuBar(self.menu_bar)
|
||||
|
||||
self.CreateStatusBar(1)
|
||||
self.SetStatusText("Подключение отсутствует")
|
||||
|
||||
self._bind_menu_events()
|
||||
|
||||
def _bind_menu_events(self):
|
||||
self.Bind(
|
||||
wx.EVT_MENU, self.on_client_connect, self.menu_bar.item_client
|
||||
)
|
||||
self.Bind(wx.EVT_MENU, self.on_server_start, self.menu_bar.item_server)
|
||||
self.Bind(
|
||||
wx.EVT_MENU, self.on_disconnect, self.menu_bar.item_disconnect
|
||||
)
|
||||
|
||||
def on_client_connect(self, event):
|
||||
d = ClientConnectDialog(self)
|
||||
if d.ShowModal() == wx.ID_OK:
|
||||
name, ip = d.get_data()
|
||||
self.menu_bar.set_connected_state(True)
|
||||
self.SetStatusText(f"Подключено к {ip} | Ваше имя {name}")
|
||||
d.Destroy()
|
||||
|
||||
def on_server_start(self, event):
|
||||
d = ServerStartDialog(self)
|
||||
if d.ShowModal() == wx.ID_OK:
|
||||
name, ip = d.get_data()
|
||||
self.menu_bar.set_connected_state(True)
|
||||
self.SetStatusText(f"Сервер запущен на {ip} | Ваше имя {name}")
|
||||
d.Destroy()
|
||||
|
||||
def on_disconnect(self, event):
|
||||
self.menu_bar.set_connected_state(False)
|
||||
self.SetStatusText("Подключение отсутствует")
|
||||
@@ -0,0 +1,85 @@
|
||||
import wx
|
||||
|
||||
|
||||
class AppMenuBar(wx.MenuBar):
|
||||
def __init__(self, parent: wx.Frame):
|
||||
super().__init__()
|
||||
self.parent = parent
|
||||
|
||||
self._create_file_menu()
|
||||
self._create_connection_menu()
|
||||
self._create_help_menu()
|
||||
|
||||
def _create_file_menu(self):
|
||||
self.file_menu = wx.Menu()
|
||||
|
||||
self.item_open = self.file_menu.Append(
|
||||
wx.ID_OPEN,
|
||||
"&Открыть...\tCtrl+O",
|
||||
"Открыть файл с результатами сессий",
|
||||
)
|
||||
|
||||
self.item_save = self.file_menu.Append(
|
||||
wx.ID_SAVE,
|
||||
"&Сохранить\tCtrl+S",
|
||||
"Сохранить текущие результаты сессий",
|
||||
)
|
||||
|
||||
self.item_save_as = self.file_menu.Append(
|
||||
wx.ID_SAVEAS,
|
||||
"Сохранить &как...\tCtrl+Shift+S",
|
||||
"Сохранить результаты сессий в новый файл",
|
||||
)
|
||||
|
||||
self.file_menu.AppendSeparator()
|
||||
|
||||
self.item_exit = self.file_menu.Append(
|
||||
wx.ID_EXIT,
|
||||
"&Выход\tAlt+F4",
|
||||
"Завершить работу программы",
|
||||
)
|
||||
|
||||
self.Append(self.file_menu, "&Файл")
|
||||
|
||||
def _create_connection_menu(self):
|
||||
self.conn_menu = wx.Menu()
|
||||
|
||||
self.item_client = self.conn_menu.Append(
|
||||
wx.ID_ANY,
|
||||
"&Клиент...",
|
||||
"Подключиться к серверу",
|
||||
)
|
||||
|
||||
self.item_server = self.conn_menu.Append(
|
||||
wx.ID_ANY,
|
||||
"&Сервер...",
|
||||
"Запустить сервер",
|
||||
)
|
||||
|
||||
self.conn_menu.AppendSeparator()
|
||||
|
||||
self.item_disconnect = self.conn_menu.Append(
|
||||
wx.ID_ANY,
|
||||
"&Разорвать подключение",
|
||||
"Завершить сетевое соединение",
|
||||
)
|
||||
|
||||
self.item_disconnect.Enable(False)
|
||||
|
||||
self.Append(self.conn_menu, "&Подключение")
|
||||
|
||||
def _create_help_menu(self):
|
||||
self.help_menu = wx.Menu()
|
||||
|
||||
self.item_about = self.help_menu.Append(
|
||||
wx.ID_ABOUT,
|
||||
"&О программе...\tF1",
|
||||
"Информация о программе",
|
||||
)
|
||||
|
||||
self.Append(self.help_menu, "&Справка")
|
||||
|
||||
def set_connected_state(self, is_connected: bool):
|
||||
self.item_client.Enable(not is_connected)
|
||||
self.item_server.Enable(not is_connected)
|
||||
self.item_disconnect.Enable(is_connected)
|
||||
Reference in New Issue
Block a user