Is there a bug in the natural scrollbar trough click event handler, is something wrong with the way I set it up, or something else? I ask because it doesn't always work (when it doesn't work, it either does nothing or else moves to the wrong position). The scrollbars otherwise work fine. Sometimes the trough clicks do work, but a lot of the time they don't. (More than one or two clicks is often needed to discover the problem.)
hbar=Scrollbar(newTabFrame, orient=HORIZONTAL, bg=self.d["hbgcolor"], troughcolor=self.d["htcolor"]);
vbar=Scrollbar(newTabFrame, orient=VERTICAL, bg=self.d["vbgcolor"], troughcolor=self.d["vtcolor"]);
scroll=Text(self, newTabFrame, font=self.d["font"], undo=True, tabs=("0.4c"), wrap=self.d["wrap"], xscrollcommand=hbar.set, yscrollcommand=vbar.set, bg=self.d["bgcolor"], fg=self.d["fgcolor"], insertbackground=self.d["insertcolor"]);
vbar.grid(row=1, column=2, columnspan=2, rowspan=4, sticky=N+S);
vbar.config(command=scroll.yview);
hbar.grid(sticky=E+W);
hbar.config(command=scroll.xview);
Once again, it's only when I click on the troughs where I experience a problem. All the other scrollbar functionality (which is most of it) works fine. For those who don't know, a scrollbar trough is the long part of the scrollbar that does not move.
My scrollbars are attached to Text widgets inside Frames that are inside of ttk.Notebook widget tabs.
To directly answer your question, no, there is no known bug in the scrollbar code. This code has been in use for more than a decade without anyone reporting issues with the trough. That doesn't mean a bug isn't possible, but it is highly unlikely. There also doesn't appear to be any problems with how you defined the scrollbar or how you attached it to the text widget. .
Based on comments to the original question, it sounds like you have some bindings in your app that may be interfering with the default behavior of the scrollbar.
Related
GUI noob here. I've created a simple screen overlay where the user can click-drag to create a transparent rectangle.
Think 'cropping an image'.
That part was easy enough. The problem is that I want to reset the overlay if/when the user attempts to click-drag inside the transparent rectangle, thereby starting a new rectangle.
Illustrative example code:
import tkinter as tk
def fail_click(evt):
print(evt.x)
root = tk.Tk()
root.attributes('-topmost', True)
root.attributes('-transparentcolor', 'grey')
canvas = tk.Canvas(root, width=300, height=300, bg='grey')
canvas.bind('<Button-1>', fail_click)
canvas.pack()
root.mainloop()
What I expected:
An invisible canvas upon which I could draw.
What I got:
An empty frame I could reach through to grab whatever is on the other side. This surprised me because I was unaware that 'transparent' == 'not there'. While I can imagine cool things to do with this newfound knowledge, in this case, it's the opposite of what I want.
The question(s):
Is this the intended behavior for GUI windows in general or is this a quirk of Tkinter? In other words, could I solve this problem simply by using a different toolkit, e.g., wxPython or pyQt?
Assuming this is the intended behavior, is there a workaround for getting my invisible canvas to register mouse events. e.g., capturing the click event and redirecting it to where it belongs (the canvas)? It doesn't need to be trivial, I just need a signpost pointing me in the right direction.
Notes:
I haven't put a lot of effort into this as it's just a silly side project I'm working on. I just decided to ask the question before I waste time I don't have trying a hundred different things, like learning how to use a new toolkit. And, who knows, maybe it'll help save someone else some time.
I've glanced over the code from this answer - https://stackoverflow.com/a/42880450/3602761 - but that's just capturing click events. I need the whole caboodle: Motion, Button-1, B1-Motion, ButtonRelease-1, etc.
I'm only using Python and Tkinter here because Python is the language I'm most familiar with and Tkinter is built-in. Feel free to offer suggestions straying from this implementation decision.
If you want partially transparent write the number as you wish instead of 0 in alpha
import tkinter as tk
def fail_click(evt):
print(evt.x)
root = tk.Tk()
root.attributes('-topmost', True)
root.attributes('-alpha', 0)
canvas = tk.Canvas(root, width=300, height=300, bg='grey')
canvas.bind('<Button-1>', fail_click)
canvas.pack()
root.mainloop()
The title basically says it. Right now I have the two panedWindows attached to the root window. I would like the windows to either lift() or lower() one panedWindow on top of the other when a button is pressed rather than the panedWindows being stacked on top of each other in the same window.
I also understand there may be a better way of implementing this sort of menu feature. If you know a better way, that would be great too.
I used .grid(row = 0) on both panedWindows. Then I called lift on the window I wanted to raise up and it worked.
I'm working on a basic PIN interface for a touch screen with Python 2.7 Tkinter and ttk. I'm developing the script on Windows but it will eventually be loaded on a Linux OS.
I am trying to prevent what is shown on the "6" button of the picture bellow, i.e. a dashed border around the button lastly clicked. Since I don't want people to easily steal the PIN from my users, I have to prevent this from happening, otherwise it becomes really easy to find out what their PIN are just by looking at the screen. I have noticed that this behavior becomes even more obvious on LINUX with something like a thick white border around the button.
I am calling my buttons inside a loop like this:
ttk.Style().configure('TButton', padding=11, relief="flat", background="#ccc", foreground="#393939", width=4,font='Arial 9')
btn = ttk.Button(window, text = txt, command = lambda txt=txt:self.addChar(txt))
btn.grid(row=row, column=col, padx=1, pady=1)
The solution is pretty simple: modify your addChar function to move the focus back to some other widget after it inserts the character.
for my board game, I need to press a certain button and after that, disable it (to prevent the user or the computer to place a "peace" in the same place). The problem I have with this is basically design-wise: as you would know, when a button is disabled in tkinter, it turns grayed-out, kinda "visually blocking" the piece I placed... Here is an image of what I'm talking about:
My question is, how would I disable a button, but keep it as if it wasn't disabled? I searched and the only answer I came about was basically getting rid of the button and replacing it with an image... If that's my best bet, how would I do this? the grid is created with a for loop that fills a list with buttons, and then displays them into a frame using the grid() method. This would look like:
Is there another way to achieve this with tkinter methods? I would rather not change the buttons to an image with a bound event, that seems too complicated given that I'd have to mess with my loop. Thanks!!
Thanks!
You can control the foreground and background colors with a variety of options, such as foreground, background, disabledforeground, and highlightbackground. Have you tried setting any of those to get the visual behavior you want?
You also have the option of disabling the callback, so the button will press but it won't do anything. To disable it, simply configure the command option to be None:
the_button.configure(command=None)
Turns out in order to disable the button but keeping its appearance, you have to disable its callback to make it "unresponsive" (as stated by #Bryan Oakley and #martineau, thanks!) and also change its 'relief' as to make it stay "fixed" (it kind of shifts into the bottom right corner, but that's good enough).
Imagine you have this generic button:
button = tkinter.Button(frame, height=0, bg='blue',\
activebackground='blue',width = 0, text = " ", image = self.blank, \
command=lambda row=row_index, \
column=column_index: \
self.button_clicked(row,column))
Now when you want to disable it but keeping its original appearance, you change the following attributes of the button:
button['command'] = 0 #this disables the callback
button['relief'] = 'sunken' #makes the button fixed
As easy as that! thanks!
I'm creating a simple GUI app using Tkinter with Python, but I'm having problems adding a scrollbar to a single frame. The frame is visible from top to bottom on my 20" but in order to display everything on a netbook or any other low res screen it needs a scrollbar. Here's a snippet of how I thought it would work (it does with listboxes).
framelist = Tkinter.Frame(self.pmaster, relief=FLAT, borderwidth=0)
framelist.pack(fill=BOTH, padx=0, pady=0)
yscroll = Tkinter.Scrollbar(framelist, width=10, orient=VERTICAL)
yscroll.pack(fill=Y,side=RIGHT,padx=0,pady=0)
Though this doesn't work with frames apparently. Any help on this issue from you guys will be deeply appreciated!
I'm also wondering if Tkinter might be outdated. It was the only GUI interface I learned in school, but thats several years ago and it doesn't really meet my demands anymore. Surely there must be a better alternative? I'm on Ubuntu btw.
The frame widget of tkinter doesn't scroll. One solution is to put your whole frame in a canvas (as a canvas object), and attach the scrollbar to the canvas. You have to tell the canvas how big the scrollable area is, which you can do by getting the size of the frame once you've placed all the widgets in it. Though, you might want to reconsider your UI design -- scrollable frames aren't very easy to use no matter what GUI toolkit you use.
As for whether Tkinter is outdated... some say yes, some say no. There is a lot of tkinter misinformation out there so take all tkinter opinions with a grain of salt (even mine!). Tkinter continues to improve, it hasn't stagnated. If you have the luxury of using python 2.7 or greater you have access to the ttk widgets which offer platform-specific themes and additional widgets such as a notebook and hierarchical tree among others.
For alternatives you might want to check out wxPython. In my experience it seems to have considerably more bugs and quirks than tkinter, but has a lot more widgets and seems to be more popular.
I like to think that the difference between tkinter and wxPython is like the difference between Home Depot (a home improvement / lumbar yard store) and Ikea (prefabricated furniture that you assemble yourself) - one gives you all the bits and pieces to make just about anything you want (tkinter) the other gives you a lot of pre-packaged stuff. Each approach has its strengths and weaknesses.