The Ctrl+Shift+a not working inTkinter bind_all - python

I am trying to recreate the notepad. I have added a lot of shortcut keys with a combination of two keys. I am trying to make a three combination shortcut, which will be Ctrl+Shift+s. But when I used <Control-Shift-Key-s> it's not working. I had even tried app.bind<Control-Shift-KeyPress-s> which I found at the Control+Shift+Tab key binding in stack overflow. When I used Tab instead of s that worked, when I use s nothing happens. I want to create a key binding of Control+Shift+s. How Can I Do That?This Is My Code:
from tkinter import *
app = Tk()
def SaveAs(event):
#Some code to save as new file.
print('Pressed Ctrl+Shift+s.')
app.bind_all('<Control-Shift-Key-s>', SaveAs)

Make sure that you are not mixing up uppercase and lowercase, because in Tkinter, "<Control-S>" means CTRL-SHIFT-S and "<Control-s>" means CTRL-S.
So, this line:
app.bind_all('<Control-Shift-Key-s>', SaveAs)
must be
app.bind_all('<Control-S>', SaveAs)

Related

How to simulate random key inputs from a pre-defined set of keys, key combinations? tkinter GUI / window not working

i'm a beginner in python, only having finished a course on it and currently working through a book.
A fairly simple project (and one of the few actually useful things i could think of) is an anit-AFK tool. I started googleing and found a few elements that i fried to combine.
So i "frankensteined" a script together by stitching different elements and my first test seem to work kinda fine, generally sort of doing what i want it to.
However i have a few problems:
1: tkinter GUI doesn't really work (i'm running the code directly from PyCharm); a window opens but it completely lacks the buttons or anything really. It's a blank window, that seems to have the dimension i gave it, but lacking everything else.
2: I don't know how to make it press random keys, from a set of pre-defined keys and key combinations.
My idea was assigning each key to a number, then having a random number generator pick a number, assigning it to a variable. All of that in a loop so that each time another loop decides it's time to press a key, the key (combination') is a new random one.
Now that i've explained the general idea, here's the code i have until now:
import pyautogui
from random import randint
from time import sleep
from tkinter import *
running = True
key = ["w", "a", "s", "d"] # this is the "base" keys
key_2 = [key[randint(0,3)], key[randint(0,3)] + "shift", "space"] # this is for combinations
def anti_afk():
while running:
pyautogui.press(key_2[randint(0,2)])
print("Test") # to easily test if the sleep is working working
sleep(randint(5,30))
def start():
running = True
def stop():
running = False
root = Tk()
root.title("Anti AFK Tool")
root.geometry ("500x500")
app = Frame(root)
app.grid
start = Button(app, text="Start anti-AFK", command=start)
stop = Button(app, text="Stop preventing AFK", command=stop)
start.grid()
stop.grid()
root.after(1000, anti_afk)
root.mainloop()
As i said above i'm a beginner and pretty much everything regarding tkinter and pyautogui isn't written by me but taken from THIS and THIS post right here. Also this is the very first time i use tkinter
So, when running it with only one key (W key in my case) it generally seems to work kinda fine. The GUI doesn't work beyond what i described above.
I'm programming on my MacBook and get the "spinning ball of death" in the application window. Generally i want the program do be running mainly on windows.
So the problem is that the random key selections seems to be not working like i want it to. Especially the (in this case) shift+key doesn't. Also the GUI of the program doesn't work.
Another idea i had was defining a function for each action seperately and then randomly calling that function. But the problem of how to call / use random functions / list elements is basically the same and the list solution seems much more flexible with less code.
Can you help me with this?

Using tkinter's button and entry widgets to update instance variable

I am trying to implement a little application that logs in a user and the user after log in can add/update/delete contents to/of a textfile. Here's a rough sketch of the code I have so far:
class admin():
def __init__(self):
self.app = Tk()
.
self.name=StringVar()
update = Button(self.app,....,command=self.update)
.
.
.
def update():
#Function to take different entries using Entry widget of tkinter in another window
anotherapp = Tk()
nameentry = Entry(anotherapp,textvariable = self.name)
submitbutton = Button(anotherapp,....,command=submit)
.
.
def submit():
#Opens a file and adds entries to a textfile.
namevar = self.name.get()
# code to append to file
To explain the above, I have a class admin. Creating an instance of this class would open a window with buttons that say create, update, delete and so on. On clicking one of the buttons, the respective functions (defined in the same class) would be called (I use lambda: in case the function has arguments, but so far, it doesn't).
So in the code I've mentioned, say I click on the Update button, it should call the update function which opens another window and takes the text that has to be updated in the text file (via the Entry widget). So according to the code it'll update the value of name. On clicking submit, the function submit uses .get() to get the string value of name, and appends it to the text file.
The code executes with no error but it DOES NOT read the input from the user. Blank lines get appended to my textfile when I click on the submit button.
Now I don't understand why this isn't working. The name variable is defined in init and can be updated by the functions of the same class. I have tried a lot of things to make this work, including adding parameters in the button commands, defining name elsewhere, etc. Even though I've solved the error, I get the same result: the file gets appended with blank lines. I've also tried to make name a class variable but that doesn't work since it is declared using StringVar() which needs it to be part of a tkinter window. I think I've also tried nesting submit function inside the update function, but I don't know why that didn't work out or if I hadn't implemented it correctly.
I don't know if it has to do with the working of tkinter's StringVar() and .get() function.
I can't think of any other way to implement the situation I have at hand. I am open to taking suggestions on changing the structure of the code, as long as it is not something major major and manages to achieve the functionality that I've described.
I am sorry if I've missed something basic, cause I've only started trying out OOP in python recently. And thanks in advance for any help.

How to specify input language for Entry or any other input field?

In short, i try to type letters (in input components like "Entry", "Text") that are allowed by Windows language-keyboard (i'm using "Latvan(QWERTY)" keyboard) and i can't write long letters like 'ā', 'č', 'ģ' and others.
For example, when i try to write 'ā', the result is 'â'.
The interesting part - when i focus on specific GUI input fiend and change Windows keyboard-language (with "Alt+Shift" shortcut or manually) twice (for example, from "Latvan(QWERTY)" to "Russian" and back to "Latvan(QWERTY)") - then i can write all letters i needed.
What i want is to set all input fields keyboard-language so i could write all letters i want without doing things mentioned above every time i launch my GUI program.
If you need more info or there is already place where this question is answered, please leave a comment and i will act accordingly.
Edit 1:
I am using PyCharm to write my Python Tkinter code. I tried to assign necessary keyboard to my program's generated GUI form according to this guide but it didn't work (i guess that because i used it on temporary created GUI forms).
I was able to solve my problem by using pynput.
Here is simplified version of my final code:
from tkinter import *
from pynput.keyboard import Key, Controller
def change_keyboard_lang(event):
keyboard = Controller()
for i in range(2):
keyboard.press(Key.alt)
keyboard.press(Key.shift_l)
keyboard.release(Key.shift_l)
keyboard.release(Key.alt)
root = Tk()
word_input = Entry(root)
word_input.focus_set()
word_input.bind("<FocusIn>", change_keyboard_lang)
word_input.pack()
root.mainloop()
In short, if cursor is focused on Entry field "word_input", system calls function "change_keyboard_lang" that changes input language from original to other and back to original - and now i can write necessary letters.
It's not the best solution since i need to bind event to every input field in my GUI form but it gets the job done. If you have a better solution please post it here.

Naming a file the content of a Text Entry Widget

I am trying to create a program in tkinter that allows people to rename a log file to whatever is typed into a text entry box. However this is not going to plan.
EDITED Thanks to Bryan Oakley.
I have slaved the rename function to a button however my new issue is that the values for contents are a weird set of numbers. These appear to be randomly generated every time I run the rename function.
These numbers look like
44499952get
44452520get
46401376get
46400496get
44688048get
44697440get
Can anyone please help or explain what these numbers mean?
Look at this code:
newname_ent = Entry(self,width = 50,)
contents = newname_ent.get()
It seems highly unlikely that the user will be able to type in something in the millisecond or so between creating the widget and getting the value.
You need to create a button or set an event binding that will call a function after the user has the chance to enter some information. That function is where you will put the code to do the rename.

How do I get the Mac "command" symbol in a Tkinter menu

I've written a Python program for a friend's business, and am using Tkinter for the interface. Up until now, all features have been added in the main program window, but I'm now adding a print feature, have created a simple "File" menu, and want to add a "Print" entry to that menu, including displaying the relevant keyboard shortcut.
On my Mac, I want the shortcut to be Command-P. I found the Mac "command" symbol's Unicode value, and have tried various ways to create an accelerator string that simply concatenates that symbol and the letter "P", but nothing works. I get either the symbol or the letter to display in the menu next to "Print", but never both.
Here is the full line of code that adds the menu item, with the latest attempt at building the string (I believe I found this unicode.join option elsewhere in Stack Overflow):
sub_menu.add_command(label="Print", command=self.print_, accelerator=unicode.join(u"\u2318", u"P"))
// Only the "P" displays
Here are some of the other options that I've tried (lines truncated for clarity). With each of these options, only the "command" symbol appears:
accelerator=u"\u2318\u0050"
accelerator=u"\u2318" + "P"
accelerator=u"\u2318" + u"P"
accelerator=u"\u2318P"
accelerator=u"".join([u"\u2318", u"P"])
Up until now I haven't had a need to learn much about Unicode strings, so perhaps there's something I'm doing wrong in that regard. However, all of the attempts that I've made have come as a result of various searches, both here and elsewhere, and so far nothing has worked. Any insight into how to make this work would be most welcome!
Python 2.7.3, Mac OS X 10.8.3
After further searching online, I finally found a page that has the solution. I was surprised (and a touch annoyed) that this solution was different than the one outlined in the PDF documentation for Tkinter 8.4 that I've been referencing thus far (the one published by New Mexico Tech). I found links to Tkinter 8.5 documentation, but they also list the incorrect process.
Anyway, it's a lot simpler than I thought, and is similar to the syntax used for key binding, but slightly different. Instead of directly including the command symbol in the accelerator string, Tkinter takes the literal word "Command" (or the abbreviated "Cmd"), and internally converts it to the displayable character "⌘" in the menu. So my resulting line is:
sub_menu.add_command(label="Print", command=self.print_, accelerator="Command-P")
...and what I get in my full menu item is:
Print ⌘P
As the page linked above shows, similar shortcut words exist for other modifier keys, and on Mac OS X, these are all automatically translated into their graphical equivalents.
It was actually really easy, all I did was use string formatting to concatenate text="%s%s" % (u"\u2318","P")
Here is a sample Tkinter App, the display is small but it shows what you need.
import Tkinter as tk
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.label = tk.Label(text="%s%s" % (u"\u2318","P"))
self.label.pack(padx=10, pady=10)
app = SampleApp()
app.mainloop()
Output:
⌘P

Categories

Resources