-1

So I have this neat little program that is working fine except when I try to pack it in to tkinter with the fill option. I get an error if I use the fill option with the X value.

TclError: bad fill style "64": must be none, x, y, or both

From what I undrestand, tkinter is saying that I have something other than none, x, y, or both in the fill option... I tried to put x with lower case, but that is just refering to x as a variable. This only happens in my code, no where else as I experimented it on a new document.

from Tkinter import *
import tkMessageBox
from urllib import *
from webbrowser import *
from re import *

stage = Tk()

button_frame = Frame(stage)

url='http://9gag.com/gif'
caption_var=StringVar()
window_var=StringVar()

def core_fn():
    global open_url, read_url, search
    global title_head, gif_caption
    global counter, caption_count, caption_var
    global message_alert, gif_list

    counter = 0

    #Scrape webpage for gif url
    open_url = urlopen(url)
    read_url = open_url.read()
    search = findall(r'http.*\.gif', read_url)

    #Encode all gifs found and append to list
    gif_list=[]
    for gif in search:
        encode_gif = urlopen(gif).read().encode('base64', 'strict')
        gif_list.append(encode_gif)
        print 'Encode Success'

    #Scrape webpage for title and remove unwanted characters
    title_head = str(findall(r'<title>.*</title>', read_url))[9:-10]

    #Scrape webpage for caption
    caption_search = findall(r'alt=".*"', read_url)
    caption_search.remove(caption_search[0])
    gif_caption=[]

    #Remove unwated characters from caption
    for caption in caption_search:
        sub_1 = sub(r'&#039;', "'", caption)
        sub_2 = sub(r'&quot;', '"', sub_1)
        sub_3 = sub(r'&rsquo;', "'", sub_2)
        sub_4 = sub(r'&ldquo;', '"', sub_3)
        caption = sub_4[5:-1]
        gif_caption.append(caption)

    #Display retrieved data from webpage
    message_alert = 'NOTE: Application is still in beta\n' + str(len(search)) + ' Gifs Found'
    caption_var.set(gif_caption[counter])

core_fn()
stage.title(title_head)

def update_gif():
    image = PhotoImage(data = gif_list[counter])
    label.configure(image=image)
    label.image=image

#Previous Function
def btn_previous_fn():
    global counter
    global search

    #Makes sure that the counter is not less than 0
    counter -=1
    if counter < 0:
        #If the counter is less than 0, go to the last gif in the list
        counter = (len(search)-1)

    #Change and update gif
    update_gif()
    caption_var.set(gif_caption[counter])

    #Keep track of the gif
    print 'Gif', str(counter+1), 'of', len(search)

#Next Function
def btn_next_fn():
    global counter
    global search

    #Makes sure that the counter is not greater than the ammount of gifs found
    counter +=1
    if counter > (len(search)-1):
        #If the counter is greater than the ammount of gifs found, go to the first gif in the list
        counter = 0

    #Change and update gif
    update_gif()
    caption_var.set(gif_caption[counter])

    #Keep track of the gif
    print 'Gif', str(counter+1), 'of', len(search)

#Menus
def check():
    tkMessageBox.showinfo(title='Check', message=message_alert)

def latest():
    global url
    url='http://9gag.com/gif/fresh'
    core_fn()
    update_gif()
    stage.title(title_head+' - Latest')
    print 'Gif', str(counter+1), 'of', len(search)
    tkMessageBox.showinfo(title='Check', message=message_alert)

def popular():
    global url
    url='http://9gag.com/gif'
    core_fn()
    update_gif()
    stage.title(title_head+' - Popular')
    print 'Gif', str(counter+1), 'of', len(search)
    tkMessageBox.showinfo(title='Check', message=message_alert)

def save():
    url_image = search[counter]
    image = PhotoImage(data = gif_list[counter])
    gif_name = str(gif_caption[counter]) + '.gif'
    image.write(gif_name, format='gif')
    tkMessageBox.showinfo(title='Check', message='Save Complete')

#View gif in browser
def web():
    open(search[counter])

menu_bar = Menu(stage)
file_menu = Menu(menu_bar)
page_menu = Menu(menu_bar)
about_menu = Menu(menu_bar)

file_menu.add_command(label='Check Page',  command=check)
file_menu.add_command(label='Save Image',  command=save)
menu_bar.add_cascade(label='File',menu=file_menu)

page_menu.add_command(label='Latest Gifs', command=latest)
page_menu.add_command(label='Popular Gifs', command=popular)
menu_bar.add_cascade(label='Page',menu=page_menu)

about_menu.add_command(label='About')
menu_bar.add_cascade(label='Help',menu=about_menu)

stage.config(menu=menu_bar)

#Initial gif
image = PhotoImage(data = gif_list[counter])
tkMessageBox.showinfo(title='Check', message=message_alert)
print 'Gif', str(counter+1), 'of', len(search)

#Labels
app_title = Label(stage, text=title_head, font=("Impact", 30))
label = Label(stage, image=image)
caption = Label(stage, textvariable=caption_var, wraplength=300, font=("Arial", 11, "italic"))
status_bar = Label(stage, text='Ready', borderwidth=1, relief=SUNKEN, anchor=W)

#Buttons
btn_view = Button(button_frame, command=web, text='View', width=5)
btn_next = Button(button_frame, text='>', width=2, command=btn_next_fn)
btn_previous = Button(button_frame, text='<', width=2, command=btn_previous_fn)

#Place to stage
app_title.pack(side=TOP)
label.pack(side=TOP)
caption.pack(side=TOP)

button_frame.pack(side=TOP)
btn_previous.grid(row=1, column=1)
btn_view.grid(row=1, column=2)
btn_next.grid(row=1, column=3)

#the problem
status_bar.pack(side=BOTTOM, fill=X)

stage.mainloop()
no coder
  • 2,290
  • 16
  • 18
潘俊忠
  • 5
  • 1
  • Please read http://stackoverflow.com/help/mcve - the overwhelming majority of your code is **completely irrelevant** to the issue of packing widgets. Also, don't use `grid` and `pack` together; see e.g. http://stackoverflow.com/q/3966367/3001761 – jonrsharpe May 02 '15 at 15:27
  • @jonrsharpe Don't use `grid` and `pack` together? You should at least specify under the same parent.. – nbro May 02 '15 at 16:08
  • @Rinzler that would be more accurate, but in general I think it's better to start new users off with one or the other – jonrsharpe May 02 '15 at 16:10
  • 1
    The use of pack and grid in this app is perfectly fine (if not actually preferred!). As long as two widgets have different parents you can safely use grid for one and pack for the other. – Bryan Oakley May 02 '15 at 17:10

1 Answers1

2

This is why global imports are bad. Both the Tkinter and re modules define the "constant" X. When you import re after importing Tkinter, X is getting set to 64, hence the error.

The simplest fix is to remove all global imports:

import Tkinter as tk
import re
...
state = tk.Tk()
...

Also, I personally recommend not using the tkinter constants. They provide no real value. Just use literal strings "x", "y" or "both".

Doing either of these two (no global imports, don't use these constants) would have prevented the error and are generally considered best practices. Doing both, and having two modules that define the same variable, is what caused your problem.

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685