2201_75335496 2024-06-20 23:27 采纳率: 76.5%
浏览 6
已结题

python tkinter文件树添加entry输入框如何回车跳转到输入的路径?

如何将代码中的pse.bind补全(文件树功能实现 -> 路径显示框,第559行),实现换行后再文件树内显示输入的路径下的文件,如果输入路径不存在就print报错?

import sys,os
import tkinter as tk
from tkinter import ttk,scrolledtext
from tkinter.messagebox import askyesnocancel as aync,showwarning as warn,showinfo as info,showerror as serr
from tkinter.filedialog import asksaveasfilename as asfn
from PIL import ImageTk,Image
from tkinter import PhotoImage
import easygui
import string
import os
import time
import ctypes
from functools import partial
import chardet
import re
import idlelib.colorizer as idc
import idlelib.percolator as idp
import subprocess
import signal
import threading
import psutil
import math
import random
from CUTool import infoTool
#获取当前文件位置
pythonRunningPath = os.getcwd()

#获取配置文件
default_cfgdic = {"tcfgTWv":1, # 自动换行
                  "tcfgRSv":1, # 自动保存
                  "lofPath":"" # 上一次打开的文件
                  }
if os.path.exists("./pythonRunning.ini"):
    with open("./pythonRunning.ini","r",encoding = "utf-8") as f:
        cfgdic = f.read().split("\n")
        cfgdics = {}
        for i in cfgdic:
            cfgdics[i.split(":")[0]] = i.split(":")[1]
        cfgdic = cfgdics
        del cfgdics
else:
    with open("./pythonRunning.ini","w",encoding = "utf-8") as f:
        f.write(f"tcfgTWv:{default_cfgdic['tcfgTWv']}\ntcfgRSv:{default_cfgdic['tcfgRSv']}")
        f.write(f"\nlofPath:{default_cfgdic['lofPath']}")
    cfgdic = default_cfgdic

#带行数文本框实现
class TextLineNumbers(tk.Canvas):
    def __init__(self,*args, **kwargs):
        tk.Canvas.__init__(self, *args, **kwargs)
        self.textwidget = None
    def attach(self, text_widget):
        self.textwidget = text_widget
 
    def redraw(self, *args):
 
        '''redraw line numbers'''
        self.delete("all")
        # ====================self.textwidget.index("@0,0") @0,0表示最接近左上角的行信息.
        i = self.textwidget.index("@0,0")  # 找到0行0列的信息. ref: 参考文档:    https://tkdocs.com/shipman/text-index.html
        hang, lie = i.split('.')
        while True:
            dline = self.textwidget.dlineinfo(i)
            hang, lie = i.split('.')  # 计算上面i行的信息.    self.textwidget.get(i)
            debug222 = self.textwidget.get(i)  # 这里面显示滚动之后的左上角第一个字.#这时候我们读入的是1.4
            if dline is None: break  # Return tuple (x,y,width,height,baseline) giving the bounding box        and baseline position of the visible part of the line containing        the character at INDEX.
            if lie == '0':  # ===首列才画行号.
                y = dline[1]
                linenum = hang  # 行信息
                self.create_text(1, y, anchor="nw", text="{0:>2}".format(linenum),font = font)  # 创建行号. 2是x索引.
            # i = self.textwidget.index("%s+1line" % i) #然后计算下一行.
            i = self.textwidget.index(str(int(hang) + 1) + '.' + '0')  # 然后计算下一行.
        self.config(width = 50 / 4 * len(str(hang)) + 20)
