Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9d28357

Browse files
committed
add rich text editor tutorial
1 parentb0ae13a commit9d28357

File tree

3 files changed

+191
-0
lines changed

3 files changed

+191
-0
lines changed

‎README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,5 +235,6 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
235235
-[How to Build a GUI Currency Converter using Tkinter in Python](https://www.thepythoncode.com/article/currency-converter-gui-using-tkinter-python). ([code](gui-programming/currency-converter-gui/))
236236
-[How to Detect Gender by Name using Python](https://www.thepythoncode.com/article/gender-predictor-gui-app-tkinter-genderize-api-python). ([code](gui-programming/genderize-app))
237237
-[How to Build a Spreadsheet App with Tkinter in Python](https://www.thepythoncode.com/article/spreadsheet-app-using-tkinter-in-python). ([code](gui-programming/spreadsheet-app))
238+
-[How to Make a Rich Text Editor with Tkinter in Python](https://www.thepythoncode.com/article/create-rich-text-editor-with-tkinter-python). ([code](gui-programming/rich-text-editor))
238239

239240
For any feedback, please consider pulling requests.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#[How to Make a Rich Text Editor with Tkinter in Python](https://www.thepythoncode.com/article/create-rich-text-editor-with-tkinter-python)
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
fromtkinterimport*
2+
fromtkinter.filedialogimportaskopenfilename,asksaveasfilename
3+
importctypes
4+
fromfunctoolsimportpartial
5+
fromjsonimportloads,dumps
6+
7+
ctypes.windll.shcore.SetProcessDpiAwareness(True)
8+
9+
# Setup
10+
root=Tk()
11+
root.geometry('600x600')
12+
13+
# Used to make title of the application
14+
applicationName='Rich Text Editor'
15+
root.title(applicationName)
16+
17+
# Current File Path
18+
filePath=None
19+
20+
# initial directory to be the current directory
21+
initialdir='.'
22+
23+
# Define File Types that can be choosen
24+
validFileTypes= (
25+
("Rich Text File","*.rte"),
26+
("all files","*.*")
27+
)
28+
29+
# Setting the font and Padding for the Text Area
30+
fontName='Bahnschrift'
31+
padding=60
32+
33+
# Infos about the Document are stored here
34+
document=None
35+
36+
# Default content of the File
37+
defaultContent= {
38+
"content":"",
39+
"tags": {
40+
'bold': [(), ()]
41+
},
42+
}
43+
44+
# Transform rgb to hex
45+
defrgbToHex(rgb):
46+
return"#%02x%02x%02x"%rgb
47+
48+
# Add Different Types of Tags that can be added to the document.
49+
tagTypes= {
50+
# Font Settings
51+
'Bold': {'font':f'{fontName} 15 bold'},
52+
'Italic': {'font':f'{fontName} 15 italic'},
53+
'Code': {'font':'Consolas 15','background':rgbToHex((200,200,200))},
54+
55+
# Sizes
56+
'Normal Size': {'font':f'{fontName} 15'},
57+
'Larger Size': {'font':f'{fontName} 25'},
58+
'Largest Size': {'font':f'{fontName} 35'},
59+
60+
# Background Colors
61+
'Highlight': {'background':rgbToHex((255,255,0))},
62+
'Highlight Red': {'background':rgbToHex((255,0,0))},
63+
'Highlight Green': {'background':rgbToHex((0,255,0))},
64+
'Highlight Black': {'background':rgbToHex((0,0,0))},
65+
66+
# Foreground / Text Colors
67+
'Text White': {'foreground':rgbToHex((255,255,255))},
68+
'Text Grey': {'foreground':rgbToHex((200,200,200))},
69+
'Text Blue': {'foreground':rgbToHex((0,0,255))},
70+
'Text green': {'foreground':rgbToHex((0,255,0))},
71+
'Text Red': {'foreground':rgbToHex((255,0,0))},
72+
}
73+
74+
# Handle File Events
75+
deffileManager(event=None,action=None):
76+
globaldocument,filePath
77+
78+
# Open
79+
ifaction=='open':
80+
# ask the user for a filename with the native file explorer.
81+
filePath=askopenfilename(filetypes=validFileTypes,initialdir=initialdir)
82+
83+
84+
withopen(filePath,'r')asf:
85+
document=loads(f.read())
86+
87+
# Delete Content
88+
textArea.delete('1.0',END)
89+
90+
# Set Content
91+
textArea.insert('1.0',document['content'])
92+
93+
# Set Title
94+
root.title(f'{applicationName} -{filePath}')
95+
96+
# Reset all tags
97+
resetTags()
98+
99+
# Add To the Document
100+
fortagNameindocument['tags']:
101+
fortagStart,tagEndindocument['tags'][tagName]:
102+
textArea.tag_add(tagName,tagStart,tagEnd)
103+
print(tagName,tagStart,tagEnd)
104+
105+
elifaction=='save':
106+
document=defaultContent
107+
document['content']=textArea.get('1.0',END)
108+
109+
fortagNameintextArea.tag_names():
110+
iftagName=='sel':continue
111+
112+
document['tags'][tagName]= []
113+
114+
ranges=textArea.tag_ranges(tagName)
115+
116+
fori,tagRangeinenumerate(ranges[::2]):
117+
document['tags'][tagName].append([str(tagRange),str(ranges[i+1])])
118+
119+
ifnotfilePath:
120+
# ask the user for a filename with the native file explorer.
121+
newfilePath=asksaveasfilename(filetypes=validFileTypes,initialdir=initialdir)
122+
123+
# Return in case the User Leaves the Window without
124+
# choosing a file to save
125+
ifnewfilePathisNone:return
126+
127+
filePath=newfilePath
128+
129+
ifnotfilePath.endswith('.rte'):
130+
filePath+='.rte'
131+
132+
withopen(filePath,'w')asf:
133+
print('Saving at: ',filePath)
134+
f.write(dumps(document))
135+
136+
root.title(f'{applicationName} -{filePath}')
137+
138+
139+
defresetTags():
140+
fortagintextArea.tag_names():
141+
textArea.tag_remove(tag,"1.0","end")
142+
143+
fortagTypeintagTypes:
144+
textArea.tag_configure(tagType.lower(),tagTypes[tagType])
145+
146+
147+
defkeyDown(event=None):
148+
root.title(f'{applicationName} - *{filePath}')
149+
150+
151+
deftagToggle(tagName):
152+
start,end="sel.first","sel.last"
153+
154+
iftagNameintextArea.tag_names('sel.first'):
155+
textArea.tag_remove(tagName,start,end)
156+
else:
157+
textArea.tag_add(tagName,start,end)
158+
159+
160+
textArea=Text(root,font=f'{fontName} 15',relief=FLAT)
161+
textArea.pack(fill=BOTH,expand=TRUE,padx=padding,pady=padding)
162+
textArea.bind("<Key>",keyDown)
163+
164+
resetTags()
165+
166+
167+
menu=Menu(root)
168+
root.config(menu=menu)
169+
170+
fileMenu=Menu(menu,tearoff=0)
171+
menu.add_cascade(label="File",menu=fileMenu)
172+
173+
fileMenu.add_command(label="Open",command=partial(fileManager,action='open'),accelerator='Ctrl+O')
174+
root.bind_all('<Control-o>',partial(fileManager,action='open'))
175+
176+
fileMenu.add_command(label="Save",command=partial(fileManager,action='save'),accelerator='Ctrl+S')
177+
root.bind_all('<Control-s>',partial(fileManager,action='save'))
178+
179+
fileMenu.add_command(label="Exit",command=root.quit)
180+
181+
182+
formatMenu=Menu(menu,tearoff=0)
183+
menu.add_cascade(label="Format",menu=formatMenu)
184+
185+
fortagTypeintagTypes:
186+
formatMenu.add_command(label=tagType,command=partial(tagToggle,tagName=tagType.lower()))
187+
188+
189+
root.mainloop()

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp