0

I am creating a news feed program that uses the Feedparser module to read the Yahoo! RSS API, write key data to a text file, and then display the data organised in a Tkinter GUI.

I was enquiring if it is possible to have clickable hyperlinks in a text file/Tkinter message widget.

My current thinking is that you could write code that runs in the following fashion:

  • If item in the text file includes 'http', make it a hyperlink.

If anyone knows of a Pythonic way to achieve this, or knows if it is not in fact possible, please contribute.

Thank you for your time, here is my code:

def news_feed(event):
    ''' This function creates a new window within the main window, passes an event(left mouse click), and creates a text heading'''

    root = Toplevel(window)

    # Create a text heading and define its placement within the grid
    menu_heading = Label(root, text = 'News feed', font = 'bold')
    menu_heading.grid(row = 0, column = 0, columnspan = 3, pady = 4)

    # Create a variable of the selected radio button
    button_choice = IntVar()

    def selection():
        ''' This function gets the activated radio button and calls its corresponding function.'''

        # Get the value of the activated radio button, and call its corresponding function
        news_choice = button_choice.get()

        # If the user's choice is industry news, ask them which feed they would like (E.g. Stock market),
        if news_choice == 0:
            # grab the corresponding url segment to the user's feed choice from the dictionary,
            news_choice_url = news_areas[news_feed]
            # set the url variable using by inserting this segment into the API url,
            rss_url = feedparser.parse('https://au.finance.yahoo.com/news/' + news_choice_url + '/?format=rss')
            # and call the feed parsing function.
            parse_feed()
        # If the user's choice is the second button, call the company news function
        elif news_choice == 1:
            company_news()

    def read_news_file(news_feed_message):
        '''This function opens the companyNews text file and reads its contents, line by line'''
        with open('C:\\Users\\nicks_000\\PycharmProjects\\untitled\\SAT\\GUI\\Text Files\\companyNews.txt', mode='r') as inFile:
            news_data_read = inFile.read()
            print('\n')
        news_feed_message.configure(text = news_data_read)

    def parse_feed(news_feed_message, rss_url):
        ''' This function parses the Yahoo! RSS API for data of the latest five articles, and writes it to the company news text file'''

        # Define the RSS feed to parse from, as the url passed in of the company the user chose
        feed = feedparser.parse(rss_url)

        try:
            # Define the file to write the news data to the company news text file
            with open('C:\\Users\\nicks_000\\PycharmProjects\\untitled\\SAT\\GUI\\Text Files\\companyNews.txt', mode='w') as outFile:

                # Create a list to store the news data parsed from the Yahoo! RSS
                news_data_write = []
                # Initialise a count
                count = 0
                # For the number of articles to append to the file, append the article's title, link, and published date to the news_elements list
                for count in range(10):
                    news_data_write.append(feed['entries'][count].title)
                    news_data_write.append(feed['entries'][count].published)
                    article_link = (feed['entries'][count].link)
                    article_link = article_link.split('*')[1]
                    news_data_write.append(article_link)
                    # Add one to the count, so that the next article is parsed
                    count+=1
                    # For each item in the news_elements list, convert it to a string and write it to the company news text file
                    for item in news_data_write:
                        item = str(item)
                        outFile.write(item+'\n')
                    # For each article, write a new line to the company news text file, so that each article's data is on its own line
                    outFile.write('\n')
                    # Clear the news_elements list so that data is not written to the file more than once
                    del(news_data_write[:])
        finally:
            outFile.close()

        read_news_file(news_feed_message)

    def industry_news():
        ''' This function creates a new window within the main window, and displays industry news'''

        industry_window = Toplevel(root)
        Label(industry_window, text = 'Industry news').grid()

    def company_news():
        ''' This function creates a new window within the main window, and displays company news'''

        company_window = Toplevel(root)
        company_label = Label(company_window, text = 'Company news')
        company_label.grid(row = 0, column = 0, columnspan = 6)

        def company_news_handling(company_ticker):
            ''' This function gets the input from the entry widget (stock ticker) to be graphed.'''

            # set the url variable by inserting the stock ticker into the API url,
            rss_url = ('http://finance.yahoo.com/rss/headline?s={0}'.format(company_ticker))
            # and call the feed parsing function.
            parse_feed(news_feed_message, rss_url)

        # Create the entry widget where the user enters a stock ticker, and define its location within the grid
        company_ticker_entry = Entry(company_window)
        company_ticker_entry.grid(row = 1, column = 0, columnspan = 6, padx = 10)

        def entry_handling():
            '''This function validates the input of the entry box, and if there is nothing entered, an error is outputted until a value is'''

            # Create a variable that equals the input from the entry widget
            company_ticker = company_ticker_entry.get()

            # Convert the input into a string
            company_ticker = str(company_ticker)

            if company_ticker == '':
                news_feed_message.configure(text = 'Please input a stock ticker in the entry box.')
            else:
                company_news_handling(company_ticker)

        # Create the button that the user presses when they wish to graph the data of the stock ticker they inputted in the entry widget
        graph_button = Button(company_window, text = 'SHOW', command = entry_handling, width = 10).grid(row = 2, column = 0, columnspan = 6)

        news_feed_message = Message(company_window, text='', width=500, borderwidth=5, justify=LEFT, relief=RAISED)
        news_feed_message.grid(row=3, column=0, columnspan=6)
