I want to make a whole column of various widgets scrollable in a Tkinter GUI, like so:
Tkinter can only attach scrollbars to certain widgets, of which, frames are not included. Making a scollable column is a common practice in interfaces, and there should be a simple solution, but so far, all I have been able to find is this hacky example of a scrollable frame, using a canvas widget. A similar hacky solution was used in a similar stack overflow question.
Is there a commonly accepted way in Tkinter to make a column, or a group of widgets, that is scrollable?
The solution using the canvas is the commonly accepted way to solve this problem. It's really not all that hacky, and the end result can be indistinguishable from having a native scrolling container widget.
If you're making a single column, another option is to use a text widget, and use the widget's ability to embed other widgets. Insert a widget, then insert a newline, insert another widget, etc. You then get the scrolling ability for free. The only thing you need to worry about is configuring the width of the embedded windows, which isn't too hard to do.
Related
Suppose one were to want to build a spread-sheet in tkinter. So one could have (many) cells, most of which would take text entry, but some could be drop-down lists (tkinter comboboxes) etc.
Is that feasible in tkinter for a spreadsheet of any size? (Say 100x10)? Or would that many tkinter Text object and comboboxes etc just be too much handle performance wise? (Or is there some other way to do this other than just gridding many tkinter objects?)
I ask not because I want to do this literally, but because I need to build an app in which users are presented with lots of chunks of information, any of them editable. It's convenient for the user to access those chunks directly (click on the cell) rather than have to pass through some preliminary interface.
I think the best way to know is to try. I used the code below to create a 100x10 grid of Entry widgets and tkinter did not seem slow once all widgets were created. But it will depend on the performances of the computer.
import tkinter as tk
root = tk.Tk()
for i in range(100):
for j in range(10):
tk.Entry(root)).grid(row=i, column=j)
root.mainloop()
I'm working on a X-plotter like widget that plots incomming data live.
I already searched for an solution to realize a scrolling along the x-axis if the widget has to much values and so they don't fit.
I had the folling approaches to realize it:
derive from a widget that supports scrolling and child widgets and add my own widget while making it bigger and bigger during the live updates: -> Which parent do I need to use and how do I avoid to draw all the stuff that is currently not visible?
modify my widget in a way that it supports the scrollbars itself -> but how?
draw/handle my own scrollbars -> worstcase :(
I really searched the web for suggestions or examples, but there is nothing about how to "construct" custom controls in a good way (beyond drawing something) esp. in the case of interaction...
Sorry but I'm a newbie at GTK in general :/
Most widgets in Gtk do not have scrollbars.
If you want to scroll the entire widget, you have to implement the GtkScrollable interface. Then, you add the widget to a GtkScrolledWindow. The scrolled window has the scrollbars, those GtkScrollbars are linked with GtkAdjustments which are passed to your custom widget through the GtkScrollable interface set_vadjustment and set_hadjustment.
If you just want to add a scrollbar and control its behaviour yourself, then you need to somehow add a GtkScrollbar in your widget, which means you will need to make it a container too.
The GtkScrollable approach is the following, first you implement vadjustment and hadjustment setters and getters, then when the GtkAdjustments are set, you set its lower and upper limits and the page size(how much of the widget is visible at once). After that, you connect their value-changed signal so you can refresh your widget when the scrollbars are dragged. A GtkScrollable doesn't get to check the scrollbars, only the adjustments that will be bound to the scrollbars. When drawing the widget you get the adjustments' value property in order to determine how much the scrollbars have shifted in the horizontal and vertical axes.
How can I auto scroll for the scroll area? For example, when there is a new update instead of the view of the scroll area staying the same, I want to go down with the new text. Think of it as in a CMD console, when you type a command it autoscroll with the output.
I was just going to respond to the other answer, but I just didn't know the best way to phrase it in the space allotted.
QScrollArea's are very useful widgets to use when designing custom PyQt widgets - I use them often. Things like rollout widgets, card widgets, anything where you could be displaying multiple sub-widgets with the need for scrolling can be a very useful utility. I don't agree with the idea that a QScrollArea isn't much use on its own.
The QTextEdit answer solves the problem the developer was facing - but only because it so happens the question is really about that. If you're trying to scroll a text edit, go with that answer.
However, if you are searching for an answer to the actual question and come across this thread, then the way to scroll down a QScrollArea is by actually modifying the scrollbar's value.
area = QScrollArea(parent)
vbar = area.verticalScrollBar()
vbar.setValue(vbar.maximum())
If you want to scroll to particular areas or anything (like implementing the ensureCursorVisible) then you want to take the location on the area's widget that you want to scroll to, figure out the percentage of the height of it, and apply that value to the vertical scrollbar. (Pseudocode)
Use QTextEdit.moveCursor to set the location you want to scroll to, and then use QTextEdit.ensureCursorVisible to scroll to it:
textedit.moveCursor(QtGui.QTextCursor.End)
textedit.ensureCursorVisible()
I want to provide a listbox where the user can select (multiple) characters (usually close to 15). Quite often some of these will be sequenced, so a listbox is easier than a validated text entry field.
Since the character combination has a meaning to the user, it is user friendly to orient the listbox horizontally.
Is there an easy way e.g. a theme, setting or subclass of the Tkinter listbox so I do not have to build my own?
No, there is no setting, subclass or theme that will let you do that with a listbox.
What you might want to use instead is a set of check buttons with the indicator turned off so they each appear as a button with a single letter. You can then pack them all horizontally in a frame. With the indicator off, the button will appear sunken when selected, or normal otherwise.
I'm working on a project using Tkinter and Python. In order to have native theming and to take advantage of the new widgets I'm using ttk in Python 2.6. My problem is how to allow the user to scroll through the tabs in the notebook widget (a la firefox). Plus, I need a part in the right edge of the tabs for a close button. The frame for the active tab would need to fill the available horizontal space (including under the scroll arrows).
I thought I could do this using the Place geometry manager, but I was wondering if there was a better way? The ttk python docs don't have any methods to deal with this that I could see.
Edit: looks like there are difficulties for even trying to implement this using place. For one, I'd still need the tabs to scroll and the active panel to stay in the one place.
The notebook widget doesn't do scrolling of tabs (or multiple layers of them either) because the developer doesn't believe that they make for a good GUI. I can see his point; such GUIs tend to suck. The best workaround I've seen is to have a panel on the side that allows the selection of which pane to display. You can then apply tricks to that panel to manage the amount of information there (e.g., by making it a treeview widget and holding the info hierarchically, much like most email clients handle mail folders; treeview widgets are scrollable).
I've never used these widgets so I have no idea how possible this is, but what I would try is something akin to the grid_remove() method. If you can move the tabs to an invisible widget, or just make them invisible without losing content, that's what I'd look for/try.