class CustomText(tk.Text):
    def __init__(self,*args, **kwargs):
        tk.Text.__init__(self,*args, **kwargs,font = font,autoseparators=False, undo=True,maxundo=codeMaxUndo)
        self.config(wrap = tk.NONE)
        '''
        # create a proxy for the underlying widget
        self._orig = self._w + "_orig"
        self.tk.call("rename", self._w, self._orig)
        self.tk.createcommand(self._w, self._proxy)'''
        self.bind('<Key>',self.callback)
        #绑定撤回/取消撤回事件
        self.bind("<Control-KeyPress-Z>",self.undo)
        self.bind("<Control-KeyPress-Y>",self.redo)
    def undo(self,event = None):
        self.edit_undo()
    def redo(self,event = None):
        self.edit_redo()
    def callback(self,event = None):
        self.edit_separator()
    def copy(self,event = None):
        self.event_generate("<<Copy>>")
    def paste(self,event = None):
        self.event_generate("<<Paste>>")
    def cut(self,event = None):
        self.event_generate("<<Cut>>")
        
    def _proxy(self, *args): #发送自定义信号change
        # let the actual widget perform the requested action
        result=1
        try:
            cmd = (self._orig,) + args
            result = self.tk.call(cmd)
 
            # generate an event if something was added or deleted,
            # or the cursor position changed
            if (args[0] in ("insert", "replace", "delete") or
                args[0:3] == ("mark", "set", "insert") or
                args[0:2] == ("xview", "moveto") or
                args[0:2] == ("xview", "scroll") or
                args[0:2] == ("yview", "moveto") or
                args[0:2] == ("yview", "scroll")
            ):
                self.event_generate("<<Change>>", when="tail")#触发change信号.
        except:
            pass
        # return what the actual widget returned
        return result
 
