From 220b923e7657090660fcf285f82f27b531810485 Mon Sep 17 00:00:00 2001 From: prog1764 Date: Tue, 4 Aug 2026 23:50:25 +0400 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=BE=D0=BA=D0=BD=D0=BE=20=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D1=87=D1=91=D1=82=D0=B0=20=D0=BF=D0=BE=D0=BA=D0=B0=D0=B7?= =?UTF-8?q?=D0=B0=D1=82=D0=B5=D0=BB=D0=B5=D0=B9=208/9=20=E2=80=94=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D1=83=D1=85=D0=BE=D0=B4=D0=B8=D1=82=20=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=B7=D0=B0=D0=B4=D0=BD=D0=B8=D0=B9=20=D0=BF=D0=BB=D0=B0=D0=BD?= =?UTF-8?q?,=20=D0=B2=D0=B2=D0=BE=D0=B4=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=B0=D0=B5=D1=82,=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA=D0=B0=20?= =?UTF-8?q?=D0=BD=D0=B0=20=D0=BC=D0=B5=D1=81=D1=82=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Проблемы: 1. Окно уходило на задний план при сдвиге — не было grab_set/lift, родитель указывал на главное окно вместо диалога ПП 127 2. В показателе 8 не вводились данные — из-за потери фокуса 3. В показателе 9 кнопка «Рассчитать» не была видна — окно 720x560 не вмещало все поля (прибыль/налог/ΔДоходов/бюджет/НДПИ/ДИВ/ВСО/НС + результат), кнопки уезжали за край Исправлено: - родитель окна — dialog (ПП 127), а не root - w.transient(dialog) + w.lift() + w.grab_set() + w.focus_force() - тело окна в Canvas + вертикальный Scrollbar (все поля доступны) - кнопки «🧮 Рассчитать / ✔️ Применить / Отмена» вне скролла — всегда видны - при закрытии — grab_release() --- dokogen/ui.py | 54 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/dokogen/ui.py b/dokogen/ui.py index d3ec04e..bc909fb 100644 --- a/dokogen/ui.py +++ b/dokogen/ui.py @@ -2172,23 +2172,38 @@ class DokoGenApp: profit = getattr(self.model, 'profit', '') or '' profit_tax = getattr(self.model, 'profit_tax', '') or '' - w = tk.Toplevel(self.root) + # Родитель — окно ПП 127 (dialog), а не главное окно; + # grab_set + lift — чтобы окно не уходило на задний план + w = tk.Toplevel(dialog) w.title(f"🧮 Авторасчёт показателя {num} — {name[:60]}") - w.geometry("720x560") - w.transient(self.root) - frm = ttk.Frame(w, padding=10) - frm.pack(fill=tk.BOTH, expand=True) + w.geometry("820x700") + w.transient(dialog) + w.lift() + w.focus_force() + + # Внешняя рамка: тело со скроллом + кнопки снизу (всегда видны) + outer = ttk.Frame(w, padding=10) + outer.pack(fill=tk.BOTH, expand=True) + + canvas = tk.Canvas(outer, highlightthickness=0) + scrollbar = ttk.Scrollbar(outer, orient=tk.VERTICAL, command=canvas.yview) + frm = ttk.Frame(canvas) + frm.bind("", lambda e: canvas.configure(scrollregion=canvas.bbox("all"))) + canvas.create_window((0, 0), window=frm, anchor="nw") + canvas.configure(yscrollcommand=scrollbar.set) + canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) + scrollbar.pack(side=tk.RIGHT, fill=tk.Y) if num == '9': ttk.Label(frm, text="Показатель 9 — ущерб бюджетам РФ (применим ко всем субъектам КИИ)", font=('Arial', 10, 'bold')).pack(anchor=tk.W) ttk.Label(frm, text="Формула: №9 = ΔБ / Бусредн × 100%, где ΔБ = ΔНП + ΔНДПИ + ΔДИВ + ΔВСО + ΔНС\n" "ΔНП = ΔДоходов × (налог на прибыль / прибыль); если ΔДоходов > прибыли — весь налог.", - foreground='gray', wraplength=660, justify=tk.LEFT).pack(anchor=tk.W, pady=(2, 6)) + foreground='gray', wraplength=760, justify=tk.LEFT).pack(anchor=tk.W, pady=(2, 6)) def _row(label, key, default=''): ttk.Label(frm, text=label).pack(anchor=tk.W, pady=(4, 0)) - e = ttk.Entry(frm, width=60) + e = ttk.Entry(frm, width=70) e.insert(0, str(default or '')) e.pack(fill=tk.X) return e @@ -2204,18 +2219,18 @@ class DokoGenApp: e_div = _row("Снижение выплат от дивидендов ΔДИВ (руб.):", 'div', '0') e_vso = _row("Снижение выплат сторонних организаций ΔВСО (руб.):", 'vso', '0') e_ns = _row("Снижение сборов ΔНС (руб.):", 'ns', '0') - result = tk.Text(frm, height=10, wrap=tk.WORD, state=tk.NORMAL) + result = tk.Text(frm, height=8, wrap=tk.WORD, state=tk.NORMAL) result.pack(fill=tk.BOTH, expand=True, pady=(8, 0)) else: ttk.Label(frm, text="Показатель 8 — ущерб субъекту КИИ", font=('Arial', 10, 'bold')).pack(anchor=tk.W) ttk.Label(frm, text="Применим только для: госкорпорации, ГУП, госкомпании, стратегического АО/предприятия " "(Указ Президента № 1009).\nФормула: №8 = ΔДоходов / Дусредн × 100%.", - foreground='gray', wraplength=660, justify=tk.LEFT).pack(anchor=tk.W, pady=(2, 6)) + foreground='gray', wraplength=760, justify=tk.LEFT).pack(anchor=tk.W, pady=(2, 6)) def _row(label, key, default=''): ttk.Label(frm, text=label).pack(anchor=tk.W, pady=(4, 0)) - e = ttk.Entry(frm, width=60) + e = ttk.Entry(frm, width=70) e.insert(0, str(default or '')) e.pack(fill=tk.X) return e @@ -2230,7 +2245,7 @@ class DokoGenApp: 'dincome', f"{_d_loss:,.0f}" if _d_loss else '') e_budget = _row("Доходы субъекта КИИ, усреднённые за 5 лет (руб.):", 'budget', f"{_d_avg:,.0f}" if _d_avg else '') - result = tk.Text(frm, height=10, wrap=tk.WORD, state=tk.NORMAL) + result = tk.Text(frm, height=8, wrap=tk.WORD, state=tk.NORMAL) result.pack(fill=tk.BOTH, expand=True, pady=(8, 0)) def _calc(): @@ -2240,7 +2255,7 @@ class DokoGenApp: b = _num(e_budget.get()) if d is None or b is None or b <= 0: result.delete('1.0', tk.END) - result.insert('1.0', "Заполните оба поля (ΔДоходов и Дусредн).") + result.insert('1.0', "Заполните оба поля (ущерб и доходы за 5 лет).") return val = d / b * 100 lines.append(f"Суммарный экономический ущерб от нарушения критических процессов: {d:,.0f} руб.") @@ -2316,12 +2331,10 @@ class DokoGenApp: elif 'Категория значимости: III' in cat_line: cat = 'III' if cat: - # Выбрать в комбобоксе соответствующую категорию opts = list(combo['values']) target = next((o for o in opts if o.startswith(f"{cat} категория")), None) if target: var.set(target) - # Обоснование с расчётом prefix = f"Показатель {num}. {name} — {cat} категория." full = prefix + "\n" + txt cur = justify_txt.get('1.0', 'end-1c').strip() @@ -2340,14 +2353,23 @@ class DokoGenApp: justify_txt.insert('end', '\n' + full) else: justify_txt.insert('1.0', full) + w.grab_release() w.destroy() - btns = ttk.Frame(frm) + # Кнопки — вне скролла, всегда видны + btns = ttk.Frame(outer) btns.pack(fill=tk.X, pady=(8, 0)) ttk.Button(btns, text="🧮 Рассчитать", command=_calc).pack(side=tk.LEFT, padx=2) ttk.Button(btns, text="✔️ Применить категорию", command=_apply).pack(side=tk.LEFT, padx=2) - ttk.Button(btns, text="Отмена", command=w.destroy).pack(side=tk.LEFT, padx=2) + ttk.Button(btns, text="Отмена", + command=lambda: (w.grab_release(), w.destroy())).pack(side=tk.LEFT, padx=2) + # Захват фокуса — окно не уходит на задний план + try: + w.grab_set() + except Exception: + pass + w.lift() rows = [] # (num, name, values{III:..,II:..,I:..}, var, applicable) _combos = {} # num -> комбобокс (для автозаполнения)