from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.uix.label import Label from kivy.metrics import dp # 👉 import tvého numpadu (uprav cestu podle projektu) from numberpad import NumberPad # ===================================================== # IP + PORT INPUT (COMPACT) # ===================================================== class IpPortInput(BoxLayout): """ mode: "ip" → jen IP "port" → jen port "both" → IP + port """ def __init__(self, *, mode="both", ip="192.168.0.1", port=8000, on_done=None, **kwargs): super().__init__( orientation="vertical", spacing=dp(5), size_hint_y=None, height=dp(120), padding=dp(5), **kwargs ) self.mode = mode self.on_done = on_done self.ip_parts = self._parse_ip(ip) self.port = str(port) # ================= DISPLAY ================= self.lbl = Label( text=self._format(), size_hint_y=None, height=dp(25), halign="center", valign="middle", ) self.lbl.bind(size=lambda *_: setattr(self.lbl, "text_size", self.lbl.size)) self.add_widget(self.lbl) # ================= BUTTON ROW ================= row = BoxLayout(spacing=dp(3), height=dp(45), size_hint_y=None) self.btn_ip = [] if mode in ("ip", "both"): for i in range(4): b = Button(text=self.ip_parts[i], font_size=14) b.bind(on_press=lambda inst, idx=i: self._edit_ip(idx)) self.btn_ip.append(b) row.add_widget(b) if mode in ("port", "both"): self.btn_port = Button(text=self.port, font_size=14) self.btn_port.bind(on_press=self._edit_port) row.add_widget(self.btn_port) self.add_widget(row) # ================= OK BUTTON ================= btn_ok = Button( text="OK", size_hint_y=None, height=dp(40), background_color=(0.2, 0.6, 0.2, 1), ) btn_ok.bind(on_press=self._done) self.add_widget(btn_ok) # ================================================= # PARSE / FORMAT # ================================================= def _parse_ip(self, ip): try: parts = ip.split(".") return [str(int(p)) for p in parts[:4]] except Exception: return ["192", "168", "0", "1"] def _format(self): if self.mode == "ip": return ".".join(self.ip_parts) if self.mode == "port": return self.port return f"{'.'.join(self.ip_parts)}:{self.port}" def get_value(self): if self.mode == "ip": return ".".join(self.ip_parts) if self.mode == "port": return int(self.port) return ".".join(self.ip_parts), int(self.port) # ================================================= # EDIT IP PART # ================================================= def _edit_ip(self, idx): def done(val): try: v = int(val) if 0 <= v <= 255: self.ip_parts[idx] = str(v) self.btn_ip[idx].text = str(v) self._refresh() except Exception: pass NumberPad( mode="number", max_len=3, allow_fraction=False, initial_value=self.ip_parts[idx], on_accept=done, ).open() # ================================================= # EDIT PORT # ================================================= def _edit_port(self, *_): def done(val): try: v = int(val) if 0 <= v <= 65535: self.port = str(v) self.btn_port.text = str(v) self._refresh() except Exception: pass NumberPad( mode="number", max_len=5, allow_fraction=False, initial_value=self.port, on_accept=done, ).open() # ================================================= # REFRESH # ================================================= def _refresh(self): self.lbl.text = self._format() # ================================================= # DONE # ================================================= def _done(self, *_): if self.on_done: self.on_done(self.get_value()) # ===================================================== # TEST APP # ===================================================== class TestApp(App): def build(self): root = BoxLayout(padding=dp(20)) widget = IpPortInput( mode="both", ip="10.0.0.5", port=8080, on_done=lambda v: print("RESULT:", v), ) root.add_widget(widget) return root if __name__ == "__main__": TestApp().run()