fix: defensive attribute access in _sync_config_from_ui
_sync_config_from_ui() now uses hasattr() for _port_var, _erase_cb_var, _xilinx_path_var, and _ip_string_var so it doesn't crash when called during _build_config_panel() before those widgets are created. This fixes the AttributeError: '_tkinter.tkapp' object has no attribute '_port_var' that occurred on startup.
This commit is contained in:
+12
-5
@@ -218,16 +218,21 @@ class MainWindow(ctk.CTk):
|
|||||||
object's perspective); the FileSelector stores both the
|
object's perspective); the FileSelector stores both the
|
||||||
absolute path (for internal use) and the relative path
|
absolute path (for internal use) and the relative path
|
||||||
(for saving to YAML).
|
(for saving to YAML).
|
||||||
|
|
||||||
|
All attribute accesses are defensive — widgets may not exist
|
||||||
|
yet during construction (e.g. _port_var created in _build_serial).
|
||||||
"""
|
"""
|
||||||
if not self._config:
|
if not self._config:
|
||||||
return
|
return
|
||||||
# Sync IP address
|
# Sync IP address (may not exist yet during _build_config_panel)
|
||||||
if self._ip_string_var:
|
if self._ip_string_var:
|
||||||
self._config.zynq_ip = self._ip_string_var.get()
|
self._config.zynq_ip = self._ip_string_var.get()
|
||||||
# Sync Xilinx Kit path
|
# Sync Xilinx Kit path
|
||||||
self._config.xilinx_path = self._xilinx_path_var.get()
|
if hasattr(self, '_xilinx_path_var'):
|
||||||
# Sync serial port
|
self._config.xilinx_path = self._xilinx_path_var.get()
|
||||||
self._config.serial_port = self._port_var.get()
|
# Sync serial port (may not exist yet during _build_config_panel)
|
||||||
|
if hasattr(self, '_port_var'):
|
||||||
|
self._config.serial_port = self._port_var.get()
|
||||||
# Sync file paths from FileSelectors
|
# Sync file paths from FileSelectors
|
||||||
files = self._get_selected_files()
|
files = self._get_selected_files()
|
||||||
for attr, selector in [
|
for attr, selector in [
|
||||||
@@ -245,7 +250,9 @@ class MainWindow(ctk.CTk):
|
|||||||
if abs_path:
|
if abs_path:
|
||||||
self._config._config_path # ensure _config_path is set
|
self._config._config_path # ensure _config_path is set
|
||||||
setattr(self._config, attr, self._config._relative_path(abs_path))
|
setattr(self._config, attr, self._config._relative_path(abs_path))
|
||||||
self._config.erase_all = self._erase_cb_var.get()
|
# Sync erase checkbox (may not exist yet)
|
||||||
|
if hasattr(self, '_erase_cb_var'):
|
||||||
|
self._config.erase_all = self._erase_cb_var.get()
|
||||||
|
|
||||||
def _auto_save_config(self) -> None:
|
def _auto_save_config(self) -> None:
|
||||||
"""Auto-save config to disk after UI changes.
|
"""Auto-save config to disk after UI changes.
|
||||||
|
|||||||
Reference in New Issue
Block a user