繁体   English   中英

Tkinter:将 (.txt) 文件路径打印到文本小部件和 (.txt) 文件内容到同一 gui 中的滚动文本小部件,只需一个文件对话访问

[英]Tkinter: print (.txt) filepath to text widget AND (.txt) file content to scrolledtext widget in the same gui with one filedialogue access

作为对此的后续问题: Python tkinter - 如何使用 grid() 和使用程序代码将 StringVar() 内容发送到滚动文本框

  1. 我知道如何将文件路径打印到文本小部件字段 GUI。
  2. 我知道如何将文本文件的内容放入 GUI 中的滚动文本小部件字段中。
  3. 我不知道如何同时进行...

我可以在同一个程序中浏览两次,以实现目标; 但这并没有真正实现目标。

  1. 这是我尝试过大小并修改过的其他人的代码:
def browsefunc(): #browse button to search for files
    filename = filedialog.askopenfilename()
    infile = open(filename, 'r')
    content = infile.read()
    pathadd = os.path.dirname(filename)+filename

    pathlabel.delete(0, END)
    pathlabel.insert(0, pathadd)

    return content

Tkinter 中的按钮错误 - 选择文件,添加它们的路径我也是这样做的,这有点不同:

def fd_getfile():
    filetypes = (
        ('sys list file', '*.txt'),
        ('any', '*.*')
    )
    filename_file1 = fd.askopenfilename(
        title='add file1',
        initialdir='src',
        filetypes=filetypes)
file1_entry.insert(tk.END, filename_file1)
    showinfo(
        title='file1 selected',
        message=filename_file1,
    )

def process(*args):
    try:
        # COMMENT: Reset output
        file1.set('')

        # COMMENT: Load files
        with open(file1path.get()) as file1:

  1. 这就是我让它工作的方式......我在任何地方都没有在网上看到任何这样的例子。
def forkscroll():
    mylabelframe = tk.LabelFrame(myframe, text='My Long Text:').pack()
    scroll_w = 30
    scroll_h = 10
    myscrolledtext = scrolledtext.ScrolledText(mylabelframe, width=scroll_w, height=scroll_h, wrap=tk.WORD)
    myscrolledtext.vbar.config(width=20)
    myscrolledtext.grid(sticky='news', row=6, column=0, rowspan=1, columnspan=1, padx=5, pady=5)

# Open a dialogue; select and load a text file; read the text file directly into the scrolledtext widget (box)
    fork = open(filedialog.askopenfilename(), 'r') # it's the same as "infile" above; but it's not a string
    myscrolledtext.insert(tk.END, fork.read()) ### This reads the content of "fork" into the scrolledtext widget
  1. ……做不到。 正如我所说,我可以并行运行这两个进程...浏览两次文件,但每个 function 对看起来相似的代码做了不同的事情。
  forkit = StringVar()
    forkit.set(fork.get())
    mynormaltext = Text(mylabelframe, width = 10, height = 1, wrap=tk.WORD)
    mynormaltext.grid(sticky='news', row=5, column=0, rowspan=1, columnspan=1, padx=5, pady=5)
    mynormaltext.insert(tk.END, forkit.get())

# Even though it does the same thing in one line as it does in three, the outcome is not the same for scrolledtext
#    forkname = filedialog.askopenfilename()
#    forkfile = open(forkname, 'r')
#    fork = forkfile.read()

# above... "fork" is a textIO, but Text can read it...

我查看了 forkname、forkfile 和 fork 这三行,发现它看起来像是 fork=open(filedialog.askopenfilename(), 'r').read() 的简写,这就是我最终获得滚动文本的方式工作......但是这个“fork”在每种情况下都是不同的文件类型......一个是字符串,另一个是“TextIO”或“FilePath”object。 后者适用于滚动文本,但前者不适用。 前者适用于插入文本,但后者不适用。 它们不能在同一个 function 中共存,而且代码似乎不喜欢它们在 same.py 文件中,所以我猜它们应该在不同的类中......但我不知道如何转换这段代码上课。

关于如何实现预期功能的任何想法?

预期的功能是:

  1. 呈现 2 个带有 2 个按钮的标签,每个按钮带有一个字段:一个作为文本小部件字段; 和滚动文本小部件字段。
  2. 单击按钮浏览到文本文件,并将其读入 memory,并将其路径打印到文本小部件字段中
  3. 单击另一个按钮,并将同一文件的内容打印到滚动文本字段中,并将其显示在框架内,并带有一个漂亮的长滚动条。

到目前为止我能得到的最接近的......

对于你问题的第二部分

由于wrap设置,出现了路径不完整的问题。 要解决这个问题,只需更改此字符串:

