【问题标题】:Tkinter reading row in order from a csv filesTkinter 从 csv 文件中按顺序读取行
【发布时间】:2019-10-05 00:22:38
【问题描述】:

我正在尝试为某些设备创建故障排除程序,有一个输入框使用您的关键字转到正确的框架,它工作正常,但我需要一些帮助才能从 csv 文件中读取每个单独的步骤具体问题。为此,我制作了一个读取 csv 文件中第一步的按钮,但是,我想制作另一个名为“Next Step”的按钮,每次单击时都会显示 csv 文件中的下一步。我也想知道我怎样才能摆脱“第一步”按钮,这样就不会混淆,这样才有意义。我已经尝试分配一个等于 True 的变量并进行了一个 while 循环来实现它,因此该按钮仅在变量设置为 true 时才显示,这根本不起作用。任何关于如何使这项工作的想法,一切都非常感谢。

这是我的代码

class wetDevice(tk.Frame):

def __init__(self, parent, controller):
    tk.Frame.__init__(self, parent)
    self.controller = controller
    label = tk.Label(self, text="How to fix a wet phone", fg="purple", font=controller.title_fontT)
    label.pack(side="top", fill="x", pady=10)


    def stepOne():
        with open("Wet Device.csv", "r") as f:
            csvreader = csv.reader(f, delimiter=",")
            for row in csvreader:
                if "1" in row[0]:
                    test = str(row[1])
                    stepOneL = tk.Label(self, text=test)
                    stepOneL.place(x = 10, y = 70, width = 500, height = 20)

    #def nextStep():



    stepOneB = tk.Button(self, text="First Step",
                         command=lambda: stepOne())
    stepOneB.place(x = 230, y = 130, width = 60, height = 20)


    mButton = tk.Button(self, text="Go to the Main Troubleshoot Menu",
                       command=lambda: controller.show_frame("MainTMenu"))
    mButton.place(x = 285, y = 210, width = 200, height = 25)  

csv 文件采用这种格式(只需 5 个步骤):

Step, Instructions
1, instruction
2, instruction
3, instruction
4, instruction
5, instruction

如果你们能帮助我打开同一项目文件夹中另一个文件夹中的 csv 文件,我也将不胜感激。

非常感谢任何帮助

【问题讨论】:

  • 你的问题不是很清楚,而且你给出的代码不起作用,我已经编辑了它,所以它会起作用,但它似乎仍然不能像你解释的那样起作用做。请确保您提供可行的代码。

标签: python python-3.x csv tkinter


【解决方案1】:

您可以将 csvreader 添加到对象上,获取 init 方法中的第一行,将其添加到窗口并在每次按下下一步按钮时引用该对象。然后您可以一次访问一个 csv 元素,而不需要例如遍历所有行以找到带有row[0] = "1" 的行,并且可以从您离开的地方挑选。

...
self.csvreader = csv.reader(f, delimiter=",")
data = next(self.csvreader)
# set text with data
...

def nextStep():
    data = next(self.csvreader)
    # change text with data

请记住,当 csv 用尽时,它会引发异常。

