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()
Related
I tried to build off of the solution here. My code is:
from tkinter import mainloop, Tk, Frame, Button, Label, Canvas, PhotoImage, NW
from tkinter import ttk
from tkinter import filedialog
import tkinter as tk
from PIL import Image, ImageTk
class my_class(tk.Tk):
def __init__(self):
super().__init__()
self.geometry=('1400x1400')
self.filename = ''
my_notebook = ttk.Notebook(self)
my_notebook.pack(pady=5)
self.selections = Frame(my_notebook, width = 1100, height = 700)
self.selections.pack(fill = "both", expand=1)
my_notebook.add(self.selections, text = "Selections")
Button(self.selections, text = "Select an Image", command = self.get_image).place(x=10,y=40)
self.image_frame = Frame(my_notebook, width = 1100, height = 700)
self.image_frame.pack(fill = "both", expand=1)
my_notebook.add(self.image_frame, text = "Image")
self.my_canvas = Canvas(self.image_frame, width=800, height=600, bg="white")
self.my_canvas.pack()
self.rgb_var = tk.StringVar(self.image_frame, '0 0 0')
self.rgb_label = tk.Label(self.image_frame, textvariable = self.rgb_var)
self.rgb_label.pack()
self.image_frame.bind('<Motion>', lambda e: self.get_rgb(e))
def get_image(self):
self.filename = filedialog.askopenfilename(initialdir="D:/Python", title="select a file", filetypes = (("png files","*.png"),("jpg files","*.jpg")))
self.img = Image.open(self.filename)
self.img_rgb = self.img.convert('RGB')
dim_x, dim_y = self.img_rgb.size
self.img_tk = ImageTk.PhotoImage(self.img_rgb.resize((dim_x, dim_y)))
self.my_canvas.create_image(dim_x // 2, dim_y // 2, image = self.img_tk)
def get_rgb(self, event):
x, y = event.x, event.y
try:
rgb = self.img_rgb.getpixel((x, y))
self.rgb_var.set(rgb)
except IndexError:
pass # ignore errors if cursor is outside the image
if __name__ == '__main__':
app = my_class()
app.geometry=('1200x900')
app.mainloop()
I can use the button to select an image. Then I click the (Image) tab and see the selected image on the canvas.
I expected the (rgb_var) displayed under the image to update as I move the mouse pointer across the image. Instead the numbers under the image only update when the mouse pointer is in the frame, but outside the canvas. Also the numbers displayed seem to be unrelated to pixels in the image. How can I display the RGB values of a pixel that is (under the mouse pointer) when the mouse pointer is over the image?
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 have a class that represents a Window that contains a canvas, a label and is soon to contain some color-coordinated buttons.
Here is the code:
class Canvas():
def __init__(self, width, height):
self.root = tk.Tk()
self.width = width
self.height = height
self.text_label = tk.Label(self.root, text="10",font=("Times New Roman", 20, "italic"))
self.text_label.pack()
self.canvas = tk.Canvas(master= self.root,width = self.width,height = self.height)
self.canvas.pack()
#======================
self.redBtn = tk.Button(master=self.root,text="hello",command=lambda:self.changeColor("Red"))
self.redBtn.pack()
#======================
self.root.mainloop()
canvas = Canvas(1980,1080)
Although I used redBtn.pack() on the button it doesn't show up.
Does anyone know why?
It worked. I can see number 10. Change this:
win = Window(1980,1080)
to
win = Canvas(1980,900)
So you can see the button on bottom.
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")
I'm trying to write my first GUI based python program using Tkinter. I have created a base window which holds the menu bar with a couple of options.
One of the options is for a standard 'About' box. When I call the about section with
helpMainMenu.add_command(label="About", command=self.aboutProgram)
It opens the message box, but in a fresh window so there are now two windows showing on the taskbar.
Is there any way to stop it opening a new window and use the main one instead, or is there a better way to do it?
The full code is below
#! /usr/bin/python3
from tkinter import *
from tkinter import messagebox
import datetime
timeNow = datetime.datetime.now()
writeYear = 2020 # Enter the year you started writing the program
lineFeed = "\n"
programTitle = "Basic Menu"
programVersion = "Version 1.0.0"
programmerName = " Name (email#gmail.com)"
if timeNow.year > writeYear:
programAuthor = "©" + str(writeYear) + "-" + str(timeNow.year) + programmerName
else:
programAuthor = "©" + str(writeYear) + programmerName
aboutMessage = programTitle + lineFeed + programVersion + lineFeed + programAuthor
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
self.master.title("{} ({})".format(programTitle, programVersion))
self.pack(fill=BOTH, expand=1)
menu = Menu(self.master)
self.master.config(menu=menu)
fileMainMenu = Menu(menu, tearoff=0) #Create the File menu container
fileMainMenu.add_command(label="Exit", command=self.programExit) # File menu option
menu.add_cascade(label="File", menu=fileMainMenu)
helpMainMenu = Menu(menu, tearoff=0) #Create the Help menu container
helpMainMenu.add_command(label="About", command=self.aboutProgram)
menu.add_cascade(label="Help", menu=helpMainMenu)
def programExit(self):
exitMsgBox = messagebox.askquestion ("Exit Application","Are you sure you want to exit the application",icon = "warning")
if exitMsgBox == "yes":
root.destroy()
exit()
def aboutProgram(self):
messagebox.showinfo("About","About the application", icon = "info")
root = Tk() # root window created. Here, that would be the only window, but
windowHeight = int(root.winfo_screenheight()/100*75) # Set the main window height to 75% of the screen height
windowWidth = int(root.winfo_screenwidth()/100*75) # Set the main window width to 75% of the screen width
screenWidth = int(root.winfo_screenwidth())
screenHeight = int(root.winfo_screenheight())
positionRight = int(root.winfo_screenwidth()/2 - windowWidth/2) # Get the screen width and divide by 2, then minus the result of 'windowWidth' divided by 2
positionDown = int(root.winfo_screenheight()/2 - windowHeight/2) # Get the screen height and divide by 2, then minus the result of 'windowHeight' divided by 2
root.geometry("{}x{}+{}+{}".format(windowWidth, windowHeight, positionRight, positionDown)) # Positions the window in the center of the page.
app = Window(root)
root.mainloop()
Python Version 3.7.3
tkinter.TkVersion 8.6
The simplest way would be to create a new frame for the "about" page, and then overlay it on top of the main window with place -- one of the few times when place is superior to grid and pack.
You should also do a "grab" on the frame so that all events are funneled to the frame and its children. With a grab, while the popup is visible you can't interact with the widgets on the main window.
Here's a quick example:
def aboutProgram(self):
# create the frame with a message and a button
# which destroys the window
aboutFrame = Frame(self.master, bd=2, relief="groove")
label = Label(aboutFrame, text="About the application...")
button = Button(aboutFrame, text="Ok", command=aboutFrame.destroy)
label.pack(side="top", padx=20, pady=20)
button.pack(side="bottom", pady=20)
# overlay the "about" page on top of the root window
aboutFrame.place(relx=.5, rely=.5, anchor="c")
# force all events to go to the popup
aboutFrame.grab_set()
If you want to completely hide the contents of the main window, you can change the place arguments to fill the window:
aboutFrame.place(x=0, y=0, anchor="nw", relwidth=1.0, relheight=1.0)