前言
最近我比较闲写了一个idle的小plus,发出来分享一下
- 拖动文字(内)
- 拖动文字(外)
- 拖拽打开文件
原理
就是动态打补丁,在导入idle之前就“升级”一下,同时不影响其他效果(包括运行的程序),用到了我之前写的TkContentMoveAndCopyableText,当然,改名为TextPlus并加上了drop部分
实现
idlelib
idlelib.pyshell有一个PyShell,包含方法open可以用idle打开文件。
PATH = "你的文件"
import tkinter
root = tk.Tk()
import idlelib.pyshell
flist = idlelib.pyshell.PyShell(root)
flist.open(PATH)
root.mainloop()
TkinterDnD2
这个模块可以让你的tkinter跨进程支持拖拽。
def _bind_dnd(self):
self.drop_target_register(DND_FILES, DND_TEXT)
self.dnd_bind("<<Drop>>",self._drop)
def _drop(self,e):
data = e.data
if os.path.exists(data):
import idlelib.pyshell
flist = idlelib.pyshell.PyShellFileList(self.master)
flist.open(data)
else:
self.insert("current",data)
源码
# main.py
import tkinter
try:
from TkinterDnD2 import *
root = TkinterDnD.Tk()
root.withdraw()
def getroot(*a,**b):
return root
tkinter.Tk = getroot
except Exception as e:
print("TkinterDnD2 not installed",e)
import TextPlus
tkinter.Text = TextPlus.TextPlus
import idlelib.__main__
# TextPlus.py
import tkinter as tk
import sys
import os
try:
from TkinterDnD2 import *
candnd = 1
except:
candnd = 0
class TextPlus(tk.Text):
def __init__(self,*a,**b):
super().__init__(*a,**b)
self.content=""
self.draging=False
self.ctrl=False
self.breakpoint=()
self.bind("<KeyPress>",self.ctrldown,1)
self.bind("<KeyRelease>",self.ctrlup,1)
self.bind("<B1-Motion>",self.handledrag,1)
self.bind("<Button-1>",self.handledown,1)
self.bind("<ButtonRelease-1>",self.handleup,1)
self._bind_dnd()
def ctrlup(self,e):
if e.keycode==17:
self.ctrl=False
def ctrldown(self,e):
if e.keycode==17:
self.ctrl=True
def handledown(self,e):
try:
if self.insel(e):
self.content = self.get("sel.first","sel.last")
self.sel = (self.index("sel.first") , self.index("sel.last"))
return "break"
except:
self.content=""
def handledrag(self,e):
if self.content:
self.draging=True
self.mark_set("insert","@%d,%d"%(e.x,e.y))
return "break"
def handleup(self,e):
if self.draging:
if not self.ctrl:
self.delete(*self.sel)
self.insert("insert",self.content)
self.draging=False
self.content=""
else:
if self.content:
self.tag_remove("sel","1.0","end")
self.content=""
self.mark_set("insert","@%d,%d"%(e.x,e.y))
def insel(self,e):
try:
y1,x1=map(int,self.index("sel.first" ).split("."))
y2,x2=map(int,self.index("@%d,%d"%(e.x,e.y)).split("."))
y3,x3=map(int,self.index("sel.last" ).split("."))
if y3>y2>y1:
return 1
if y2==y1 and x2>x1:
return 1
elif y2==y3 and x2<x3:
return 1
except:
pass
def _bind_dnd(self):
try:
assert candnd
self.drop_target_register(DND_FILES, DND_TEXT)
self.dnd_bind("<<Drop>>",self._drop)
except:
pass
def _drop(self,e):
data = e.data
if os.path.exists(data):
import idlelib.pyshell
flist = idlelib.pyshell.PyShellFileList(self.master)
flist.open(data)
else:
self.insert("current",data)
def test():
root=tk.Tk()
root.title("TextPlus")
TextPlus().pack(expand=1,fill="both")
root.mainloop()
if __name__ == "__main__":
test()
当然,你还可以参考这篇,给IDLE加入脱离系统样式的窗口。
本文发于CSDN于 2022/4/2 9:23