Related
I am a quite beginner with tkinter. I am trying to visually connect two instances of some self created object on a canvas by clicking on them (right mouse click). In procedural coding style and using a global variable to count the clicks everything works fine. I cannot figure out what am I overlook in my code when I create everything in a class.
Any clue?
from tkinter import Tk, Frame, Canvas, CURRENT, Text, END, TRUE, BOTH
class features_object():
def __init__(self, master, feature_text, feature_xpos, feature_ypos, feature_color):
self.master = master
self.feature_text = feature_text
self.feature_xpos = feature_xpos
self.feature_ypos = feature_ypos
self.feature_color = feature_color
self.click = 0
self.feature_frame = Frame(self.master, bg=self.feature_color, border=40)
self.feature_text = Text(self.feature_frame, font=("Helvetica", 12), relief='flat', width=20, height=3, selectbackground=self.feature_color, selectforeground="black", exportselection=TRUE)
self.feature_text.grid(row=0, column=0, padx=5, pady=5, sticky='w')
self.feature_text.config(wrap='word')
self.feature_text.insert(END, feature_text)
self.feature_tags = 'feature'
self.feature_id = self.master.create_window(self.feature_xpos, self.feature_ypos, window=self.feature_frame, tags=self.feature_tags)
self.bind_events()
def bind_events(self):
self.feature_frame.bind('<Button-1>', self.clicked)
self.feature_frame.bind('<Button-3>', self.draw_line_with_bind)
def clicked(self, event=None):
print(f'You clicked {self.feature_id} with the cords {self.master.coords(self.feature_id)}')
def draw_line_with_bind(self, event):
self.activ_elem = self.master.coords(self.feature_id)
if self.click == 0:
self.elem_start = self.activ_elem
self.start_x = self.activ_elem[0]
self.start_y = self.activ_elem[1]
self.click = 1
elif self.click == 1:
self.elem_end = self.activ_elem
self.end_x = self.activ_elem[0]
self.end_y = self.activ_elem[1]
self.master.create_line(self.start_x, self.start_y, self.end_x, self.end_y, fill="red", width=5)
self.click = 0
window = Tk()
window.geometry("1000x800")
frame_start = Frame(window)
frame_start.pack(expand=TRUE, fill=BOTH)
draw_canvas = Canvas(frame_start)
draw_canvas.pack(expand=TRUE, fill=BOTH)
created_feature_1 = features_object(draw_canvas, 'feature A', 100, 100, 'red')
created_feature_2 = features_object(draw_canvas, 'feature B', 300, 300, 'green')
created_feature_3 = features_object(draw_canvas, 'feature C', 500, 500, 'magenta')
if __name__ == '__main__':
window.mainloop()
THis is happens because self.start_x, self.start_y, self.end_x, self.end_y, and self.count are not same for all features_objects instance.
Means self.start_x, self.start_y, self.end_x, self.end_y, and self.count are different for all instances.
You can use global here.
Try this.
from tkinter import Tk, Frame, Canvas, CURRENT, Text, END, TRUE, BOTH
click = 0
class features_object():
def __init__(self, master, feature_text, feature_xpos, feature_ypos, feature_color):
self.master = master
self.feature_text = feature_text
self.feature_xpos = feature_xpos
self.feature_ypos = feature_ypos
self.feature_color = feature_color
self.click = 0
self.feature_frame = Frame(self.master, bg=self.feature_color, border=40)
self.feature_text = Text(self.feature_frame, font=("Helvetica", 12), relief='flat', width=20, height=3, selectbackground=self.feature_color, selectforeground="black", exportselection=TRUE)
self.feature_text.grid(row=0, column=0, padx=5, pady=5, sticky='w')
self.feature_text.config(wrap='word')
self.feature_text.insert(END, feature_text)
self.feature_tags = 'feature'
self.feature_id = self.master.create_window(self.feature_xpos, self.feature_ypos, window=self.feature_frame, tags=self.feature_tags)
self.bind_events()
def bind_events(self):
self.feature_frame.bind('<Button-1>', self.clicked)
self.feature_frame.bind('<Button-3>', self.draw_line_with_bind)
def clicked(self, event=None):
print(f'You clicked {self.feature_id} with the cords {self.master.coords(self.feature_id)}')
def draw_line_with_bind(self, event):
global click,start_x,start_y,end_x,end_y
self.activ_elem = self.master.coords(self.feature_id)
if click == 0:
self.elem_start = self.activ_elem
start_x = self.activ_elem[0]
start_y = self.activ_elem[1]
click = 1
elif click == 1:
self.elem_end = self.activ_elem
end_x = self.activ_elem[0]
end_y = self.activ_elem[1]
self.master.create_line(start_x, start_y, end_x, end_y, fill="red", width=5)
print("asdkaj")
click = 0
window = Tk()
window.geometry("1000x800")
frame_start = Frame(window)
frame_start.pack(expand=TRUE, fill=BOTH)
draw_canvas = Canvas(frame_start)
draw_canvas.pack(expand=TRUE, fill=BOTH)
created_feature_1 = features_object(draw_canvas, 'feature A', 100, 100, 'red')
created_feature_2 = features_object(draw_canvas, 'feature B', 300, 300, 'green')
created_feature_3 = features_object(draw_canvas, 'feature C', 500, 500, 'magenta')
if __name__ == '__main__':
window.mainloop()
Output
This code is fine, but I would like to scroll the page using the mousewheel just like we do with Chrome, when the pointer of the mouse is in the middle of the page.
import tkinter as tk
from random import randint
class ScrolledFrame(tk.Frame):
def __init__(self, parent, vertical=True, horizontal=False):
super().__init__(parent)
self._canvas = tk.Canvas(self)
self._canvas.grid(row=0, column=0, sticky='news') # changed
self._vertical_bar = tk.Scrollbar(self, orient='vertical', command=self._canvas.yview)
if vertical:
self._vertical_bar.grid(row=0, column=1, sticky='ns')
self._canvas.configure(yscrollcommand=self._vertical_bar.set)
self._horizontal_bar = tk.Scrollbar(self, orient='horizontal', command=self._canvas.xview)
if horizontal:
self._horizontal_bar.grid(row=1, column=0, sticky='we')
self._canvas.configure(xscrollcommand=self._horizontal_bar.set)
self._vertical_bar.config(command=self._canvas.yview)
self.inner = tk.Frame(self._canvas, bg='red')
self._window = self._canvas.create_window((0, 0), window=self.inner, anchor='nw')
self.columnconfigure(0, weight=1) # changed
self.rowconfigure(0, weight=1) # changed
self.inner.bind('<Configure>', self.resize)
self._canvas.bind('<Configure>', self.frame_width)
def frame_width(self, event):
canvas_width = event.width
self._canvas.itemconfig(self._window, width=canvas_width)
def resize(self, event=None):
self._canvas.configure(scrollregion=self._canvas.bbox('all'))
class Question:
def __init__(self, parent, question, answer):
self.parent = parent
self.question = question
self.answer = answer
self.create_widgets()
def get_input(self):
value = self.entry.get()
print('value:', value)
if value == self.answer:
print("Right it's " + self.answer)
self.label['text'] = self.question + "Right it's " + self.answer
else:
self.label['text'] = "Sorry, it was " + self.answer
def create_widgets(self):
self.labelframe = tk.LabelFrame(self.parent, text="Domanda:")
self.labelframe.pack(fill="both", expand=True)
self.label = tk.Label(self.labelframe, text=self.question)
self.label.pack(expand=True, fill='both')
self.entry = tk.Entry(self.labelframe)
self.entry.pack()
self.entry.bind("<Return>", lambda x: self.get_input())
root = tk.Tk()
root.title("Quiz")
root.geometry("400x300")
window = ScrolledFrame(root)
window.pack(expand=True, fill='both')
for i in range(10):
one = randint(1, 10)
two = randint(1, 10)
Question(window.inner, "How is the result of {} + {} ?".format(one, two), str(one + two))
root.mainloop()
I found how to make it
Ok, I had some problems asking how to make it, but thanks to https://code.activestate.com/recipes/580640-scrolling-frame-with-mouse-wheel-support/ I succeded in making the mousewheel work as I intended. If it can help, the example is here.
import tkinter as tk
from random import randint
# --- classes ---
try:
from Tkinter import Canvas, Frame
from ttk import Scrollbar
from Tkconstants import *
except ImportError:
from tkinter import Canvas, Frame
from tkinter.ttk import Scrollbar
from tkinter.constants import *
import platform
OS = platform.system()
class Mousewheel_Support(object):
# implemetation of singleton pattern
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = object.__new__(cls)
return cls._instance
def __init__(self, root, horizontal_factor=2, vertical_factor=2):
self._active_area = None
if isinstance(horizontal_factor, int):
self.horizontal_factor = horizontal_factor
else:
raise Exception("Vertical factor must be an integer.")
if isinstance(vertical_factor, int):
self.vertical_factor = vertical_factor
else:
raise Exception("Horizontal factor must be an integer.")
if OS == "Linux":
root.bind_all('<4>', self._on_mousewheel, add='+')
root.bind_all('<5>', self._on_mousewheel, add='+')
else:
# Windows and MacOS
root.bind_all("<MouseWheel>", self._on_mousewheel, add='+')
def _on_mousewheel(self, event):
if self._active_area:
self._active_area.onMouseWheel(event)
def _mousewheel_bind(self, widget):
self._active_area = widget
def _mousewheel_unbind(self):
self._active_area = None
def add_support_to(self, widget=None, xscrollbar=None, yscrollbar=None, what="units", horizontal_factor=None, vertical_factor=None):
if xscrollbar is None and yscrollbar is None:
return
if xscrollbar is not None:
horizontal_factor = horizontal_factor or self.horizontal_factor
xscrollbar.onMouseWheel = self._make_mouse_wheel_handler(widget, 'x', self.horizontal_factor, what)
xscrollbar.bind('<Enter>', lambda event, scrollbar=xscrollbar: self._mousewheel_bind(scrollbar))
xscrollbar.bind('<Leave>', lambda event: self._mousewheel_unbind())
if yscrollbar is not None:
vertical_factor = vertical_factor or self.vertical_factor
yscrollbar.onMouseWheel = self._make_mouse_wheel_handler(widget, 'y', self.vertical_factor, what)
yscrollbar.bind('<Enter>', lambda event, scrollbar=yscrollbar: self._mousewheel_bind(scrollbar))
yscrollbar.bind('<Leave>', lambda event: self._mousewheel_unbind())
main_scrollbar = yscrollbar if yscrollbar is not None else xscrollbar
if widget is not None:
if isinstance(widget, list) or isinstance(widget, tuple):
list_of_widgets = widget
for widget in list_of_widgets:
widget.bind('<Enter>', lambda event: self._mousewheel_bind(widget))
widget.bind('<Leave>', lambda event: self._mousewheel_unbind())
widget.onMouseWheel = main_scrollbar.onMouseWheel
else:
widget.bind('<Enter>', lambda event: self._mousewheel_bind(widget))
widget.bind('<Leave>', lambda event: self._mousewheel_unbind())
widget.onMouseWheel = main_scrollbar.onMouseWheel
#staticmethod
def _make_mouse_wheel_handler(widget, orient, factor=1, what="units"):
view_command = getattr(widget, orient + 'view')
if OS == 'Linux':
def onMouseWheel(event):
if event.num == 4:
view_command("scroll", (-1) * factor, what)
elif event.num == 5:
view_command("scroll", factor, what)
elif OS == 'Windows':
def onMouseWheel(event):
view_command("scroll", (-1) * int((event.delta / 120) * factor), what)
elif OS == 'Darwin':
def onMouseWheel(event):
view_command("scroll", event.delta, what)
return onMouseWheel
class Scrolling_Area(Frame, object):
def __init__(self, master, width=None, anchor=N, height=None, mousewheel_speed=2, scroll_horizontally=True, xscrollbar=None, scroll_vertically=True, yscrollbar=None, background=None, inner_frame=Frame, **kw):
Frame.__init__(self, master, class_="Scrolling_Area", background=background)
self.grid_columnconfigure(0, weight=1)
self.grid_rowconfigure(0, weight=1)
self._width = width
self._height = height
self.canvas = Canvas(self, background=background, highlightthickness=0, width=width, height=height)
self.canvas.grid(row=0, column=0, sticky=N + E + W + S)
if scroll_vertically:
if yscrollbar is not None:
self.yscrollbar = yscrollbar
else:
self.yscrollbar = Scrollbar(self, orient=VERTICAL)
self.yscrollbar.grid(row=0, column=1, sticky=N + S)
self.canvas.configure(yscrollcommand=self.yscrollbar.set)
self.yscrollbar['command'] = self.canvas.yview
else:
self.yscrollbar = None
if scroll_horizontally:
if xscrollbar is not None:
self.xscrollbar = xscrollbar
else:
self.xscrollbar = Scrollbar(self, orient=HORIZONTAL)
self.xscrollbar.grid(row=1, column=0, sticky=E + W)
self.canvas.configure(xscrollcommand=self.xscrollbar.set)
self.xscrollbar['command'] = self.canvas.xview
else:
self.xscrollbar = None
self.rowconfigure(0, weight=1)
self.columnconfigure(0, weight=1)
self.innerframe = inner_frame(self.canvas, **kw)
self.innerframe.pack(anchor=anchor)
self.canvas.create_window(0, 0, window=self.innerframe, anchor='nw', tags="inner_frame")
self.canvas.bind('<Configure>', self._on_canvas_configure)
Mousewheel_Support(self).add_support_to(self.canvas, xscrollbar=self.xscrollbar, yscrollbar=self.yscrollbar)
#property
def width(self):
return self.canvas.winfo_width()
#width.setter
def width(self, width):
self.canvas.configure(width=width)
#property
def height(self):
return self.canvas.winfo_height()
#height.setter
def height(self, height):
self.canvas.configure(height=height)
def set_size(self, width, height):
self.canvas.configure(width=width, height=height)
def _on_canvas_configure(self, event):
width = max(self.innerframe.winfo_reqwidth(), event.width)
height = max(self.innerframe.winfo_reqheight(), event.height)
self.canvas.configure(scrollregion="0 0 %s %s" % (width, height))
self.canvas.itemconfigure("inner_frame", width=width, height=height)
def update_viewport(self):
self.update()
window_width = self.innerframe.winfo_reqwidth()
window_height = self.innerframe.winfo_reqheight()
if self._width is None:
canvas_width = window_width
else:
canvas_width = min(self._width, window_width)
if self._height is None:
canvas_height = window_height
else:
canvas_height = min(self._height, window_height)
self.canvas.configure(scrollregion="0 0 %s %s" % (window_width, window_height), width=canvas_width, height=canvas_height)
self.canvas.itemconfigure("inner_frame", width=window_width, height=window_height)
class Question:
def __init__(self, parent, question, answer):
self.parent = parent
self.question = question
self.answer = answer
self.create_widgets()
def get_input(self):
value = self.entry.get()
print('value:', value)
if value == self.answer:
print("Right it's " + self.answer)
self.label['text'] = self.question + "Right it's " + self.answer
else:
self.label['text'] = "Sorry, it was " + self.answer
def create_widgets(self):
self.labelframe = tk.LabelFrame(self.parent, text="Domanda:")
self.labelframe.pack(fill="both", expand=True)
self.label = tk.Label(self.labelframe, text=self.question)
self.label.pack(expand=True, fill='both')
self.entry = tk.Entry(self.labelframe)
self.entry.pack()
self.entry.bind("<Return>", lambda x: self.get_input())
# self.button = tk.Button(self.labelframe, text="Click", command=self.get_input)
# self.button.pack()
# --- main ---
root = tk.Tk()
root.title("Quiz")
root.geometry("400x300")
window = Scrolling_Area(root)
window.pack(expand=True, fill='both')
for i in range(10):
one = randint(1, 10)
two = randint(1, 10)
Question(window.innerframe, "How is the result of {} + {} ?".format(one, two), str(one + two))
domande = [("Qual รจ la prima leva del marketing mix? (prodotto o prezzo?", "prodotto")]
for d, r in domande:
Question(window.innerframe, d, r)
root.mainloop()
I'm new to python and tkinter and I've been getting the error below whenever I try and add custom grid sizes to my program. I'm pretty sure this isn't a duplicate thread as in all other threads, none of them involve a grid or utilize the grid function within their issue.
TypeError: unsupported operand type(s) for /: 'int' and 'str' when making grid
The error I'm getting occurs whenever I try and change the vale of the GridSize within the GUI. You can change the value of it in the 'Change the settings of the treasure hunting game' part of the menu. I'm new to python so please put it in the simplest terms possible!
Here's my code:
import tkinter
import math
import random
from tkinter import *
import tkinter as tk
from tkinter import ttk
GridSizeSetByUser = '8x8'
choicesRows = ['8', '10', '12', '14']
v = choicesRows[0]
choicesColumns = ['8', '10', '12', '14']
v2 = choicesColumns[0]
GridRows = 9
GridColumns = 9
def getRows():
global GridRows
GridRows = GridRowSpinbox.get()
print(GridRows)
def getColumns():
global GridColumns
GridColumns = GridColumnSpinbox.get()
print(GridColumns)
def Treasure_Hunt_Window():
THunt = tk.Tk()
THunt.title("Treasure Hunt")
THuntInstructions = "Find the treasure hidden deep in the sand!Use ye arrow keys to move around,\n\n then press Space to search that spot! Keep searching until ye find it!"
board = GameBoard(THunt)
board.pack(side="top", fill="both", expand="true", padx=4, pady=4)
THunt.mainloop()
def Settings_Window():
Settings = tk.Tk()
Settings.title("Settings")
SettingsWelcome = tk.Label(Settings, text='Settings Menu', width=50, fg="magenta")
SettingsGridSize = tk.Label(Settings, text='Grid Size:', width =50, fg="magenta")
global mystring
mystring = StringVar()
global mystring2
mystring2 = StringVar()
global GridRowSpinbox
GridRowSpinbox = Spinbox(Settings, values=choicesRows, textvariable=mystring, width=50, state="readonly", fg="magenta")
SaveRowSize = tk.Button(Settings, text='Save row size for grid', width=50, fg="magenta", command = getRows)
global GridColumnSpinbox
GridColumnSpinbox = Spinbox(Settings, values=choicesColumns, textvariable=mystring2, state="readonly", width=50, fg="magenta")
SaveColumnSize = tk.Button(Settings, text='Save column size for grid', width=50, fg="magenta", command = getColumns)
SettingsBandits = tk.Label(Settings, text='Amount of Bandits:', width =50, fg="magenta")
BanditAmount = tk.Entry(Settings, width = 50, fg="magenta")
SettingsBandits = tk.Label(Settings, text='Amount of Treasure Chests (up to 64)', width =50, fg="magenta")
SettingsWelcome.pack(fill=X)
SettingsGridSize.pack(fill=X)
GridRowSpinbox.pack(fill=X)
SaveRowSize.pack(fill=X)
GridColumnSpinbox.pack(fill=X)
SaveColumnSize.pack(fill=X)
SettingsBandits.pack(fill=X)
BanditAmount.pack(fill=X)
def main():
root = tk.Tk()
root.title("Menu")
WelcomeButton = tk.Label(root, text='Welcome to the menu!', width=50, height=2, fg="magenta")
WelcomeButton.pack(fill=X)
StartButton = tk.Button(root, text='Start treasure hunting!', width=50, fg="magenta", command = Treasure_Hunt_Window)
StartButton.pack(fill=X)
SettingsButton = tk.Button(root, text='''Change the settings of the treasure hunting game.
This includes the grid size.''', width=50, fg="magenta", command = Settings_Window)
SettingsButton.pack(fill=X)
QuitButton = tk.Button(root, text='Exit the program', width=50, fg="magenta", command = root.destroy)# display message in a child window.
QuitButton.pack(fill=X)
root.mainloop()
def teststuff():
print(GridRows)
print(GridColumns)
class GameBoard(tk.Frame):
def __init__(self, parent, size=48, color1="white", color2="black"):
'''size is the size of a square, in pixels'''
self.rows = GridRows
self.columns = GridColumns
self.size = size
self.color1 = color1
self.color2 = color2
self.pieces = {}
canvas_width = GridColumns * size
canvas_height = GridRows * size
tk.Frame.__init__(self, parent)
self.canvas = tk.Canvas(self, borderwidth=0, highlightthickness=0,
width=canvas_width, height=canvas_height, background="green")
self.canvas.pack(side="top", fill="both", expand=True, padx=2, pady=2)
self.canvas.bind("<Configure>", self.refresh)
def refresh(self, event):
'''Redraw the board, possibly in response to window being resized'''
xsize = int((event.width-1) / self.columns)
ysize = int((event.height-1) / self.rows)
self.size = min(xsize, ysize)
self.canvas.delete("square")
color = self.color2
for row in range(self.rows):
color = self.color1 if color == self.color2 else self.color2
for col in range(self.columns):
x1 = (col * self.size)
y1 = (row * self.size)
x2 = x1 + self.size
y2 = y1 + self.size
self.canvas.create_rectangle(x1, y1, x2, y2, outline="black", fill=color, tags="square")
color = self.color1 if color == self.color2 else self.color2
for name in self.pieces:
self.placepiece(name, self.pieces[name][0], self.pieces[name][1])
self.canvas.tag_raise("piece")
self.canvas.tag_lower("square")
main()
Please continue working on your program, but replace your code with the following and work from there. You may also want to make it a practice to run your code through the PEP8 online website. Changes that were made to your code include ensuring that no errors or warnings were generated.
To answer your question, two of the functions down below do something slightly different from what your code originally did. Notice the first two functions, get_rows and get_columns. When getting information from a Spinbox, you need to convert the data into the correct type before using it.
from tkinter import *
import tkinter as tk
GridSizeSetByUser = '8x8'
choicesRows = ['8', '10', '12', '14']
v = choicesRows[0]
choicesColumns = ['8', '10', '12', '14']
v2 = choicesColumns[0]
GridRows = 9
GridColumns = 9
my_string = my_second_string = grid_row_spinbox = grid_column_spinbox = None
def get_rows():
global GridRows
GridRows = int(grid_row_spinbox.get())
print(repr(GridRows))
def get_columns():
global GridColumns
GridColumns = int(grid_column_spinbox.get())
print(repr(GridColumns))
def treasure_hunt_window():
t_hunt = tk.Tk()
t_hunt.title("Treasure Hunt")
# t_hunt_instructions = """\
# Find the treasure hidden deep in the sand!Use ye arrow keys to move around,
#
# then press Space to search that spot! Keep searching until ye find it!"""
board = GameBoard(t_hunt)
board.pack(side="top", fill="both", expand="true", padx=4, pady=4)
t_hunt.mainloop()
def settings_window():
global my_string, my_second_string, grid_row_spinbox, grid_column_spinbox
settings = tk.Tk()
settings.title("Settings")
settings_welcome = tk.Label(settings, text='Settings Menu', width=50,
fg="magenta")
settings_grid_size = tk.Label(settings, text='Grid Size:', width=50,
fg="magenta")
my_string = StringVar()
my_second_string = StringVar()
grid_row_spinbox = Spinbox(settings, values=choicesRows,
textvariable=my_string, width=50,
state="readonly", fg="magenta")
save_row_size = tk.Button(settings, text='Save row size for grid',
width=50, fg="magenta", command=get_rows)
grid_column_spinbox = Spinbox(settings, values=choicesColumns,
textvariable=my_second_string,
state="readonly", width=50, fg="magenta")
save_column_size = tk.Button(settings, text='Save column size for grid',
width=50, fg="magenta", command=get_columns)
# settings_bandits = tk.Label(settings, text='Amount of Bandits:',
# width=50, fg="magenta")
bandit_amount = tk.Entry(settings, width=50, fg="magenta")
settings_bandits = tk.Label(settings,
text='Amount of Treasure Chests (up to 64)',
width=50, fg="magenta")
settings_welcome.pack(fill=X)
settings_grid_size.pack(fill=X)
grid_row_spinbox.pack(fill=X)
save_row_size.pack(fill=X)
grid_column_spinbox.pack(fill=X)
save_column_size.pack(fill=X)
settings_bandits.pack(fill=X)
bandit_amount.pack(fill=X)
def main():
root = tk.Tk()
root.title("Menu")
welcome_button = tk.Label(root, text='Welcome to the menu!', width=50,
height=2, fg="magenta")
welcome_button.pack(fill=X)
start_button = tk.Button(root, text='Start treasure hunting!', width=50,
fg="magenta", command=treasure_hunt_window)
start_button.pack(fill=X)
settings_button = tk.Button(root, text='''\
Change the settings of the treasure hunting game.
This includes the grid size.''', width=50, fg="magenta",
command=settings_window)
settings_button.pack(fill=X)
# display message in a child window.
quit_button = tk.Button(root, text='Exit the program', width=50,
fg="magenta", command=root.destroy)
quit_button.pack(fill=X)
root.mainloop()
def test_stuff():
print(GridRows)
print(GridColumns)
class GameBoard(tk.Frame):
def __init__(self, parent, size=48, color1="white", color2="black"):
"""size is the size of a square, in pixels"""
self.rows = GridRows
self.columns = GridColumns
self.size = size
self.color1 = color1
self.color2 = color2
self.pieces = {}
canvas_width = GridColumns * size
canvas_height = GridRows * size
tk.Frame.__init__(self, parent)
self.canvas = tk.Canvas(self, borderwidth=0, highlightthickness=0,
width=canvas_width, height=canvas_height,
background="green")
self.canvas.pack(side="top", fill="both", expand=True, padx=2, pady=2)
self.canvas.bind("<Configure>", self.refresh)
def refresh(self, event):
"""Redraw the board, possibly in response to window resize"""
x_size = int((event.width-1) / self.columns)
y_size = int((event.height-1) / self.rows)
self.size = min(x_size, y_size)
self.canvas.delete("square")
color = self.color2
for row in range(self.rows):
color = self.color1 if color == self.color2 else self.color2
for col in range(self.columns):
x1 = (col * self.size)
y1 = (row * self.size)
x2 = x1 + self.size
y2 = y1 + self.size
self.canvas.create_rectangle(x1, y1, x2, y2, outline="black",
fill=color, tags="square")
color = self.color1 if color == self.color2 else self.color2
for name in self.pieces:
self.place_piece(name, self.pieces[name][0], self.pieces[name][1])
self.canvas.tag_raise("piece")
self.canvas.tag_lower("square")
def place_piece(self, name, a, b):
pass
if __name__ == '__main__':
main()
I've got a script in python2.7 write in Pycharm IDE on windows, can I run same program in ubuntu ?
from Tkinter import *
import tkFileDialog
from PIL import Image, ImageTk
class App:
label_rgb_template = "R: {0}, G: {1}, B: {2}"
def __init__(self):
self.picked_image_filename = None
self.image = None
self.tk_image = None
self.image_id = None
self.image_filename = None
self.current_size = None
self.current_factor = None
self.root = root = Tk()
self.offset_x = 0
self.offset_y = 0
root.title('Biomteria')
root.size = (500, 500)
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=1)
root.bind("<Configure>", self.resize_handler)
root.bind("<Key>", self.root_key_press_handler)
frame = Frame(root)
frame.grid(column=0, row=0, sticky=N + S + W + E)
frame.grid_columnconfigure(10, weight=1)
btn_open = Button(frame, text='otworz plik', command=self.open_image)
btn_save = Button(frame, text='zapisz plik', command=self.save_image)
btn_zoom_in = Button(frame, text='+', command=self.zoom_in)
btn_zoom_out = Button(frame, text='-', command=self.zoom_out)
self.entry_red = entry_red = Spinbox(frame, from_=0, to=255)
label_entry_red = Label(frame, text="R:")
self.entry_green = entry_green = Spinbox(frame, from_=0, to=255)
label_entry_green = Label(frame, text="G:")
self.entry_blue = entry_blue = Spinbox(frame, from_=0, to=255)
label_entry_blue = Label(frame, text="B:")
self.label_rgb_text = StringVar()
self.label_rgb_text.set(self.label_rgb_template.format(0, 0, 0))
label_rgb = Label(frame, textvariable=self.label_rgb_text)
btn_open.grid(row=0, column=0)
btn_save.grid(row=0, column=1)
btn_zoom_in.grid(row=0, column=2)
btn_zoom_out.grid(row=0, column=3)
label_entry_red.grid(row=0, column=4)
entry_red.grid(row=0, column=5)
label_entry_green.grid(row=0, column=6)
entry_green.grid(row=0, column=7)
label_entry_blue.grid(row=0, column=8)
entry_blue.grid(row=0, column=9)
label_rgb.grid(row=0, column=10, sticky=E)
self.canvas = canvas = Canvas(root)
canvas.grid(row=1, column=0, sticky=N + S + W + E)
canvas.bind("<Button-1>", self.canvas_click_handler)
canvas.bind("<Motion>", self.canvas_motion_handler)
self.root.mainloop()
def open_image(self):
self.image_filename = image_filename = tkFileDialog.askopenfilename(filetypes=(('All files', '*.*'),))
self.image = Image.open(image_filename)
self.image = self.image.convert("RGB")
self.current_size = self.image.size
self.current_factor = 1
self.refresh()
def save_image(self):
image_filename = tkFileDialog.asksaveasfilename(initialfile=self.image_filename)
self.image.save(image_filename)
def zoom(self, factor):
self.current_size = tuple((int(value * factor) for value in self.current_size))
self.current_factor = int(self.current_factor * factor)
self.refresh()
def zoom_in(self):
self.zoom(2)
def zoom_out(self):
self.zoom(0.5)
def refresh(self):
center = (self.canvas.winfo_width() / 2 + self.offset_x, self.canvas.winfo_height() / 2 + self.offset_y)
self.canvas.delete(self.image_id)
self.tk_image = ImageTk.PhotoImage(self.image.resize(self.current_size))
self.image_id = self.canvas.create_image(center, image=self.tk_image)
def resize_handler(self, evt):
if self.image:
self.refresh()
def get_pixel_coords(self, evt):
bbox = self.canvas.bbox(ALL)
if bbox and bbox[0] <= evt.x <= bbox[2] and bbox[1] <= evt.y < bbox[3]:
pixel_coords = evt.x - bbox[0], evt.y - bbox[1]
return tuple((value / self.current_factor for value in pixel_coords))
return None
def canvas_click_handler(self, evt):
pixel_coords = self.get_pixel_coords(evt)
if pixel_coords:
color = self.entry_red.get(), self.entry_green.get(), self.entry_blue.get()
color = tuple(int(value) for value in color)
self.image.putpixel(pixel_coords, color)
self.refresh()
def canvas_motion_handler(self, evt):
pixel_coords = self.get_pixel_coords(evt)
if pixel_coords:
self.label_rgb_text.set(self.label_rgb_template.format(*self.image.getpixel(pixel_coords)))
def root_key_press_handler(self, evt):
code = evt.keycode
print code
if code == 37:
self.offset_x -= 10
if code == 38:
self.offset_y -=10
if code == 39:
self.offset_x += 10
if code == 40:
self.offset_y += 10
self.refresh()
I have to change something ?, becouse when I runing that script on ubuntu a script window opens, but buttons doesn't work
If this is all of your code, you're forgetting to create an instance of App. Add the following to the bottom of the file:
if __name__ == "__main__":
app = App()
I am working on a project where I got rid of the root window. And I made my own. I have it working but I have not been able to find out a way to minimize the window.
I tried using root.iconify() with root.root.overrideredirect(True) set. But it gives me the following error: TclError: can't iconify ".": override-redirect flag is set.
How can I minimize the window without getting this error and where it minimizes it like a normal root window.
Code:
from Tkinter import *
import time
import os
class Application(Frame):
def __init__(self, parent):
Frame.__init__(self,parent)
self.pack(fill=BOTH)
self.create_widgets()
def create_widgets(self):
self.borderFrame = Frame(self, width=500, height=600, bg="Gray")
self.borderFrame.pack_propagate(False)
self.borderFrame.pack(side=TOP)
self.holderFrame = Frame(self.borderFrame, width=500, height=570, bg="blue")
self.holderFrame.pack_propagate(False)
self.holderFrame.pack(side=BOTTOM)
self.close = Label(self, font=("Arial", 11), bg="Gray", anchor=CENTER, text="X", cursor="hand2")
self.close.place(x=460, y=0, width=40, height=30)
self.min = Label(self, font=("Arial", 11), bg="Gray", anchor=CENTER, text="_", cursor="hand2")
self.min.place(x=420, y=0, width=40, height=30)
def hoverMin(event):
event.widget.config(bg="lightBlue")
def unHoverMin(event):
event.widget.config(bg="Gray")
self.min.bind("<Enter>", hoverMin)
self.min.bind("<Leave>", unHoverMin)
self.min.bind("<Button-1>", self.minimize)
def hover(event):
event.widget.config(bg="red")
def unhover(event):
event.widget.config(bg="Gray")
self.close.bind("<Enter>", hover)
self.close.bind("<Leave>", unhover)
self.close.bind("<Button-1>", self.exitProgram)
self.borderFrame.bind("<Button-1>", self.startMove)
self.borderFrame.bind("<ButtonRelease-1>", self.stopMove)
self.borderFrame.bind("<B1-Motion>", self.moving)
def startMove(self, event):
self.x = event.x
self.y = event.y
def stopMove(self, event):
self.x = None
self.y = None
def moving(self,event):
x = (event.x_root - self.x - self.borderFrame.winfo_rootx() + self.borderFrame.winfo_rootx())
y = (event.y_root - self.y - self.borderFrame.winfo_rooty() + self.borderFrame.winfo_rooty())
root.geometry("+%s+%s" % (x, y))
def minimize(self, event):
root.iconify()
def exitProgram(self, event):
os._exit(0)
root = Tk()
root.title("Draggable Root")
root.geometry("500x600")
root.overrideredirect(True)
app = Application(root)
root.mainloop()
Calling overrideredirect(True) declares to the window manager that you will handle all of your own window-management. Iconification is a window-manager thing. If you just want to hide the window, then changing the minimize function to root.state('withdrawn') does that. Call root.state('normal') to show the window again.
In order to appear in the taskbar, you need to call root.overrideredirect(False) before you call root.state('iconic') AND BEFORE THAT you need to call root.update_idletasks(). See the change to the minimize method.
In order to get the window back the way you want, I made a new method 'frame_mapped' and bound it to the Map event on the borderFrame. Map events happen when a widget gets handled by the geometry manager ( pack/place/grid). So that when you click on the taskbar to un-minimize, 'frame_mapped' gets triggered to call overrideredirect(True) again.
Here is the modified code:
try:
from Tkinter import *
except ImportError:
from tkinter import *
import time
import os
class Application(Frame):
def __init__(self, parent):
Frame.__init__(self,parent)
self.pack(fill=BOTH)
self.create_widgets()
def create_widgets(self):
self.borderFrame = Frame(self, width=500, height=600, bg="Gray")
self.borderFrame.pack_propagate(False)
self.borderFrame.pack(side=TOP)
self.holderFrame = Frame(self.borderFrame, width=500, height=570, bg="blue")
self.holderFrame.pack_propagate(False)
self.holderFrame.pack(side=BOTTOM)
self.close = Label(self, font=("Arial", 11), bg="Gray", anchor=CENTER, text="X", cursor="hand2")
self.close.place(x=460, y=0, width=40, height=30)
self.min = Label(self, font=("Arial", 11), bg="Gray", anchor=CENTER, text="_", cursor="hand2")
self.min.place(x=420, y=0, width=40, height=30)
def hoverMin(event):
event.widget.config(bg="lightBlue")
def unHoverMin(event):
event.widget.config(bg="Gray")
self.min.bind("<Enter>", hoverMin)
self.min.bind("<Leave>", unHoverMin)
self.min.bind("<Button-1>", self.minimize)
def hover(event):
event.widget.config(bg="red")
def unhover(event):
event.widget.config(bg="Gray")
self.close.bind("<Enter>", hover)
self.close.bind("<Leave>", unhover)
self.close.bind("<Button-1>", self.exitProgram)
self.borderFrame.bind("<Button-1>", self.startMove)
self.borderFrame.bind("<ButtonRelease-1>", self.stopMove)
self.borderFrame.bind("<B1-Motion>", self.moving)
self.borderFrame.bind("<Map>",self.frame_mapped)
def startMove(self, event):
self.x = event.x
self.y = event.y
def stopMove(self, event):
self.x = None
self.y = None
def moving(self,event):
x = (event.x_root - self.x - self.borderFrame.winfo_rootx() + self.borderFrame.winfo_rootx())
y = (event.y_root - self.y - self.borderFrame.winfo_rooty() + self.borderFrame.winfo_rooty())
root.geometry("+%s+%s" % (x, y))
def frame_mapped(self,e):
print(self,e)
root.update_idletasks()
root.overrideredirect(True)
root.state('normal')
def minimize(self, event):
root.update_idletasks()
root.overrideredirect(False)
#root.state('withdrawn')
root.state('iconic')
def exitProgram(self, event):
os._exit(0)
root = Tk()
root.title("Draggable Root")
root.geometry("500x600")
root.overrideredirect(True)
app = Application(root)
root.mainloop()