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")
Related
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.
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()
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()
So I have been playing with tkinter to try add a gui to a lift simulator project I have written for university. It is not really needed, but I would like to add it.
Here is the code that I currently have.
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
master.title("Test") #Controls the window title.
self.pack()
self.createWidgets()
def createWidgets(self):
floors = [i for i in range(41)]
buttons = []
xPos = 0
yPos = 0
for floor in floors:
if(yPos == 5):
xPos = xPos + 1
yPos = 0
if(xPos == 8):
yPos = 2
self.button = tk.Button(self, width=3, text=floor,
command = lambda f=floor: self.pressed(f))
self.button.grid(row=xPos, column =yPos)
yPos = yPos +1
self.QUIT = tk.Button(self, text="QUIT", fg="red",
command=root.destroy).grid(row = xPos, column = yPos)
def pressed(self, index):
print("number pressed", index)
self.button.configure(bg = "red")
root = tk.Tk()
app = Application(master=root)
app.mainloop()
This is all fine and dandy other than when the button is pressed it prints out the correct number, but it changes the background of the last button (number 40) to red, not the one pressed.
If you could let me know what needs correcting that would be great.
Thanks
self.button can only ever reference a single button, and it will always be whatever was assigned to it last. A simple solution is to store the button references in a dict, using floor as the key. Since you're passing that to the callback, you then have everything you need to reconfigure the button:
def createWidgets(self):
...
self.buttons = {}
for floor in floors:
...
self.buttons[floor] = tk.Button(...)
...
def pressed(self, index):
...
self.buttons[index].configure(bg="red")
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()