python tkinter listbox performance with other tk/ttk widgets - python

I tried to isolate the problem as best as i could.
Lets assume that there are 3 tk/ttk widgets.
Why doesn't the tk_spinbox unselect the selected listbox entry and why does the ttk_spinbox?
I dont want to unselect the items whenever the ttk_spinbox is pressed. Is there an workaround in order to get an equal behaviour for ttk_spinbox and tk_spinbox?
Here is the code:
import tkinter as tk
import tkinter.ttk as ttk
masterframe = tk.Tk()
listbox = tk.Listbox(masterframe, height=5, selectmode='multiple')
listbox.pack(padx=10, pady=10)
listbox.insert(tk.END, 'blubb_1')
listbox.insert(tk.END, 'blubb_2')
tk_spinbox = tk.Spinbox(masterframe,from_=10, to=20, increment=2)
tk_spinbox.pack(padx=10, pady=10)
ttk_spinbox = ttk.Spinbox(masterframe,from_=10, to=20, increment=2)
ttk_spinbox.pack(padx=10, pady=10)
masterframe.mainloop()

The "why" is simply, that's how they are designed to work. When you interact with a ttk spinbox, the spinbox value is automatically selected. This doesn't happen for the tk spinbox. By default only one thing can have the selection at a time, so the listbox loses the selection when the spinbox gains the selection.
If you don't want to have the listbox lose the selection you can set the exportselection option to False on the listbox and/or the ttk spinbox.

Related

How to access entries beyond the window size in Tkinter

I am creating a form with 40 labels and entries. The problem is that I can enter till 20 after that the window size reaches the maximum and I cannot see entries below it. How do I integrate a scrolling option in Tkinter main window? I know that scrollbar cannot be integrated into main window and only to widgets. I want something so that I can either scroll using mouse or arrow keys or anything to see below content. Below is my code:
from Tkinter import *
root = Tk()
root.title('test')
root.geometry("400x400")
for i in range(40):
Label(root, text="Field {} ".format(i)).grid(row=i,column=0)
value=Entry(root).grid(row=i,column=1)
root.mainloop()
Output image
ListBox
Scrollbars are almost always used in conjunction with Listbox, Canvas or Text widget. To connect a vertical scrollbar to one of these widgets you have to do two things:
Set the widget’s yscrollcommand callbacks to the set method of the scrollbar.
Set the scrollbar’s command to the yview method of the widget.
Example
from tkinter import *
master = Tk()
scrollbar = Scrollbar(master)
scrollbar.pack(side=RIGHT, fill=Y)
listbox = Listbox(master, yscrollcommand=scrollbar.set)
for i in range(40):
listbox.insert(END, Label(master, text=f"Field {i} "))
listbox.insert(END, Entry(master))
listbox.pack(side=LEFT, fill=BOTH)
scrollbar.config(command=listbox.yview)
mainloop()

Why does providing the initialfile argument to tkFileDialog.asksaveasfilename unselect Listbox elements?

Problem
When I provide the initialfile keyword argument to tkFileDialog.asksaveasfilename all my Listbox elements are unselected.
MCVE
I'm using Python 2.7.15+ with Tkinter version 8.6 under Ubuntu 18.04.3 LTS.
import Tkinter as tk
import tkFileDialog
import ttk
# set up a box with some selected elements
root = tk.Tk()
box = tk.Listbox(root, selectmode=tk.MULTIPLE)
for s in ('this', 'is a', 'minimal', 'example'):
box.insert(tk.END, s)
box.selection_set(1)
box.selection_set(3)
box.grid()
# hitting this button does not reset the current selection in box
ttk.Button(root, text='no initialfile',
command=tkFileDialog.asksaveasfilename).grid()
# hitting this button resets the current selection in box - why?
ttk.Button(root, text='with initialfile',
command=lambda: tkFileDialog.asksaveasfilename(initialfile='XXX')).grid()
root.mainloop()
Result
It is due to the fact that by default only one set of text can be selected at a time. That is because tk widgets export the selection to the clipboard, and only one item can be on the clipboard at a time.
You can prevent this from happening by setting exportselection to False on your listbox, removing the connection between the listbox selection and the clipboard.
box = tk.Listbox(root, selectmode=tk.MULTIPLE, exportselection=False)

How do I get an attribute from a Combobox and put it into a variable?

I'm making a project in Tkinter Python and I want users to select an attribute from a Combobox widget and press a button and that attribute will be stored in a variable. I've searched all over the web, but I can't make heads or tails of the code and have no idea how to store this attribute. Can someone tell me how to do this
I've tried the .get thing... (module? widget?) but that is not working and as I said, the internet ain't no help.
This is my basic code with the window and the Combobox:
from tkinter import *
from tkinter import ttk
master = Tk()
ver = ttk.Combobox(master, state="readonly", values=["test1", "test2"]).pack()
Button(master, text="Run").pack()
master.mainloop()
I want to be able to store the selected item in the Combobox and put it in a variable.
pack returns None if you want to assign to a variable, you must do it on a separate line.
If you want action, Button requires a command key word arg to which you assign a callback.
After you have fixed the mistakes, you can use the get method on the Combobox:
import tkinter as tk
from tkinter import ttk
def print_selected():
print(combo.get())
master = tk.Tk()
combo = ttk.Combobox(master, state="readonly", values=["test1", "test2"])
combo.pack()
tk.Button(master, text="Run", command=print_selected).pack()
master.mainloop()

How do I disable keyboard input into an Entry widget, disable resizing of tkinter window and hide the console window?

I am making a calculator using tkinter and I wish to do the following:
Disable keyboard input for the Entry widget so that the user can only input through the buttons.
Even after disabling keyboard input for the Entry widget, I wish to be able to change the background and foreground of the widget.
I wish to hide the console window because it is totally useless in the use of this calculator.
I don't want to let the user resize the root window. How do I disallow the resizing of the root window?
Here is my code so far...
from tkinter import *
root = Tk()
root.title("Calculator")
root.config(background="black")
operator = ""
textVar = StringVar()
def valInput(number):
global operator
operator+=str(number)
textVar.set(operator)
display = Entry(root, textvariable=textVar, font=("Arial", 14, "bold"), bg="lightblue", fg="black", justify="right")
display.grid(row=0, column=0, columnspan=4)
btn7 = Button(root, font=("Arial", 12, "bold"), bg="orange", fg="red", text="7", command= lambda : valInput(7))
btn7.grid(row=1, column=0)
"""
And more buttons...
"""
root.mainloop()
As you can see, I can input into the Entry widget using buttons but later on, after the calculator is complete, if the user inputs characters like abcd... it will cause problems and show errors. How do I disallow keyboard entry so that I can avoid these errors?
I want to make my calculator a bit colorful. I changed the color of the root window, the buttons and also the color of the Entry widget. Is there any way to change the color of the widget even after it is disabled?
I don't need the console window while using this calculator. How do I hide it?
If I resize the root window, the calculator becomes ugly, besides, resizing the window isn't necessary. So how do I prevent the user from resizing the window?
To be able to disable keyboard input in Entry(args)
Set the state to disabled:
display = Entry(root, state=DISABLED)
To be able to disable the feature of resizing the tkinter window (so that you can't drag and stretch it.
root.resizable(0,0)
To be able to make the command prompt window disappear. (I just want the tkinter window.
Rename the file with a .pyw extension (assuming you are using windows)
Don't use from tkinter import * it's really not recommended because it pollutes the main namespace with every public name in the module. At best this makes code less explicit, at worst, it can (and it will) cause name collisions.
Have the right reflexes, use import tkinter or import tkinter as tk instead
this should work, you have to use the disabledbackground option :
import tkinter as tk
root = tk.Tk()
display = tk.Entry(root,font=('Arial', 20, 'bold'), disabledbackground='lightblue', state='disabled')
display.pack()
root.resizable(0,0)
root.mainloop()

Is there a tkinter equivalent for Perl/Tk's Scrolled pseudo-widget?

Perl/Tk has a pseudo-widget Tk::Scrolled that takes as its argument another widget and adds a corresponding scrollbar according to options (where to put it in relation to the widget and if to show at all if there is nothing to scroll). For example, to have a listbox with a scrollbar to the right that disappears if the listbox can display all entries you just have to say:
my $Listbox = $MW->Scrolled ('Listbox', -scrollbars => 'oe');
Has tkinter (3.3.2) some equivalent functionality?
Tkinter has a Scrollbar class that can be used to wrap widgets in a scrollbar. It may not be as concise to configure as perl, but you can set it up to do what you are asking for without too much hassle.
Here are some examples of the scrollbar in use:
from Tkinter import *
root = Tk()
scrollbar = Scrollbar(root)
scrollbar.pack(side=RIGHT, fill=Y)
listbox = Listbox(root)
listbox.pack()
for i in range(100):
listbox.insert(END, i)
# attach listbox to scrollbar
listbox.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=listbox.yview)
mainloop()

Categories