mypathtext = Text(mylabelframe, width=10, height=1)

您可以使用.replace()方法修复带有反斜杠和正斜杠的功能。

这个怎么样:

from tkinter import *
from tkinter import filedialog
from tkinter import scrolledtext
import os

def browsefunc():
    global content
    filename = filedialog.askopenfilename()
    infile = open(filename, 'r')
    content = infile.read()
    pathadd = filename

    pathtext.delete(0.0, END)
    pathtext.insert(0.0, pathadd)

    contenttext.delete(0.0, END)
    contenttext.insert(0.0, content)

w = Tk()
w.geometry('600x370')

lb1 = Label(text="Select text file")
lb1.place(x=0, y=0)

bt1 = Button(text="Process", command=browsefunc)
bt1.place(x=0, y=40)

pathtext = Text()
pathtext.place(x=0, y=85, width=450, height=20)

contenttext = scrolledtext.ScrolledText()
contenttext.place(x=0, y=120, width=450)

读取文件后,您的数据将位于content变量中。

查看调试器后,发现 TextIO 变量“fork”包含两部分:“<_io.Textwrapper”和“name = C:\blah\blah\blah”

在此处输入图像描述

我得到了 99% 的工作是这样的:

#import os
#import io
from tkinter import *
#from tkinter import ttk
from tkinter import filedialog
from tkinter import scrolledtext
import tkinter as tk
from pathlib import Path
from typing import TextIO


def forkscroll():
    mylabelframe = tk.LabelFrame(myframe, text='My Long Text:').pack()
    scroll_w = 30
    scroll_h = 10
    myscrolledtext = scrolledtext.ScrolledText(mylabelframe, width=scroll_w, height=scroll_h, wrap=tk.WORD)
    myscrolledtext.vbar.config(width=20)
    myscrolledtext.grid(sticky='news', row=6, column=0, rowspan=1, columnspan=1, padx=5, pady=5)

# Open a dialogue; select and load a text file; read the text file directly into the scrolledtext widget (box)
    fork: TextIO = open(filedialog.askopenfilename(), 'r') 
    myscrolledtext.insert(tk.END, fork.read()) ### This reads the content of "fork" into the scrolledtext widget

    forkname = fork.name # works
    mypathtext = Text(mylabelframe, width=10, height=1, wrap=tk.WORD)
    mypathtext.grid(sticky='news', row=5, column=0, rowspan=1, columnspan=1, padx=5, pady=5)
    mypathtext.insert(tk.END, forkname)  # works

#GUI

root = Tk()
root.title('Root Title')
root.geometry('600x300')

myframe = tk.Frame(root, width=300, height=300)
myframe.winfo_toplevel().title('MyFrame Title')
myframe.grid(column=0, row=0, sticky='news')

myforkpath = StringVar()

f1 = Frame(myframe, width=900, height=150) #file1
f1.pack(fill=X, side =TOP)
f2 = Frame(myframe, width=900, height=150) #file2
f2.pack(fill=X, side=BOTTOM)

Label(f1, text="Select text file").grid(row=0, column=0, sticky='e')  # select file button label
run_button = Button(myframe, text="Process", command=forkscroll).pack()
Label(f2, text="put the content of the file in the text scroll box below").grid(row=1, column=0, sticky='s')

myframe.mainloop()

...有一个问题...那 1%

我的笔记本电脑被命名为“Crappy Laptop”(不是真的,但它在路径的那部分名称中有一个空格),因此打印到文本小部件字段的名称路径是:

“C://用户/糟糕”

...我没有完整的路径...应该是“C://Users/Crappy Laptop/Desktop/My/Python/Code/mylongtextfile.txt”

in fact I get forward slashes, and not backslashes... in the Pycharm console window it displays the paths with slashes in each direction: Like this: C.\......\python:exe C.//.. ./.../myfile.py

如何处理空间?

好吧,到目前为止我已经做到了...

    forkname = fork.name # works
# fix the "path with spaces problem"
    newforkname1 = forkname.replace(' ', '_')
    print(newforkname1)
    newforkname2 = newforkname1.replace('/', '\\')
    print(newforkname2)

    mypathtext = Text(mylabelframe, width=10, height=1, wrap=tk.WORD)
    mypathtext.grid(sticky='news', row=5, column=0, rowspan=1, columnspan=1, padx=5, pady=5)
    #mypathtext.insert(tk.END, forkname)  # works
    mypathtext.insert(tk.END, newforkname2)  # works

还没有弄清楚如何显示空格而不是下划线。

这完全不行……

    newforkname1 = forkname.replace(' ', ' '.join(forkname))

这是一个单独的答案,因为我从上一个问题和这个问题中解决了一个问题,但产生了一个新问题:D

