Tkinter and pulling a textbox value on button press - python

I used Visual TK as a generator for GUI for my app, but i have a problem. I want to pull the textbox values from one function into the button function. Also I want to update a label from within the button function also. I can't seem to do it because they are not defined.
The problem is in these two lines:
number = self.PoleMaticen.get("1.0", "end") and
GLabel_250["text"] = number
class App:
def __init__(self, root):
#setting title
root.title("Some title")
#setting window size
width=272
height=297
screenwidth = root.winfo_screenwidth()
screenheight = root.winfo_screenheight()
alignstr = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
root.geometry(alignstr)
root.resizable(width=False, height=False)
PoleMaticen=tk.Entry(root)
PoleMaticen["borderwidth"] = "1px"
ft = tkFont.Font(family='Arial',size=10)
PoleMaticen["font"] = ft
PoleMaticen["fg"] = "#333333"
PoleMaticen["justify"] = "left"
PoleMaticen["text"] = "INPUT THE NUMBER"
PoleMaticen.place(x=110,y=10,width=139,height=30)
PoleMaticen.focus()
GLabel_250=tk.Label(root)
GLabel_250["anchor"] = "ne"
ft = tkFont.Font(family='Arial',size=10)
GLabel_250["font"] = ft
GLabel_250["fg"] = "#333333"
GLabel_250["justify"] = "left"
GLabel_250["text"] = "The number"
GLabel_250.place(x=10,y=10,width=87,height=30)
GButton_baraj=tk.Button(root)
GButton_baraj["bg"] = "#f0f0f0"
ft = tkFont.Font(family='Arial',size=10)
GButton_baraj["font"] = ft
GButton_baraj["fg"] = "#000000"
GButton_baraj["justify"] = "center"
GButton_baraj["text"] = "Lookup"
GButton_baraj.place(x=20,y=90,width=227,height=30)
GButton_baraj["command"] = self.GButton_baraj_command
def GButton_baraj_command(self):
wb = openpyxl.load_workbook("workbook.xlsx")
ws = wb.active
number = self.PoleMaticen.get("1.0", "end")
GLabel_250["text"] = number
if __name__ == "__main__":
root = tk.Tk()
app = App(root)
root.mainloop()

PoleMaticen and GLabel_250 are variables local to __init__, which is why trying to use them in another function understandably fails.
If you need to use them as self.PoleMaticen and self.GLabel_250, assign them to those fields on self:
PoleMaticen = tk.Entry(root)
# ...
self.PoleMaticen = PoleMaticen
etc.

Related

When I click the increase button, the number labeled below it must be increased in Python

I would like to increment the number in Tkinter Label by 1 when a
Tkinter Button is pressed.
This is the code I implemented so far but doesn't work:
import random
from tkinter import *
class Game:
def __init__(self, root):
self.f = Frame(root, height = 1000, width = 350)
self.f.pack()
self.b = Button(self.f,text = 'Increase',height = 2, width = 15, command = self.buttonClick(1))
self.b.grid(row = 3, column = 1)
self.b.pack()
def buttonClick(self, num):
b = 1
if num == 1:
a = Label(text = str(b))
a.pack()
root = Tk()
root.geometry('350x1000')
mb = Game(root)
root.mainloop()
Few things were wrong in your code that needed correction:
You can't use two different layout managers (you are using grid and also pack and that is not allowed unfortunately).
Every time you call the method command = self.buttonClick(1) you pass the same argument 1. You don't increase anything. Also you should use lambda functions here: command = lambda: self.buttonClick(1). Because in your approach you pass the the command parameter what self.buttonClick(1) returns (your buttonClick method won't even execute!).
But still there is easier approach with using IntVar object.
The whole working code:
from tkinter import *
class Game:
def __init__(self, root):
self.f = Frame(root, height = 1000, width = 350)
self.f.pack()
self.number = IntVar(0)
self.a = Label(self.f, textvariable = self.number)
self.a.pack()
self.b = Button(self.f, text = 'Increase', height = 2, width = 15, command = self.buttonClick)
self.b.pack()
def buttonClick(self):
self.number.set(self.number.get() + 1)
root = Tk()
root.geometry('350x1000')
mb = Game(root)
root.mainloop()

How to make button using same root but different file in Tkinter?

