簡體   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