我能够使用 StringVar 将文本文件中的字符串内容从一个 function 传递到另一个 function ...

所以我在代码顶部添加了新的 StringVars

reflines_sv = StringVar()
cfglines_sv = StringVar()

然后在 function 中,我打开文本文件,获取内容,并将其传递给字符串,然后传递给字符串变量:

def getref():
    # COMMENT: Get reference file
    Label(frame_input, anchor='w', width=80, text='Reference filepath:', background='#abdbe3').pack(side=TOP, fill=Y)
    ref: TextIO = open(filedialog.askopenfilename(title='add Reference file', initialdir='src', ), 'r')
    reflines = ref.readlines()
    reflines_sv.set(reflines)

    # COMMENT: Get reference file path
    refname = ref.name
    refname_new = refname.replace('/', '\\')
    pathtext_ref = Text(frame_input, width=80, height=1, bg='#f0f0f0')
    pathtext_ref.pack(anchor='n', side=TOP, fill=Y, ipadx=5, ipady=5)
    pathtext_ref.configure(font=("Arial", 9, "italic",))
    pathtext_ref.insert(tk.END, refname_new)
    return reflines_sv

然后在下一个 function 中,我可以检索内容并使用它。

def process():
    try:
        # COMMENT: Reset output
        rdiff.set('')
        tdiff.set('')
        rtmiss.set('')

        reflines = reflines_sv.get()
        cfglines = cfglines_sv.get()

        # COMMENT: Comparing lines
        refhash = dict()
        cfghash = dict()
        different = False

etc...

这样做的好处是我现在可以拥有一个带有单独按钮的向导,用于处理文本文件的不同阶段。

可能有更好的方法可以做到这一点,但我还没有找到。

新的问题是,现在文本文件的内容没有正确输出。

等等... =下面的代码

        for i, value in enumerate(reflines):
            refhash[i] = value
        for i, value in enumerate(cfglines):
            cfghash[i] = value
            contains = value in refhash.values()
            different = different or not contains
            if not contains:
                tdiff.set(tdiff.get() + 'problem line ' + str(i) + ': ' + value) ### <- new problem!
        for i, value in enumerate(reflines):
            contains = value in cfghash.values()
            different = different or not contains
            if not contains:
                rdiff.set(rdiff.get() + 'line ' + str(i) + ': ' + value)
        if not different:
            errmsg.set('no differences')

        if len(reflines) == len(cfglines) and different:
            for i, _ in enumerate(reflines):
                if cfglines[i] != reflines[i]:
                    rtmiss.set(rtmiss.get() + 'line ' + str(i) + '\n')
        else:
            rtmiss.set('files have different number of lines')

        scroll_w = 15
        scroll_h = 5
        myscrolledtext1 = scrolledtext.ScrolledText(frame_input, width=scroll_w, height=scroll_h, wrap=tk.WORD,background='#bbffe6')
        myscrolledtext1.vbar.config(width=20)
        myscrolledtext1.pack(anchor='s', fill=X, side=LEFT, ipadx=5,ipady=5, expand=True)
        myscrolledtext1.insert(tk.END, rdiff.get())

        myscrolledtext2 = scrolledtext.ScrolledText(frame_input, width=scroll_w, height=scroll_h, wrap=tk.WORD, background='#bbffe6')
        myscrolledtext2.vbar.config(width=20)
        myscrolledtext2.pack(anchor='s', fill=X, side=LEFT, ipadx=5,ipady=5, expand=True)
        myscrolledtext2.insert(tk.END, tdiff.get())

        myscrolledtext3 = scrolledtext.ScrolledText(frame_input, width=scroll_w, height=scroll_h, wrap=tk.WORD,background='#bbffe6')
        myscrolledtext3.vbar.config(width=20)
        myscrolledtext3.pack(anchor='s', fill=X, side=LEFT, ipadx=5,ipady=5, expand=True)
        myscrolledtext3.insert(tk.END, rtmiss.get())

    except OSError:
        errmsg.set('failed to load both files')


# COMMENT: Buttons
button_ref = Button(frame_button, text="Browse for ref file", font='50', command=getref).pack(anchor='s', side=BOTTOM, pady=10, ipadx=5, ipady=20)
button_cfg = Button(frame_button, text="Browse for test file", font='50', command=getcfg).pack(anchor='s', side=BOTTOM, pady=10, ipadx=5, ipady=20)

button_process = Button(frame_button, text="Process", font='50', command=process).pack(anchor='s', side=BOTTOM, pady=10, ipadx=5, ipady=20)

它以前没有这样做,当我把它全部放在一个 function 中时,只需一个按钮。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM