[置顶] 整理一些代码__xu_init.js 作为自己项目开发时使用

本文探讨了Rails与PHP中布局的不同实现方式,并通过实例说明了Rails如何通过布局模板将共通元素整合到各个页面中,同时分享了JavaScript相关组件开发经验。

这几天一直在混淆 PHP 与 rails 布局的概念,很头疼...

 

写道
rails 中:
布局是一种在多个页面中包含共同元素的手段.可以把它看成是 同 PHP等平台上的 服务端包含include 颠倒过来的 . 与定义一些共同内容的片段,然后包含进每个文档里 不同的是, "布局"定义一个共同的模板,然后把每个页面的内容注入其中 . 如图所示:

具有包含的页面
[
[首部包含]
主页内容

[脚部包含]
]

使用布局的页面
[
首部
[主页内容]
脚部
]

 

 

学习连接: http://www.w3school.com.cn/js/jsref_obj_global.asp

 

 

还是按梯度来帖,顺便证明自己js的提高... 无语....

 

1. 第一版 2009年9月21日12:14:33 __xu_init.js

集成 jstrace 调试 , /*浏览器探测*/  , //Cookie 设置 ,存在 cookie中文读取问题...

 

 

2. 第二版,集成DOM拖拽功能,截图如下:

 

加入的代码如下:

 // ------------------- Xu.Dom命名空间
Xu.pkg("Core.Dom");

//拖拉插件 Drag -- 依賴dom-drag.js
if (typeof(Drag) != 'undefined'){	
	Core.Dom.Drag = Drag ;
	if ( __xu_debug)
		trace("拖拉插件 Drag -- 注入成功!");
} else {
	Core.Dom.Drag = {
		init: function(){
			trace("拖拉插件 Drag -- 依賴dom-drag.js ,請加入");
		}
	}
}

//
Core.Dom.Drag.init($ID('testDrag').getElementsByTagName('h1')[0],$ID('testDrag'));

 

添加一个 Widget: Javascript 校验 demo页面:

  • 大小: 66.9 KB
  • validator.zip (2 KB)
  • 描述: 支持拖拽的,带特殊字符,IP地址验证的demo
  • 下载次数: 17
  • 大小: 48.2 KB
<think>我们遇到的问题是在创建Toplevel窗口出现了AttributeError: 'StickyNotesApp' object has no attribute 'tk' 根据错误信息,问题出在StickyNotesApp对象没有'tk'属性。在Tkinter中,Toplevel窗口需要关联一个Tk实例(根窗口)。 回顾代码,在StickyNote类的__init__方法中,我们使用: self.window = tk.Toplevel(master) 这里的master应该是StickyNotesApp的实例,而StickyNotesApp类本身并不是一个Tkinter窗口部件。 在StickyNotesApp的__init__方法中,我们传入了一个root(Tk实例)并赋值给self.root,但是我们在创建StickyNote传递的master是self(即StickyNotesApp实例),而它并没有tk属性(Tkinter要求master必须是一个Tkinter窗口部件,因为Toplevel需要访问Tk对象)。 正确的做法应该是:在创建StickyNote,将self.root作为master传递,因为self.root是Tk实例(根窗口)。 修改StickyNotesApp类中创建StickyNote的地方: 原代码:StickyNote(self, note_id, ...) 修改为:StickyNote(self.root, note_id, ...) # 将master改为self.root 但是,这样修改后,StickyNote类中需要访问StickyNotesApp的方法(如save_notes, delete_note)就无法直接调用了。因此,我们需要调整设计。 解决方案: 1. 在StickyNote类中,我们仍然需要访问StickyNotesApp的方法(例如保存和删除操作需要更新应用状态),因此我们保留对StickyNotesApp实例的引用。 2.,Toplevel的master必须是Tkinter根窗口(即self.root)。 我们可以这样调整: 在StickyNote的初始化中,同保存对app(StickyNotesApp实例)的引用,而master则使用app.root。 修改StickyNote的初始化参数: 将原来的master参数改为两个:app(StickyNotesApp实例)和note_id等。 具体修改步骤: 步骤1:修改StickyNote类的__init__方法签名 def __init__(self, app, note_id, content="", position=None, color="#FFFF99"): 步骤2:在StickyNote类中,保存app引用 self.app = app 步骤3:创建Toplevel窗口使用app.root作为master self.window = tk.Toplevel(app.root) 步骤4:在StickyNotesApp类中创建StickyNote,传递self(即StickyNotesApp实例)作为app参数 StickyNote(self, note_id, ...) 步骤5:在StickyNote类中,原来调用self.master的方法(如self.master.save_notes())改为调用self.app的方法(如self.app.save_notes()) 修改后,StickyNote类中的master(即app.root)是Tkinter根窗口,符合Tkinter要求;同StickyNote可以通过self.app访问StickyNotesApp的方法。 另外,在StickyNotesApp类中,我们创建StickyNote传递了self,所以StickyNote的app参数就是StickyNotesApp实例。 我们按照这个思路修改代码。 同,我们还需要注意:在StickyNotesApp的load_notes方法中创建StickyNote也要做相应的修改。 具体代码修改如下: 在StickyNotesApp类中,创建新便签的地方: StickyNote(self, note_id, note_data["content"], note_data["position"], note_data["color"]) 改为: StickyNote(self, note_id, note_data["content"], note_data["position"], note_data["color"]) 在StickyNote类中,修改__init__方法: 将参数master改为app,并调整内部实现。 下面我们重写StickyNote类的__init__方法(按照修改后的方案): ```python class StickyNote: def __init__(self, app, note_id, content="", position=None, color="#FFFF99"): self.app = app # StickyNotesApp实例 self.note_id = note_id self.content = content # 创建窗口,使用app.root作为master self.window = tk.Toplevel(app.root) self.window.title(f"便签 {note_id}") self.window.configure(bg=color) self.window.attributes('-topmost', True) # 始终置顶 # ... 其余部分保持不变,但将原来使用self.master的地方改为self.app ... # 例如,在按钮命令中: # command=self.app.save_notes 而不是 command=self.master.save_notes ``` 修改按钮绑定的命令: 颜色按钮不需要改(不涉及app) 保存按钮:command=self.save_note (内部会调用self.app.save_notes) 删除按钮:command=self.delete_note (内部会调用self.app.delete_note) 在StickyNote的save_note方法中,原来是调用self.master.save_notes(),现在改为self.app.save_notes() 在delete_note方法中,原来是调用self.master.delete_note(self.note_id),现在改为self.app.delete_note(self.note_id) 这样修改后,应该可以解决AttributeError错误。 另外,在StickyNotesApp的__init__中,我们创建了菜单按钮(新建便签和退出按钮),这些按钮是在主窗口(root)上,但主窗口被隐藏了(self.root.withdraw())。所以用户看不到主窗口,只能看到便签窗口。这是符合预期的。 但是,在创建新便签,我们调用self.create_new_note(),这个方法内部创建了一个新的StickyNote,并传递self(即StickyNotesApp实例)作为app参数。 我们还需要修改StickyNotesApp的delete_note方法,确保删除便签从字典中移除并保存。 最后,注意在StickyNote的on_close方法中,我们调用了save_note和销毁窗口,这里不需要改变,因为save_note内部已经改为调用app的方法。 让我们总结一下修改点: 1. StickyNote的初始化参数从master改为app(StickyNotesApp实例) 2. 创建Toplevel使用app.root作为master 3. 将StickyNote内部所有对master的方法调用改为对app的方法调用 4. 在StickyNotesApp中创建StickyNote传递self(即app)作为第一个参数 按照这个修改,应该可以解决错误。 如果问题仍然存在,请检查错误发生的具体位置,可能是其他地方还有对tk属性的访问。 另外,注意在StickyNotesApp的__init__中,我们创建了self.root = root,所以root是Tk实例,具有tk属性。 我们修改代码后重新运行测试。 由于代码较长,这里只给出修改后的关键部分,完整代码请根据修改点调整。 如果遇到其他问题,请提供具体的错误信息。 下面给出修改后的完整代码(仅修改部分):</think># 解决 Tkinter AttributeError: 'StickyNotesApp' object has no attribute 'tk' 错误 这个错误发生在创建 Toplevel 窗口,表明 `StickyNotesApp` 对象缺少 `tk` 属性。在 Tkinter 中,所有窗口部件都需要连接到有效的 Tk 实例(根窗口)。让我们一步步解决这个问题: ## 问题分析 错误原因在于: 1. `StickyNote` 类试图创建 `Toplevel` 窗口,其 `master` 参数是 `StickyNotesApp` 实例 2. `StickyNotesApp` 类本身不是 Tkinter 窗口部件,没有 `tk` 属性 3. Tkinter 要求所有窗口部件必须连接到有效的根窗口(`Tk` 实例) ## 解决方案 ### 修改 StickyNote 类 ```python class StickyNote: def __init__(self, root, app, note_id, content="", position=None, color="#FFFF99"): self.root = root # Tk 根窗口实例 self.app = app # StickyNotesApp 实例 self.note_id = note_id self.content = content # 创建窗口 - 使用 root 作为 master self.window = tk.Toplevel(root) # 关键修改:使用 root 而不是 app self.window.title(f"便签 {note_id}") self.window.configure(bg=color) self.window.attributes('-topmost', True) # ... 其他代码保持不变 ... # 修改按钮命令,使用 app 的方法 tk.Button( menu_frame, text="保存", command=self.save_note ).pack(side='left', padx=2) tk.Button( menu_frame, text="删除", command=self.delete_note ).pack(side='right', padx=2) # ... 其他方法保持不变 ... def save_note(self): self.content = self.text.get("1.0", "end-1c") self.app.save_notes() # 调用 app 的方法 def delete_note(self): self.app.delete_note(self.note_id) # 调用 app 的方法 self.window.destroy() ``` ### 修改 StickyNotesApp 类 ```python class StickyNotesApp: def __init__(self, root): self.root = root # 保存根窗口引用 self.root.title("桌面便签") self.root.withdraw() # ... 其他代码保持不变 ... def create_new_note(self): """创建新便签""" note_id = max(self.notes.keys()) + 1 if self.notes else 1 self.notes[note_id] = { "content": "", "position": [100 + note_id*20, 100 + note_id*20], "color": "#FFFF99", "created": datetime.now().isoformat() } # 关键修改:传递 root 和 self 作为参数 StickyNote(self.root, self, note_id) self.save_notes() def load_notes(self): """从文件加载便签""" try: if os.path.exists("notes.json"): with open("notes.json", "r", encoding="utf-8") as f: data = json.load(f) for note_id, note_data in data.items(): self.notes[int(note_id)] = note_data # 关键修改:传递 root 和 self 作为参数 StickyNote( self.root, self, int(note_id), note_data["content"], note_data["position"], note_data["color"] ) except Exception as e: print(f"加载便签失败: {e}") ``` ## 完整修复代码 ```python import tkinter as tk from tkinter import colorchooser import json import os from datetime import datetime class StickyNote: def __init__(self, root, app, note_id, content="", position=None, color="#FFFF99"): self.root = root self.app = app self.note_id = note_id self.content = content # 创建窗口 self.window = tk.Toplevel(root) self.window.title(f"便签 {note_id}") self.window.configure(bg=color) self.window.attributes('-topmost', True) # 设置位置 if position: self.window.geometry(f"+{position[0]}+{position[1]}") else: self.window.geometry(f"+{100+note_id*20}+{100+note_id*20}") # 创建文本区域 self.text = tk.Text( self.window, bg=color, relief='flat', padx=10, pady=10, wrap='word' ) self.text.pack(fill='both', expand=True) self.text.insert('1.0', content) # 创建菜单按钮 menu_frame = tk.Frame(self.window, bg=color) menu_frame.pack(fill='x', padx=5, pady=5) # 颜色选择按钮 tk.Button( menu_frame, text="颜色", command=self.change_color ).pack(side='left', padx=2) # 保存按钮 tk.Button( menu_frame, text="保存", command=self.save_note ).pack(side='left', padx=2) # 删除按钮 tk.Button( menu_frame, text="删除", command=self.delete_note ).pack(side='right', padx=2) # 绑定关闭事件 self.window.protocol("WM_DELETE_WINDOW", self.on_close) def change_color(self): color = colorchooser.askcolor(title="选择便签颜色")[1] if color: self.window.configure(bg=color) self.text.configure(bg=color) def save_note(self): self.content = self.text.get("1.0", "end-1c") self.app.save_notes() def delete_note(self): self.app.delete_note(self.note_id) self.window.destroy() def on_close(self): self.save_note() self.window.destroy() class StickyNotesApp: def __init__(self, root): self.root = root self.root.title("桌面便签") self.root.withdraw() # 创建系统托盘图标(简化版) self.create_tray_icon() # 加载保存的便签 self.notes = {} self.load_notes() # 如果没有便签,创建一个新的 if not self.notes: self.create_new_note() def create_tray_icon(self): menu_frame = tk.Frame(self.root) menu_frame.pack(fill='x') tk.Button( menu_frame, text="新建便签", command=self.create_new_note ).pack(side='left', padx=5, pady=5) tk.Button( menu_frame, text="退出", command=self.exit_app ).pack(side='right', padx=5, pady=5) def create_new_note(self): note_id = max(self.notes.keys()) + 1 if self.notes else 1 self.notes[note_id] = { "content": "", "position": [100 + note_id*20, 100 + note_id*20], "color": "#FFFF99", "created": datetime.now().isoformat() } StickyNote(self.root, self, note_id) self.save_notes() def delete_note(self, note_id): if note_id in self.notes: del self.notes[note_id] self.save_notes() def load_notes(self): try: if os.path.exists("notes.json"): with open("notes.json", "r", encoding="utf-8") as f: data = json.load(f) for note_id, note_data in data.items(): self.notes[int(note_id)] = note_data StickyNote( self.root, self, int(note_id), note_data["content"], note_data["position"], note_data["color"] ) except Exception as e: print(f"加载便签失败: {e}") def save_notes(self): try: with open("notes.json", "w", encoding="utf-8") as f: json.dump(self.notes, f, ensure_ascii=False, indent=2) except Exception as e: print(f"保存便签失败: {e}") def exit_app(self): self.save_notes() self.root.destroy() if __name__ == "__main__": root = tk.Tk() app = StickyNotesApp(root) root.mainloop() ``` ## 关键修改说明 1. **分离职责**: - `StickyNote` 负责单个便签的UI和交互 - `StickyNotesApp` 负责应用逻辑和状态管理 2. **正确的窗口层次**: - 所有 `Toplevel` 窗口使用 `root` (Tk 实例) 作为 master - 通过 `app` 参数访问应用方法和状态 3. **数据流清晰**: - 便签操作通过 `app` 方法更新应用状态 - 应用状态变化自动同步到所有便签 这种架构遵循了 Tkinter 的窗口层次规则[^1],确保所有窗口部件都有正确的父级关系,解决了 `'tk'` 属性缺失的错误。 ## 相关问题 1. 如何为便签添加真正的系统托盘图标而不是简化版按钮? 2. 如何实现便签内容的自动保存而不是手动点击保存按钮? 3. 如何优化便签应用的内存占用,特别是在创建大量便签? 4. 如何为便签添加字体和文本格式设置功能? 5. 如何实现便签窗口的拖拽移动功能? 6. 如何将便签数据存储在SQLite数据库中而不是JSON文件? 7. 如何为便签添加提醒和通知功能? [^1]: Python 图形界面框架TkInter(第二篇:Window创建过程分析) [^2]: tkinter中控件menu的两种组织方法
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值