【讨论】:

    【解决方案2】:

    你的代码有很多问题。

    你不能在同一个框架中使用.pack().place()

    wetDevice 类的__init__() 中,您有时使用.pack(),有时使用.place()。所以所有放置的元素都不会显示在您的窗口中。

    只需将这些元素更改为 .place().pack()

    我已对您的代码进行了调整,使其能够按照我认为您希望的方式工作。

    1. 我将stepOne() 更改为step(),按照我编写代码的方式,您只需要这种方法即可更改为下一步
        def step():
            row = next(self.csvreader)
            test = str(row[1])
            self.instruction.configure(text=test)
            stepOneB.configure(text="Next Step")
    
    1. 我改变了湿设备的工作方式,它现在有一个self.instruction 变量,它是一个tk.Label 元素,这是当前指令的显示位置。我还添加了self.csvreader,这是在您当前的步骤中保存 csv。
        def __init__(self, parent, controller):
            tk.Frame.__init__(self, parent)
            self.controller = controller
            label = tk.Label(self, text="How to fix a wet phone", fg="purple")
            label.pack(side="top", fill="x", pady=10)
            self.instruction = tk.Label(self, text="", fg="purple") # the new instruction Label
            self.instruction.pack() 
    
            f = open("Wet Device.csv", "r")
            self.csvreader = csv.reader(f, delimiter=",") # new csv element
    

    这是完整的工作代码,我相信它会按照你的意愿工作。

    import tkinter as tk
    import csv
    
    
    class wetDevice(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self, parent)
            self.controller = controller
            label = tk.Label(self, text="How to fix a wet phone", fg="purple", font=controller.title_fontT)
            label.pack(side="top", fill="x", pady=10)
            self.instructions_frame = tk.Frame(self)
            self.instructions_frame.place(x = 230, y = 55)
            self.instruction_labels = []
            f = open("Wet Device.csv", "r")
            self.csvreader = csv.reader(f, delimiter=",")
    
            def step():
                try:
                    row = next(self.csvreader)
                    test = str(row[1])
                    if len(self.instruction_labels) >= 5:
                        temp = self.instruction_labels.pop(0)
                        temp.destroy()
                    instruction_temp = tk.Label(self.instructions_frame, text=test, fg="black")
                    instruction_temp.pack()
                    self.instruction_labels.append(instruction_temp)
                    stepOneB.configure(text="Next Step")
    
                except StopIteration:
                    stepOneB.configure(state="disabled", text="No Steps")
    
            # def nextStep():
    
            stepOneB = tk.Button(self, text="First Step", fg="green",
                                 command=lambda: step())
            stepOneB.place(x=230, y=175, width=60, height=20)
    
            mButton = tk.Button(self, text="Go to the Main Troubleshoot Menu",
                                command=lambda: controller.show_frame("MainTMenu"))
            mButton.place(x=285, y=210, width=200, height=25)
    

    我已对代码进行了调整,因此它可以按您的意愿工作(我认为)。

    不过,我自己做了一些假设。

    • 我让它只显示最后 5 条指令

    不幸的是,由于我这样做很快,我还没有完全解决您收到错误的事实,但是我现在做了一个“hacky”修复。我所做的修复是,如果它尝试获取 csv 的下一行并导致错误,那么它将禁用 nextStep Button 并将其文本设置为“无步骤”。

    【讨论】:

    • 我在使用这段代码时遇到的问题是:AttributeError: '_tkinter.tkapp' object has no attribute 'title_fontT',请记住我的整个代码很长,但我可以如果您真的需要查看它来修复我的代码,请将其展示给您。顺便感谢您所做的一切。
    • @DeathResister 我运行它时遇到同样的错误,因为我的代码中没有控制器变量,我使用了 title_fontT 因为我认为它是控制器变量的一个属性。从 wetDevice 类的标签中删除 font=controller.title_fontT。我将编辑我的答案代码来做到这一点。
    • 啊,是的,我添加了win = tk.Tk(),这样我就可以查看窗口以及它是如何工作的,因为您发布的代码没有运行窗口,这不是问题。也乐于提供帮助,帮助其他人解决错误实际上可以帮助我了解错误以及编写代码的新方法,这样我就可以最大限度地减少出错的机会。我还将查看您提供的代码,也许可以提供更多帮助:)
    • 是的,我知道如何解决它,但是,是否可以将新步骤放在最后一步下,以便您可以看到所有步骤,如果没有,我怎么能修复没有更多步骤时出现的“StopIteration”错误。再次感谢,您帮了大忙!代码如下:codeshare.io/5NdY14
    • 我相信这是可行的,我如何做到这一点的想法是创建一个带有指令的框架,并在框架中添加.pack() 新指令,当我更新我的解决方案时已经解决了这个问题,这可能需要一点时间,但我相信它在您的代码中绝对可行
    猜你喜欢
    • 2021-03-11
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 2016-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多