Nick
  • 63
  • 2
  • 9

3 Answers3

1

Most uses of hyperlinks in a tkinter application i have seen involved using the webbrowser and attaching events to your tkinter object to trigger callbacks, but there may be simpler ways, but heres what i mean :

from tkinter import *
import webbrowser

def callback(event):
    webbrowser.open_new(r"http://www.google.com")

root = Tk()
link = Label(root, text="Google Hyperlink", fg="blue", cursor="hand2")
link.pack()
link.bind("<Button-1>", callback)
root.mainloop()

From this source

You could do as you said and read from a text file, and if the line contains "http" create a new label, and event, attaching the hyper link from the file to the event.

import re

with open(fname) as f:
    content = f.readlines()
    urls = re.findall('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', content)

Access the url's after this and generate your label's or whatever widget you attach the url's too and you can then have all of them open the web page when clicked.

Hope this helps in some way, let me know if you need more help :)

Community
  • 1
  • 1
D3181
  • 2,037
  • 5
  • 19
  • 44
0

The output

I think it is easy to create hyperlink in tkinter using following link and its easy for modifying as per your requirement

Updated Hyperlink in tkinter

hope this works for you.

regards Midhun

Midhun Mohan
  • 552
  • 5
  • 18
0

(Answer taken from effbot) Support module for Text hyperlinks (File: tkHyperlinkManager.py)

from Tkinter import *

class HyperlinkManager:

    def __init__(self, text):

        self.text = text

        self.text.tag_config("hyper", foreground="blue", underline=1)

        self.text.tag_bind("hyper", "<Enter>", self._enter)
        self.text.tag_bind("hyper", "<Leave>", self._leave)
        self.text.tag_bind("hyper", "<Button-1>", self._click)

        self.reset()

    def reset(self):
        self.links = {}

    def add(self, action):
        # add an action to the manager.  returns tags to use in
        # associated text widget
        tag = "hyper-%d" % len(self.links)
        self.links[tag] = action
        return "hyper", tag

    def _enter(self, event):
        self.text.config(cursor="hand2")

    def _leave(self, event):
        self.text.config(cursor="")

    def _click(self, event):
        for tag in self.text.tag_names(CURRENT):
            if tag[:6] == "hyper-":
                self.links[tag]()
                return

And here’s an example:

# File: hyperlink-1.py

import tkHyperlinkManager

from Tkinter import *

root = Tk()
root.title("hyperlink-1")

text = Text(root)
text.pack()

hyperlink = tkHyperlinkManager.HyperlinkManager(text)

def click1():
    print "click 1"

text.insert(INSERT, "this is a ")
text.insert(INSERT, "link", hyperlink.add(click1))
text.insert(INSERT, "\n\n")

def click2():
    print "click 2"

text.insert(INSERT, "this is another ")
text.insert(INSERT, "link", hyperlink.add(click2))
text.insert(INSERT, "\n\n")

mainloop()

Tkinter Hyperlink Example