I'm making a chess set on the computer. I've already finished the chess board, clock and name. To play chess you need pieces. So that's what I'm doing right now. I want the chess piece on the same root but on a different file to minimize the number of lines of code in one module. So I imported it like this:
from ScreenDisplay import Screen
I accessed the root like this and it worked well when I run it. I could see the board, the clock and the names.
self.Screen = Screen()
self.root = self.Screen.root
I tried adding a button on this file but it didn't show up.
self.Character = Button(self.root, image = self.Picture)
self.Character.grid(self.root, row = y, column = x)
(By the way, self.Picture, y and x are parameters of __ init __).
How can I make widgets appear on the screen while on a different module? Thanks!
Here is my entire code:
ScreenDisplay.py:
"Impport time module to create clock"
import time
"Import tkinter widgets"
from tkinter import Tk
from tkinter import Label
from tkinter import Image
"Impport PIL to open images"
from PIL import ImageTk, Image
"Create chess board and timer"
class Screen:
def __init__(self):
"Create root"
self.root = Tk()
self.root.title("Chess")
self.root.geometry("1400x700")
"Resizing the image"
self.Board = Image.open("ChessBoard.png")
self.resizing = self.Board.resize((700, 700))
self.ChessBoard = ImageTk.PhotoImage(self.resizing)
"Putting the image in a label then putting it on the screen"
self.ChessBoardLabel = Label(self.root, image = self.ChessBoard)
self.ChessBoardLabel.grid(row = 0, column = 0, rowspan = 8, columnspan = 8)
"Creating the labels and time control"
self.AI = Label(self.root, text = 'AI', font = "Helvetica 18 bold", width = 40)
self.AI.grid(row = 0, column = 8, columnspan = 7)
self.Human = Label(self.root, text = "Human", font = "Helvetica 18 bold", width = 40)
self.Human.grid(row = 7, column = 8, columnspan = 7)
"Create time clook for both players"
self.CountdownClock = Label(self.root, font = "Helvetica 18 bold")
self.CountdownClock.grid(row = 0, column = 8)
self.CountdownClock2 = Label(self.root, font = "Helvetica 18 bold")
self.CountdownClock2.grid(row = 7, column = 8)
"Run functions to activate the clocks"
self.set_timer()
self.countdown(self.CountdownClock)
self.set_timer()
self.countdown(self.CountdownClock2)
"Create the loop"
self.root.mainloop()
def set_timer(self):
self.t = 600
return self.t
def countdown(self, label):
if self.t > 0:
self.convert(label)
self.t = self.t - 1
label.after(1000, lambda: self.countdown(label))
else:
label.config(text = "Timer Completed")
def convert(self, item):
self.seconds = self.t % (24 * 3600)
self.seconds %= 3600
self.minutes = self.t // 60
self.seconds %= 60
item.config(text = "%02d:%02d" % (self.minutes, self.seconds))
if __name__ == '__main__':
board = Screen()
ChessPiece.py:
"Import the button widget from tkinter"
from tkinter import Button
"Import the Screen class from ScreenDisplay to display the pieces on the same window"
from ScreenDisplay import Screen
class ChessPiece:
def __init__(self, x, y, picture):
"Initialize the window here from the other file"
self.Screen = Screen()
self.root = self.Screen.root
"Initialize atributes that will be used through out the code"
self.x = x
self.y = y
self.Picture = picture
self.Taken = False
self.Character = Button(self.root, image = self.Picture)
self.Character.grid(self.root, row = y, column = x)
self.root.mainloop()
if __name__ == '__main__':
piece = ChessPiece(2, 7, "WhiteBishop.png")

change Tkinter frame color with for loop from list of colors

