from kivy.app import App from kivy.uix.button import Button from kivy.uix.label import Label from kivy.uix.boxlayout import BoxLayout from kivy.uix.scrollview import ScrollView from kivy.core.window import Window from kivy.clock import Clock from kivy.metrics import dp from kivy.properties import StringProperty, ListProperty, BooleanProperty from kivy.animation import Animation from kivy.uix.behaviors import ButtonBehavior from export_opened_to_raster import export_opened_to_raster from save_to_iges import save_opened_to_iges from get_all_sheets import get_all_sheets from project_support import project_support from get_opened_files import get_opened_files class HoverBehavior(ButtonBehavior): """Поведение для обработки наведения курсора""" hovered = BooleanProperty(False) border_point = ListProperty((0, 0)) def __init__(self, **kwargs): super().__init__(**kwargs) self.register_event_type('on_enter') self.register_event_type('on_leave') Window.bind(mouse_pos=self.on_mouse_pos) def on_mouse_pos(self, *args): if not self.get_root_window(): return pos = args[1] inside = self.collide_point(*self.to_widget(*pos)) if self.hovered == inside: return self.border_point = pos self.hovered = inside if inside: self.dispatch('on_enter') else: self.dispatch('on_leave') def on_enter(self): pass def on_leave(self): pass class AnimatedButton(Button): # Цвета для разных состояний original_color = ListProperty([0.392, 0.416, 0.431, 1]) # Основной цвет (синий) hover_color = ListProperty([0.165, 0.592, 1, 1]) # При наведении press_color = ListProperty([0, 0.51, 1, 1]) # При нажатии # Параметры анимации hover_scale = 1.05 press_scale = 0.98 def __init__(self, **kwargs): super().__init__(**kwargs) self.background_normal = '' self.background_color = self.original_color self.original_size = self.size.copy() self.is_hovered = False # Настройка отслеживания мыши Window.bind(mouse_pos=self.on_mouse_pos) def on_mouse_pos(self, window, pos): # Преобразуем координаты мыши в координаты кнопки if not self.get_root_window(): return pos = self.to_widget(*pos) is_inside = self.collide_point(*pos) # Обрабатываем вход/выход курсора if is_inside and not self.is_hovered: self.is_hovered = True self.on_enter() elif not is_inside and self.is_hovered: self.is_hovered = False self.on_leave() def on_enter(self): Animation.cancel_all(self) Animation( background_color=self.hover_color, size=(self.original_size[0] * self.hover_scale, self.original_size[1] * self.hover_scale), duration=0.15, t='out_quad' ).start(self) def on_leave(self): Animation.cancel_all(self) Animation( background_color=self.original_color, size=self.original_size, duration=0.2, t='out_quad' ).start(self) def on_touch_down(self, touch): if self.collide_point(*touch.pos): Animation.cancel_all(self) Animation( background_color=self.press_color, size=(self.original_size[0] * self.press_scale, self.original_size[1] * self.press_scale), duration=0.1, t='in_out_quad' ).start(self) return super().on_touch_down(touch) def on_touch_up(self, touch): if self.collide_point(*touch.pos): Animation.cancel_all(self) Animation( background_color=self.hover_color if self.is_hovered else self.original_color, size=(self.original_size[0] * (self.hover_scale if self.is_hovered else 1), self.original_size[1] * (self.hover_scale if self.is_hovered else 1)), duration=0.1, t='out_quad' ).start(self) return super().on_touch_up(touch) class ScrollableLabel(ScrollView): text = StringProperty('') def __init__(self, **kwargs): super().__init__(**kwargs) self.label = Label( size_hint_y=None, font_size=dp(18), halign='left', valign='top', padding=(dp(15), dp(15)), markup=True ) self.label.bind( texture_size=self._update_label_size, width=lambda *x: setattr(self.label, 'text_size', (self.width, None))) self.bind( width=lambda *x: setattr(self.label, 'text_size', (self.width, None))) self.add_widget(self.label) def _update_label_size(self, instance, size): instance.size = (self.width, size[1]) def on_text(self, instance, value): self.label.text = value class KompasApp(App): def __init__(self, **kwargs): super().__init__(**kwargs) self.title = "Kompas Saver" def build(self): Window.size = (800, 600) main_layout = BoxLayout(orientation='horizontal', spacing=10, padding=10) # Левая панель (кнопки) left_panel = BoxLayout(orientation='vertical', size_hint=(0.3, 1), spacing=10) header = Label(text="Kompas Saver", size_hint=(1, 0.1), font_size=24, bold=True) # Стиль для кнопок button_style = { 'size_hint': (1, 1), #лучше не менять, т.к. кнопки будут плыть при переключении между оконным и полноэкранным режимом 'height': 150, 'halign': 'center', 'valign': 'middle', 'text_size': (None, None), 'padding': (10, 10) } # Создаем анимированные кнопки button1 = AnimatedButton(text="Создать PDF", on_press=self.process_kompas, **button_style) button2 = AnimatedButton(text="Сохранить в IGES", on_press=self.save_to_iges, **button_style) button3 = AnimatedButton(text="Получить информацию \nо чертеже", on_press=self.get_all_sheets, **button_style) button4 = AnimatedButton(text="Projects Support", on_press=self.project_support, **button_style) button5 = AnimatedButton(text="Открытые файлы", on_press=self.get_opened_files, **button_style) left_panel.add_widget(header) left_panel.add_widget(button1) left_panel.add_widget(button2) left_panel.add_widget(button3) left_panel.add_widget(button4) left_panel.add_widget(button5) # Правая панель (прокручиваемый текст) self.right_panel = BoxLayout(orientation='vertical', size_hint=(0.7, 1)) self.scroll_label = ScrollableLabel() self.right_panel.add_widget(self.scroll_label) main_layout.add_widget(left_panel) main_layout.add_widget(self.right_panel) return main_layout def update_output(self, text): self.scroll_label.text = text def process_kompas(self, instance): self.update_output("Конвертация в PDF...\n") Clock.schedule_once(lambda dt: self._run_export(), 0.2) def _run_export(self): try: result = export_opened_to_raster() self.update_output(result) except Exception as e: self.update_output(f"[color=ff3333]Ошибка: {str(e)}[/color]") def save_to_iges(self, instance): self.update_output("Экспорт в IGES...") Clock.schedule_once(lambda dt: self._run_save_iges(), 0.2) def _run_save_iges(self): try: result = save_opened_to_iges() self.update_output(result) except Exception as e: self.update_output(f"[color=ff3333]Ошибка: {str(e)}[/color]") def get_all_sheets(self, instance): self.update_output("Получение списка листов...") Clock.schedule_once(lambda dt: self._run_get_sheets(), 0.2) def _run_get_sheets(self): try: result = get_all_sheets() self.update_output(result) except Exception as e: self.update_output(f"[color=ff3333]Ошибка: {str(e)}[/color]") def project_support(self, instance): self.update_output("Project Support...") Clock.schedule_once(lambda dt: self._run_project_support(), 0.2) def _run_project_support(self): try: result = project_support() self.update_output(result) except Exception as e: self.update_output(f"[color=ff3333]Ошибка: {str(e)}[/color]") def get_opened_files(self, instance): self.update_output("Получение списка открытых файлов...") Clock.schedule_once(lambda dt: self._run_get_opened_files(), 0.2) def _run_get_opened_files(self): try: result = get_opened_files() self.update_output(result) except Exception as e: self.update_output(f"[color=ff3333]Ошибка: {str(e)}[/color]") if __name__ == '__main__': KompasApp().run()