Python Tkinter 程序到 return 来自给定 url 的文本

Python Tkinter program to return text from given url

我在做我认为不会太困难的事情时遇到了一些麻烦。我想创建一个程序,使用给定的 DOI(研究论文的唯一标识)并将其发送到网站,将 Bibtex 格式的文本结果返回给用户,以便他们可以 select,复制并粘贴结果。

下面的 (Python 3.x) 代码是我的尝试(第一次使用 Tkinter 和 class 在 Python 中编程),虽然我似乎不能让标签能够像我期望的那样更新。您可能还会注意到我并不真正理解 'self' 的用法,但这是另一个问题。如果你想让它变得活跃一点,请随意!

谢谢。

import urllib.request
from tkinter import *

##This is the logic of what I want to do
# x = urllib.request.urlopen('http://api.crossref.org/works/10.1098/rsta.2010.0348/transform/application/x-bibtex')
# data = x.read()
# print(data)

'''Small attempt at a program to take a DOI input (unique address for research papers) and 
    return the Bibtex formatted result from the above website in a copy/pastable form. 
    It should handle HTTP errors and be reusable. While the program below is my attempt,
    any solution that does the above would be appreciated.'''

class MyFirstGUI:

    def __init__(self, master):
        self.master = master
        master.title("DOI to Bibtex Tool")

        self.label1 = Label(master, text="Enter DOI")

        ##Give a default, customisable DOI value
        self.v = StringVar(root, value='10.1098/rsta.2010.0348')
        self.entry1 = Entry(master, bd =5, textvariable=self.v)
        self.label1.pack()
        self.entry1.pack()

        self.submit = Button(master, text ="Submit", command = self.update)
        self.submit.pack()

        self.close_button = Button(master, text="Close", command=master.quit)
        self.close_button.pack()

        ##Here I want to produce the result of my http request call
        self.v = StringVar()
        self.v.set("Output area for result of HTTP request to be updated when you press submit\n"
                                        +"(ideally highlightable/copy pastable)")
        self.output_label = Label(master, text=self.v.get())
        self.output_label.pack()


        ##This here is an experimental method to get highlightable text, which is desirable but can't get this to work either.
        #Uncomment for example
        # self.w = Text(master, height=100)
        # self.w.insert(1.0, self.v.get())
        # self.w.pack()
        # self.w.configure(bg=self.master.cget('bg'), relief=FLAT)
        # self.w.configure(state="disabled")


    def update(self):
        doi = str(self.entry1.get()) ##Get the user inputted DOI 
        print(str(self.entry1.get()))
        url = 'http://api.crossref.org/works/'+ doi + '/transform/application/x-bibtex'
        print(url)

        try:
            x = urllib.request.urlopen(url)
        except urllib.error.URLError as e: 
            print(str(e))
            ##Show user an error if they put in the wrong DOI
            self.v.set(str(e)) ##This doesn't update. Something like label.update() would be nice

        else:
            ##Update the output area to the returned form of the text entry, ideally highlightable for copying
            data = x.read()
            self.v.set(data) ##This doesn't update. Something like label.update() would be nice
            print(data) ##I also want it to interpret the escape characters, so \n becomes linebreak etc


root = Tk()
root.geometry("600x400")

my_gui = MyFirstGUI(root)
root.mainloop()

示例输出:

这对我有用:

self.output_label = Label(master, textvariable=self.v)

textvariable 允许您更新标签内的文本。

你真的不需要使用 StringVar 来实现你想要的。 下面的代码向您展示了如何使用文本小部件而不使用 StringVar 来获取 copy/pastable 文本。

每次要更新时都需要将文本小部件的状态切换回正常状态,所以我写了一个 update_text 方法来更新小部件内容。

import urllib.request
from tkinter import *


class MyFirstGUI(Tk):

    def __init__(self):
        # create main window by calling the __init__ method of parent class Tk
        Tk.__init__(self)
        self.geometry("600x400")
        self.title("DOI to Bibtex Tool")

        label1 = Label(self, text="Enter DOI")
        label1.pack()

        ##Give a default, customisable DOI value
        self.entry1 = Entry(self, bd=5)
        self.entry1.insert(0, '10.1098/rsta.2010.0348')
        self.entry1.pack()

        submit = Button(self, text ="Submit", command = self.update)
        submit.pack()

        close_button = Button(self, text="Close", command=self.quit)
        close_button.pack()

        ##Here I want to produce the result of my http request call
        self.w = Text(self, relief='flat', 
                      bg = self.cget('bg'),
                      highlightthickness=0, height=100) 
        # trick to make disabled text copy/pastable
        self.w.bind("<1>", lambda event: self.w.focus_set())
        self.w.insert('1.0', "Output area for result of HTTP request to be updated when you press submit\n"
                                        +"(ideally highlightable/copy pastable)")
        self.w.configure(state="disabled", inactiveselectbackground=self.w.cget("selectbackground"))
        self.w.pack()

        self.mainloop()

    def update_text(self, new_text):
        """ update the content of the text widget """
        self.w.configure(state='normal')
        self.w.delete('1.0', 'end')    # clear text
        self.w.insert('1.0', new_text) # display new text
        self.w.configure(state='disabled') 


    def update(self):
        doi = str(self.entry1.get()) ##Get the user inputted DOI 
        print(str(self.entry1.get()))
        url = 'http://api.crossref.org/works/'+ doi + '/transform/application/x-bibtex'
        print(url)

        try:
            x = urllib.request.urlopen(url)
        except urllib.error.URLError as e: 
            ##Show user an error if they put in the wrong DOI
            self.update_text(str(e)) 

        else:
            ##Update the output area to the returned form of the text entry, ideally highlightable for copying
            data = x.read()
            self.update_text(data) 

if __name__ == '__main__':
    my_gui = MyFirstGUI()