class Example(tk.Frame):
    def __init__(self,*args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        self.text = CustomText(self)
        self.vsb = tk.Scrollbar(self, orient="vertical", command=self.text.yview)#竖直方向的滑动杆.
        self.xsb = tk.Scrollbar(self,orient = tk.HORIZONTAL,command = self.text.xview)
        self.text.configure(xscrollcommand = self.xsb.set,yscrollcommand=self.vsb.set)
        
        self.linenumbers = TextLineNumbers(self, width=30)#创建行号工具
        self.linenumbers.attach(self.text) # 绑定行号工具到text空间.
 
        self.vsb.pack(side="right", fill="y")
        self.xsb.pack(side = tk.BOTTOM,fill = tk.X)
        self.linenumbers.pack(side="left", fill="y")
        self.text.pack(side="right", fill="both", expand=True)
 
        self.text.bind("<<Change>>", self._on_change)#绑定修改到重新绘制linenumber
        self.text.bind("<Configure>", self._on_change)
        
    def _on_change(self, event):
        self.linenumbers.redraw()
    def xview(self,*args):
        CustomText.xview(*args)

#输出文本框实现
class OutputTextLineNumbers(tk.Canvas):
    def __init__(self,*args, **kwargs):
        tk.Canvas.__init__(self, *args, **kwargs)
        self.textwidget = None
    def attach(self, text_widget):
        self.textwidget = text_widget
 
    def redraw(self, *args):
 
        '''redraw line numbers'''
        self.delete("all")
        # ====================self.textwidget.index("@0,0") @0,0表示最接近左上角的行信息.
        i = self.textwidget.index("@0,0")  # 找到0行0列的信息. ref: 参考文档:    https://tkdocs.com/shipman/text-index.html
        hang, lie = i.split('.')
        while True:
            dline = self.textwidget.dlineinfo(i)
            hang, lie = i.split('.')  # 计算上面i行的信息.    self.textwidget.get(i)
            debug222 = self.textwidget.get(i)  # 这里面显示滚动之后的左上角第一个字.#这时候我们读入的是1.4
            if dline is None: break  # Return tuple (x,y,width,height,baseline) giving the bounding box        and baseline position of the visible part of the line containing        the character at INDEX.
            if lie == '0':  # ===首列才画行号.
                y = dline[1]
                linenum = infoTool.infoget("",prints = False)  # 行信息
                self.create_text(1, y, anchor="nw", text="{0:>2}".format(linenum),font = font)  # 创建行号. 2是x索引.
            # i = self.textwidget.index("%s+1line" % i) #然后计算下一行.
            i = self.textwidget.index(str(int(hang) + 1) + '.' + '0')  # 然后计算下一行.
        self.config(width = 50 / 4 * len(str(hang)) + 20)
class OutputText(tk.Frame):
    def __init__(self,*args, **kwargs):
        tk.Frame.__init__(self, *args, **kwargs)
        self.text = CustomText(self)
        self.vsb = tk.Scrollbar(self, orient="vertical", command=self.text.yview)#竖直方向的滑动杆.
        self.xsb = tk.Scrollbar(self,orient = tk.HORIZONTAL,command = self.text.xview)
        self.text.configure(xscrollcommand = self.xsb.set,yscrollcommand=self.vsb.set)
        
        self.linenumbers = OutputTextLineNumbers(self, width=50)#创建行号工具
        self.linenumbers.attach(self.text) # 绑定行号工具到text空间.
 
        self.vsb.pack(side="right", fill="y")
        self.xsb.pack(side = tk.BOTTOM,fill = tk.X)
        self.linenumbers.pack(side="left", fill="y")
        self.text.pack(side="right", fill="both", expand=True)
 
        self.text.bind("<<Change>>", self._on_change)#绑定修改到重新绘制linenumber
        self.text.bind("<Configure>", self._on_change)
        
    def _on_change(self, event):
        self.linenumbers.redraw()
    def xview(self,*args):
        CustomText.xview(*args)

#硬盘获取
def hetDiskList():
    l = []
    for c in string.ascii_uppercase:
        disk = c + ':\\'
        if os.path.isdir(disk):
            l.append(disk)
            #drive_node = tree_view.insert(pc_node, 'end', text=disk, image=drive_image)
    return l
#获取选中的节点路径中的文件与文件夹
def node_path(node):
    path = ''
    parent = node
    while parent:
        node_text = tree_view.item(parent, 'text')
        if len(path) > 0:
            path = os.path.join(node_text, path)
        else:
            path = node_text
        parent = tree_view.parent(parent)
    return path
#在文件夹中添加节点
def insert_child_items(parent_node):
    path = node_path(parent_node)
    dirlist = []
    filelist = []
    if os.path.isdir(path):
        try:
            dir_items = os.scandir(path)
            for item in dir_items:
                if item.name == "$RECYCLE.BIN" or item.name == "$Recycle.Bin":
                    tree_view.insert(parent_node, 'end', text=item.name, image=recycle_image)
                else:
                    if item.is_dir() and ('.$'.find(item.name[0])<0):
                        dirlist.append(item.name)
                    else:
                        if not "$" in item.name:
                            filelist.append(item.name)
                        else:
                            dirlist.append(item.name)
            #添加节点
            dirlist.sort()
            filelist.sort()
            for item in dirlist:
                tree_view.insert(parent_node, 'end', text=item, image=folder_image)
            for item in filelist:
                tree_view.insert(parent_node, 'end', text=item, image=file_image)
        except Exception as e:
            print(e)
#展开节点事件
def open_node(event):
    focus = tree_view.focus()
    for node in tree_view.get_children(focus):
        insert_child_items(node)
#关闭节点事件
def close_node(event):
    focus = tree_view.focus()
    for node in tree_view.get_children(focus):
        children = tree_view.get_children(node)
        for c in children:
            tree_view.delete(c)
#选择节点事件
def select_node(event):
    if tree_view.focus() == "I001":
        print("=I001",node_path(tree_view.focus()),tree_view.focus())
        return
    path = node_path(tree_view.focus())
    pse.delete(0,tk.END)
    pse.insert(0,path)
    print(path)
#窗口关闭事件
def closewin():
    if saveFile():
        win.destroy()
        try:
            for child in find_child_processes(pypro.pid):
                child.terminate()
            pypro.kill()
        except:pass
        print("\n---退出程序---")
        os._exit(0)

#运行py程序函数
def find_child_processes(pid):
    for process in psutil.process_iter():
        if process.ppid() == pid:
            yield process
def whileCheck():
    while True:
        if pypro.poll() != None:
            sb.config(state = tk.DISABLED)
            rb.config(state = tk.NORMAL)
            runfm.delete(0,1)
            runfm.add_command(label = "运行",command = partial(runPythonFile,"run"))
            runfm.add_command(label = "终止",command = partial(runPythonFile,"stop"),state = tk.DISABLED)
            print("---程序运行子进程结束---")
            lineNum = 0
            return
def runPythonFile(mod = "run"):
    global pypro,openFileDir,lineNum
    lineNum = 0
    def read_output(pipe,mod):
        global lineNum
        print(f"StartReadOutput:mod={mod}")
        if mod == "err":
            cst = cset
        else:
            cst = csot
        cst.tag_configure("gray", foreground="lightgray")
        cst.tag_configure("blue", foreground="blue")
        for i in iter(pipe.readline,b''):
            line = i.strip().decode("utf-8") + "\n"
            print(f"std{mod} >> {line}",end = "")
            cst.config(state = tk.NORMAL)
            cst.insert(tk.END,"[%05d]" % lineNum,"gray")
            cst.insert(tk.END,line,mod)
            cst.config(state = tk.DISABLED)
            cst.see(tk.END)
            win.update()
            lineNum += 1
            if lineNum >= 99999:
                lineNum = 0
            #time.sleep(0.05)
        #pypro.stdout.close()
        cst.config(state = tk.NORMAL)
        cst.insert(tk.END,"----------Shell----------","blue")
        cst.config(state = tk.DISABLED)
        cst.see(tk.END)
        print(f"\n---{mod}输出流结束---\n")
    if mod == "stop":
        for i in find_child_processes(pypro.pid):
            i.terminate()
        pypro.kill()
    elif mod == "run":
        saveFile()
        rb.config(state = tk.DISABLED)
        sb.config(state = tk.NORMAL)
        runfm.delete(0,1)
        runfm.add_command(label = "运行",command = partial(runPythonFile,"run"),state = tk.DISABLED)
        runfm.add_command(label = "终止",command = partial(runPythonFile,"stop"))
        #清空文本框
        csot.config(state = tk.NORMAL)
        csot.delete("1.0",tk.END)
        csot.config(state = tk.DISABLED)
        cset.config(state = tk.NORMAL)
        cset.delete("1.0",tk.END)
        cset.config(state = tk.DISABLED)
        if openFileDir["path"] and os.path.splitext(os.path.basename(openFileDir["path"]))[1] == ".py":
            if not os.path.exists(openFileDir["path"]):
                serr(title = "错误",message = f"错误:\n{openFileDir['path']}\n文件不存在!")
                return
            try:
                pypro = subprocess.Popen([f"{pythonRunningPath}\\python37\\python.exe",openFileDir["path"]],
                                         stdout = subprocess.PIPE,
                                         stderr = subprocess.PIPE,
                                         shell = False,
                                         cwd = os.path.dirname(openFileDir["path"]),
                                         bufsize = 0)
                t1 = threading.Thread(target=read_output, args=(pypro.stdout,"out"))
                t2 = threading.Thread(target=read_output, args=(pypro.stderr,"err"))
                threading.Thread(target = whileCheck).start()
                t1.start()
                t2.start()
            except Exception as e:
                print(e)
                serr(title = "错误",message = f"运行出错!\n{e}")
                return
#保存文件函数
def saveFile():
    if not isAutoSave:
        a = aync(title = "警告",message = "是否保存?")
    else:
        a = True
    if a:
        try:os.makedirs(openFileDir["path"])
        except:pass
        savepath = openFileDir["path"]
        saveencoding = openFileDir["encoding"]
        # 如果目录不存在或者不是打开的文件询问保存位置和编码
        if (not openFileDir["path"]) or (not os.path.exists(openFileDir["path"])):
            if code.text.get("1.0",tk.END) == "\n":return True
            savepath = asfn(title = "请选择保存路径")
            print(savepath)
            if not savepath:return True
            #询问编码
            if not saveencoding:
                saveencoding = easygui.buttonbox("请选择编码","请选择编码",("GBK","GB2312","utf-8","ascii","[bit]"))
            print("保存文件-选择完毕")
            if not (savepath and saveencoding):
                print(f"未选择保存路径或编码,退出函数(savepath:'{savepath}',saveencoding:'{saveencoding}')")
                return None
        if saveencoding == "[bit]":
            with open(savepath,"wb") as f:
                f.write(code.text.get("1.0",tk.END))
        else:
            with open(savepath,"w",encoding = saveencoding) as f:
                f.write(code.text.get("1.0",tk.END))
    elif a == None:
        return None
    return True
#--------------------创建窗口--------------------#
win = tk.Tk()
win.title("pythonRunning")
winsize = (1200,700)
scrsize = (win.winfo_screenwidth(),win.winfo_screenheight())
win.geometry("{}x{}+{}+{}".format(*winsize,(scrsize[0] - winsize[0]) // 2,(scrsize[1] - winsize[1]) // 2))
#win.resizable(0,0)
#win.maxsize(width=scrsize[0], height=scrsize[1])
win.protocol('WM_DELETE_WINDOW',closewin)
win.grid_rowconfigure(0, weight=1)
win.grid_columnconfigure(0, weight=1)

#告诉操作系统使用程序自身的dpi适配
ctypes.windll.shcore.SetProcessDpiAwareness(1)
#获取屏幕的缩放因子
ScaleFactor=ctypes.windll.shcore.GetScaleFactorForDevice(0)
#设置程序缩放
win.tk.call('tk', 'scaling', ScaleFactor/75)

#-------------------窗口组件绘制------------------#
pwin = tk.PanedWindow(win, orient=tk.HORIZONTAL,sashrelief = "raised",sashwidth = 5,relief = "sunken")
pwinr = tk.PanedWindow(pwin,orient = tk.VERTICAL,sashrelief = "raised",sashwidth = 5,relief = "sunken")
pwin.grid(row=0, column=0, sticky='wnse')
#文件树
tree_area = tk.Frame(pwin)
tree_area.grid_rowconfigure(1, weight=1)
tree_area.grid_columnconfigure(0, weight=1)
#代码框
font = ("Consolas",14)
codeMaxUndo = 2200000000
print(f"codeMaxUndo:{codeMaxUndo}, font:{font}")

cf = ttk.Labelframe(pwinr,text = "代码")
cf.pack(padx = 10,pady = 10)

code = Example(cf)
#code.text.bind("<Key>",highLightCode)
idc.color_config(code.text)
code.text.focus_set()
code.text.config(bg='white',fg='black')
p = idp.Percolator(code.text)
d = idc.ColorDelegator()
p.insertfilter(d)
#code.config(yscrollcommand = cscr.set)
#line.config(yscrollcommand = cscr.set)

code.pack(fill = tk.BOTH)

pwinr.add(cf,minsize = 20,height = 450,padx = 5,pady = 5)
#运行框
rf = ttk.Labelframe(pwinr,text = "运行(某些程序可能无法显示输出,输出流可能会卡顿)")
rbf = tk.Frame(rf)
rb = ttk.Button(rbf,text = "运行",command = partial(runPythonFile,"run"),state = tk.DISABLED)
sb = ttk.Button(rbf,text = "终止",command = partial(runPythonFile,"stop"),state = tk.DISABLED)
cstpw = tk.PanedWindow(rf,orient=tk.HORIZONTAL,sashrelief = "raised",sashwidth = 5,relief = "sunken")
csof = tk.Frame(cstpw)
csol = tk.Label(csof,text = "stdout:",anchor = tk.W)
csot = tk.Text(csof,state = tk.DISABLED,font = font,wrap = tk.NONE,fg = "black")
cxso = tk.Scrollbar(csof, orient=tk.HORIZONTAL, command=csot.xview)
cyso = tk.Scrollbar(csof,orient = tk.VERTICAL,command = csot.yview)
csot.configure(xscrollcommand = cxso.set,yscrollcommand=cyso.set)

csef = tk.Frame(cstpw)
csel = tk.Label(csef,text = "stderr:",anchor = tk.W)
cset = tk.Text(csef,state = tk.DISABLED,font = font,wrap = tk.NONE,fg = "red")
cxse = tk.Scrollbar(csef, orient=tk.HORIZONTAL, command=cset.xview)
cyse = tk.Scrollbar(csef,orient = tk.VERTICAL,command = cset.yview)
cset.configure(xscrollcommand = cxse.set,yscrollcommand=cyse.set)

cstpw.add(csof,width = 430,minsize = 20)
cstpw.add(csef,minsize = 20)

rbf.pack(side = tk.TOP,fill = tk.X)
rb.pack(side = tk.LEFT)
sb.pack(side = tk.LEFT)

cstpw.pack(fill = tk.BOTH)

csol.pack(fill = tk.X)
cxso.pack(side = tk.BOTTOM,fill = tk.X)
cyso.pack(side="right", fill="y")
csot.pack(fill = tk.BOTH)

csel.pack(fill = tk.X)
cxse.pack(side = tk.BOTTOM,fill = tk.X)
cyse.pack(side="right", fill="y")
cset.pack(fill = tk.BOTH)
pwinr.add(rf,minsize = 20,padx = 5,pady = 5)


#将组件添加到pwin里
pwin.add(tree_area,minsize = 100,width = 300)
pwin.add(pwinr,minsize = 100)

#--------------------窗口menu--------------------#
menu = tk.Menu(win)
win.config(menu = menu)

filem = tk.Menu(menu, tearoff=False)
menu.add_cascade(label='File', menu=filem)
filem.add_command(label="Open", command = partial(print,"Open"))
filem.add_command(label="Save", command = saveFile)
filem.add_separator()
filem.add_command(label="Delete", command = partial(print,"Delete"))
filem.add_command(label="Create", command = partial(print,"Create"))
filem.add_command(label="Exit", command=win.quit)

editm = tk.Menu(menu,tearoff = False)
menu.add_cascade(label='Edit', menu=editm)
editm.add_command(label = "Undo",command = code.text.undo)
editm.add_command(label = "Redo",command = code.text.redo)
editm.add_command(label = "Copy",command = code.text.copy)
editm.add_command(label = "Paste",command = code.text.paste)
editm.add_command(label = "Cut",command = code.text.cut)
editm.add_separator()

tcfgm = tk.Menu(menu,tearoff = False)
menu.add_cascade(label='Config', menu=tcfgm)
def textWrap():
    global tcfgTWv
    print(tcfgTWv.get())
    if tcfgTWv.get() == 1:
        #tcfgTWv.set(1)
        code.text.config(wrap = tk.WORD)
    else:
        #tcfgTWv.set(0)
        code.text.config(wrap = tk.NONE)
    win.update()
isAutoSave = False
def reIsSave():
    global isAutoSave
    if tcfgRSv.get():
        isAutoSave = True
    else:
        isAutoSave = False

tcfgTWv = tk.IntVar()
tcfgRSv = tk.IntVar()
tcfgTWv.set(int(cfgdic["tcfgTWv"]))
tcfgRSv.set(int(cfgdic["tcfgRSv"]))
if int(cfgdic["tcfgTWv"]):textWrap()
if int(cfgdic["tcfgRSv"]):reIsSave()
tcfgm.add_checkbutton(label = "自动换行",command = textWrap,variable = tcfgTWv)
tcfgm.add_checkbutton(label = "自动保存",command = reIsSave,variable = tcfgRSv)

runfm = tk.Menu(menu,tearoff = False)
menu.add_cascade(label='Run', menu=runfm)
runfm.add_command(label = "运行",command = partial(runPythonFile,"run"),state = tk.DISABLED)
runfm.add_command(label = "终止",command = partial(runPythonFile,"stop"),state = tk.DISABLED)

#------------------文件树功能实现------------------#
#加载图像
cur_path = os.path.abspath(os.path.dirname(__file__))
pc_image = PhotoImage(file=cur_path + '\\images\\pc.png')
drive_image = PhotoImage(file=cur_path + '\\images\\drive.png')
folder_image = PhotoImage(file=cur_path + '\\images\\folder.png')
file_image = PhotoImage(file=cur_path + '\\images\\file.png')
recycle_image = PhotoImage(file = cur_path + "\\images\\recycle.png")
#路径显示框
psf = tk.Frame(tree_area)
psl = ttk.Label(psf,text = "路径")
pse = ttk.Entry(psf)
pse.bind("<Enter>",)
psf.grid(row=0, column=0, sticky = "ew")
psl.grid(row = 0,column = 0)
pse.grid(row = 0,column = 1,sticky = "ew")
psf.grid(row = 0,column = 0,sticky = "ew",columnspan = 2)
psf.grid_columnconfigure(1,weight = 1)
#文件树组件
tree_view = ttk.Treeview(tree_area, show='tree', selectmode='browse')
tree_view.grid(row=1, column=0, sticky='nsew')
#滚动条
scroll_ty = tk.Scrollbar(tree_area, orient=tk.VERTICAL, command=tree_view.yview)
scroll_ty.grid(row=1, column=1, sticky="ns")
tree_view['yscrollcommand']=scroll_ty.set
#pc图标(初始内容)
pc_node= tree_view.insert('', 'end',
                          text=os.environ.get('COMPUTERNAME'),
                          image=pc_image,
                          open = False)
#添加硬盘节点(pc节点内)
for i in hetDiskList():
    drive_node = tree_view.insert(pc_node, 'end', text=i, image=drive_image)

#-------------------获取传入参数-------------------#
def getArgv():
    try:
        print("传入的内容:",sys.argv)
        if len(sys.argv) > 2:
            print(f"传入了 {len(sys.argv) - 1} 个文件,当前打开 {sys.argv[1]} 文件")
        openfilepath = sys.argv[1]
        print("传入的文件:",openfilepath)
        if not os.path.exists(openfilepath):
            print("该文件不存在!")
            serr("pythonRunning-Error",f"传入的文件{openfilepath}不存在!")
            try:win.destroy()
            except:pass
            os._exit(0)
        return openfilepath
    except:
        print("没有传参")
        return None

#选择文件函数(配合打开文件函数openFile使用)
def chooseFile(event):
    focus = tree_view.focus()
    path = node_path(focus)
    if os.path.isfile(path):
        openFile(path)

#打开文件函数
openFileDir = {"path":None,"encoding":None,"file":None}
def get_encoding(file):# 获取文件编码类型
    # 二进制方式读取,获取字节数据,检测类型
    try:
        with open(file, 'rb') as f:
            data = f.read()
            return chardet.detect(data)['encoding']
    except Exception as e:
        print(f"Err:{e}")

def openFile(path):
    global fileEncoding,openFileDir
    print("要打开的文件:",path)
    if not os.path.isfile(path):
        print("不是一个有效的文件!")
        serr(title = "错误",message = f"{path}\n不是一个有效的文件!")
        return
    if not os.path.exists(path):
        print("文件不存在!")
        serr(title = "错误",message = f"{path}\n文件不存在!")
        return
    fileEncoding = get_encoding(path)
    print("文件编码:",fileEncoding)
    print(fileEncoding)
    if not fileEncoding:
        fileEncoding = easygui.buttonbox("请选择编码","请选择编码",("GBK","GB2312","utf-8","ascii","[bit]"))
    if not fileEncoding:
        print(f"未选择编码,退出函数(fileEncoding:{fileEncoding})")
        return
    print(fr"'{code.text.get('1.0',tk.END)}'")
    ttt = """'
'""".replace("'","")
    if code.text.get("1.0",tk.END) != "\n" or code.text.get("1.0",tk.END) != ttt:
        saveFile()
    print("基本检查完毕,可以打开文件")
    try:
        if fileEncoding == "[bit]":
            file = open(path,"rb")
        else:
            file = open(path,"r",encoding = fileEncoding)
        code.text.delete("1.0",tk.END)
        code.text.insert(tk.END,str(file.read()))
        code.linenumbers.redraw()
        openFileDir = {"path":path,"encoding":fileEncoding,"file":file}
        win.title(f"pythonRunning - {path}")
        cf.config(text = f"代码 - {path}")
    except Exception as e:
        print(f"打开文件失败!Err:{e}")
        serr(title = "错误",message = f"打开文件失败!\nErr:{e}")
    print("文件已打开!")
    rb.config(state = tk.NORMAL)
    runfm.delete(0)
    runfm.add_command(label = "运行",command = partial(runPythonFile,"run"))

#如有传参打开文件
openfilepath = getArgv()
if openfilepath:
    openFile(openfilepath)

#绑定事件
tree_view.bind('<<TreeviewSelect>>', select_node)
tree_view.bind('<<TreeviewOpen>>', open_node)
tree_view.bind('<<TreeviewClose>>', close_node)
tree_view.bind("<Double-Button-1>",chooseFile)

#窗口内快捷键
def WINrunPythonFile(event = None):
    if str(rb.cget("state")) == "normal":runPythonFile("run")
def WINstopPythonFile(event = None):
    print(sb.cget("state"))
    if str(sb.cget("state")) == tk.NORMAL:runPythonFile("stop")
win.bind("<F9>",WINrunPythonFile)
win.bind("<Control-Alt-F9>",WINstopPythonFile)

def WINsaveFile(event = None):saveFile()
win.bind("<Control-S>",WINsaveFile)

#打开上一次的文件
if cfgdic["lofPath"]:
    openFile(cfgdic["lofPath"])

win.mainloop()
  • 写回答

2条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-06-20 23:27
    关注

    引自免费微信小程序:皆我百晓生

    你的代码已经实现了一个基本的文件树和文本编辑器的功能,但似乎你希望实现的功能是在文件树中输入路径,然后按下回车后,程序能够跳转到输入的路径,并在文件树中显示该路径下的文件。

    要实现这个功能,你需要对Entry框的<Return>事件进行绑定,并在事件处理函数中调用openFile函数。

    在你的代码中,Entry框的实例是pse,所以你需要绑定<Return>事件到pse

    以下是修改后的代码:

    # ...
    
    # 路径显示框
    psf = tk.Frame(tree_area)
    psl = ttk.Label(psf,text = "路径")
    pse = ttk.Entry(psf)
    
    # 绑定 <Return> 事件
    pse.bind("<Return>", lambda event: openFile(pse.get()))
    
    psf.grid(row=0, column=0, sticky = "ew")
    psl.grid(row = 0,column = 0)
    pse.grid(row = 0,column = 1,sticky = "ew")
    psf.grid(row = 0,column = 0,sticky = "ew",columnspan = 2)
    psf.grid_columnconfigure(1,weight = 1)
    
    # ...
    

    这段代码会在Entry框中输入的内容被按下回车时,调用openFile函数,并传入Entry框中的文本作为路径。

    另外,你提到需要实现换行后再文件树内显示输入的路径下的文件,如果输入路径不存在就print报错。这个需求已经在你的代码中实现了,因为openFile函数在打开文件之前会检查文件是否存在。如果文件不存在,它会打印一个错误消息。

    注意,你需要确保openFile函数在接收到路径后能够正确地打开文件,并更新文件树以显示路径下的文件。这个部分已经在你的代码中实现了,但你需要确保它工作正常。

    最后,如果你的程序需要处理路径不存在的情况,你可能需要在openFile函数中添加额外的错误处理代码,例如,如果路径不存在,显示一个错误消息,而不是直接打印错误。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 7月6日
  • 已采纳回答 6月28日
  • 创建了问题 6月20日

悬赏问题

  • ¥20 wpf datagrid单元闪烁效果失灵
  • ¥15 券商软件上市公司信息获取问题
  • ¥100 ensp启动设备蓝屏,代码clock_watchdog_timeout
  • ¥15 Android studio AVD启动不了
  • ¥15 陆空双模式无人机怎么做
  • ¥15 想咨询点问题,与算法转换,负荷预测,数字孪生有关
  • ¥15 C#中的编译平台的区别影响
  • ¥15 软件供应链安全是跟可靠性有关还是跟安全性有关?
  • ¥15 电脑蓝屏logfilessrtsrttrail问题
  • ¥20 关于wordpress建站遇到的问题!(语言-php)(相关搜索:云服务器)