I have the following code snippet. What i need to code that when i click the button i need the frame color to change one by one from the list of colors defined.
from tkinter import *
from tkinter import ttk
def ChangeColor():
colors = ['red','green', 'orange','blue']
for color in colors:
#color = entry.get()
frame.config(bg = color)
root = Tk()
root.title("Title")
frame = Frame (root, width = 260, height = 200)
frame.pack()
btn = ttk.Button(frame, text = 'Change color', command = ChangeColor)
btn.place (x = 80, y = 100)
entry = ttk.Entry (frame, width = 20)
entry.place(x = 80, y = 70)
root.mainloop()
You can use the cycle iterator from itertools for this.
from tkinter import *
from tkinter import ttk
from itertools import cycle
root = Tk()
root.title("Title")
frame = Frame (root, width = 260, height = 200)
frame.pack()
colors = ['red','green', 'orange','blue']
color_gen = cycle(colors)
def ChangeColor():
frame.config(bg = next(color_gen))
btn = ttk.Button(frame, text = 'Change color', command = ChangeColor)
btn.place (x = 80, y = 100)
entry = ttk.Entry (frame, width = 20)
entry.place(x = 80, y = 70)
root.mainloop()
One thing I need to mention: please avoid doing "star" imports. When you do
from tkinter import *
it puts 135 Tkinter names into your namespace; in Python 2 you get 175 names. This creates needless clutter in the namespace and it can cause name collisions: if you accidentally name one of your variables with one of the imported names that can lead to mysterious bugs. It's even worse when you do star imports with multiple modules since they can stomp over each others' names. Also, star imports make the code harder to read since you have to remember which names are defined locally and which are imported.
I would change your app to a class so you can store variables and access them easily, also I bound the enter key to the entry widget so that works too. This way when you create an instance of class app it is an instance of a Tk() root, but you don't have to call it root
import tkinter as tk
from tkinter import ttk
class app(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title("Title")
self.frame = tk.Frame(self, width = 260, height = 200)
self.frame.pack()
self.btn = ttk.Button(self.frame, text = 'Change color', command = self.ChangeColor)
self.btn.place (x = 80, y = 100)
self.entry = ttk.Entry (self.frame, width = 20)
self.entry.place(x = 80, y = 70)
self.entry.bind("<Return>",self.ChangeColorEntry)
self.colors = ['red','green','orange','blue']
self.current_color = -1
self.standard_bg = self.frame['background']
def ChangeColor(self,event=None):
if self.current_color == len(self.colors) - 1:
self.frame.config(bg = self.standard_bg)
self.current_color = -1
return
else:
self.current_color += 1
color = self.colors[self.current_color]
self.frame.config(bg = color)
def ChangeColorEntry(self,event=None):
entered = self.entry.get().lower().strip()
if entered == "none":
self.frame.config(bg = self.standard_bg)
else:
try:
self.current_color = self.colors.index(entered)
self.frame.config(bg = entered)
except:
pass
#PM 2Rings answer is cleaner but since I was working on this I thought I'd still post it incase you wanted to implement it manually
from tkinter import *
from tkinter import ttk
colors = ['red', 'green', 'orange', 'blue']
colors_it = iter(colors)
def get_next_color():
try:
global colors_it
return next(colors_it)
except StopIteration:
colors_it = iter(colors)
return next(colors_it)
def ChangeColor():
frame.config(bg=get_next_color())
root = Tk()
root.title("Title")
frame = Frame (root, width = 260, height = 200)
frame.pack()
btn = ttk.Button(frame, text = 'Change color', command = ChangeColor)
btn.place (x = 80, y = 100)
entry = ttk.Entry (frame, width = 20)
entry.place(x = 80, y = 70)
root.mainloop()

Button image not appearing in tkinter

I'm new to tkinter and am running python 3.4.2 with Tk version 8.5.17 using IDLE 3.4.2 under Yosemite. This is a modified demo from Liang's book Introduction to Programming Using Python 3. I was expecting the following code to display four buttons:
from tkinter import *
class ButtonsDemo:
def __init__(self):
window = Tk()
window.title("Buttons Demo")
frame0 = Frame(window)
frame0.pack()
plusImage = PhotoImage(file = "image/plus.gif")
minusImage = PhotoImage(file = "image/minus.gif")
timesImage = PhotoImage(file = "image/times.gif")
divideImage = PhotoImage(file = "image/divide.gif")
Button(frame0, image = plusImage, command =
self.add).grid(row = 1, column = 1, sticky = W)
Button(frame0, image = minusImage, command =
self.subtract).grid(row = 1, column =2)
Button(frame0, image = timesImage, command =
self.multiply).grid(row = 1, column = 3)
Button(frame0, image = divideImage, command =
self.divide).grid(row = 1, column = 4)
window.mainloop()
def add(self):
print("add pressed")
def subtract(self):
print("subtract pressed")
def multiply(self):
print("multiply pressed")
def divide(self):
print("divide pressed")
ButtonsDemo()
When I run the code, only the first three buttons are displayed. The button with divideImage on it does not appear.
If I click where the divide button should be, I do get the message "divide pressed". It's as if the button is there, but it's invisible.
I see the same behavior running the program from the command line
instead of from IDLE.
There's nothing wrong with the gif. If I use divide.gif for plusImage, I can see divide.gif in the first button position. Also, when I put text = "Divide" on the divide button instead of image = DivideImage, the button becomes visible.
Why is the divide button invisible when I use an image? How can I fix it?
EDIT: Here's the code with everything moved to the main program. I think this should have fixed a garbage collection problem if there were one. Is this correct?
from tkinter import *
def add():
print("add pressed")
def subtract():
print("subtract pressed")
def multiply():
print("multiply pressed")
def divide():
print("divide pressed")
window = Tk()
window.title("Buttons Demo")
frame0 = Frame(window)
frame0.pack()
plusImage = PhotoImage(file = "image/plus.gif")
minusImage = PhotoImage(file = "image/minus.gif")
timesImage = PhotoImage(file = "image/times.gif")
divideImage = PhotoImage(file = "image/divide.gif")
Button(frame0, image = plusImage, command =
add).grid(row = 0, column = 0, sticky = W)
Button(frame0, image = minusImage, command =
subtract).grid(row = 0, column = 1)
Button(frame0, image = timesImage, command =
multiply).grid(row = 0, column = 2)
Button(frame0, image = divideImage, command =
divide).grid(row = 0, column = 3)
window.mainloop()

Centering and size a windows frame in Tkinter class python

I want to center a window frame ad set a size using a ratio according to screensize. But I cannot see where to modify my code correctly to perform such program. My program is the following example :
class App:
def __init__(self,master):
ScreenSizeX = master.winfo_screenwidth() # Get screen width [pixels]
ScreenSizeY = master.winfo_screenheight() # Get screen height [pixels]
ScreenRatio = 0.8 # Set the screen ratio for width and height
FrameSizeX = int(ScreenSizeX * ScreenRatio)
FrameSizeY = int(ScreenSizeY * ScreenRatio)
FramePosX = (ScreenSizeX - FrameSizeX)/2 # Find left and up border of window
FramePosY = (ScreenSizeY - FrameSizeY)/2
print FrameSizeX,FrameSizeY,FramePosX,FramePosY
#geometry(str(self.winfo_screenwidth())+"x"+str(self.winfo_screenheight())+"+0+0")
frame = Tkinter.Frame(master)
frame.pack()
self.button = Tkinter.Button(frame,text="Quit",fg="red",command=frame.quit)
self.button.pack()
self.hi_there = Tkinter.Button(frame,text="Hi!",command=self.say_hi)
self.hi_there.pack()
def say_hi(self):
print "hello !"
if __name__ == "__main__":
root = Tkinter.Tk()
app = App(root)
root.mainloop()
Why did you comment out the geometry line? It's quite close to what you need really. Try this:
master.geometry("%sx%s+%s+%s" % (FrameSizeX,FrameSizeY,FramePosX,FramePosY))
This is the final code working for this feature :
import Tkinter #Python integrated tool kit for interfaces
class App:
def __init__(self,master):
# Define frame size and position in the screen :
ScreenSizeX = master.winfo_screenwidth() # Get screen width [pixels]
ScreenSizeY = master.winfo_screenheight() # Get screen height [pixels]
ScreenRatio = 0.8 # Set the screen ratio for width and height
FrameSizeX = int(ScreenSizeX * ScreenRatio)
FrameSizeY = int(ScreenSizeY * ScreenRatio)
FramePosX = (ScreenSizeX - FrameSizeX)/2 # Find left and up border of window
FramePosY = (ScreenSizeY - FrameSizeY)/2
master.geometry("%sx%s+%s+%s"%(FrameSizeX,FrameSizeY,FramePosX,FramePosY))
frame = Tkinter.Frame(master)
frame.pack()
self.button = Tkinter.Button(frame,text="Quit",fg="red",command=frame.quit)
self.button.pack()
self.hi_there = Tkinter.Button(frame,text="Hi!",command=self.say_hi)
self.hi_there.pack()
def say_hi(self):
print "hello !"
if __name__ == "__main__":
root = Tkinter.Tk()
app = App(root)
root.mainloop()

Categories

Resources