Sorry if complete basic question. I'm doing my first steps with TkInter, trying to develop a GUI interface to a video library (I do have experience though with WPF/XAML, the MVVM paradigm, and to some extent with html/css).
I would like to have a horizontal list, scroll-able, of custom elements. Each element will have video data, including metadata (length, bitrate, etc.), a picture (thumbnail), and some action buttons (play, delete, mark, etc.). Ideally I also want to have dragging handle, to rearrange the order of the videos.
I'm looking, but cannot find, what should be the equivalent of element in WPF, with binding to data and templates. Is that even exist in Tk, or is it too ambitious requirement for a portable, free framework?
Even if templates don't exist in Tk, I still can manage by populating the parent control manually (e.g. similar to HTML's elements - each has many controls) - but I couldn't event find a list of arbitrary widgets.
Is two way binding exists (e.g. adding an item to the list of items, should automatically update the UI)?
Is Tk the right direction? The underlying logic is in python, so I'm looking for a python friendly solution. Iron Python with WPF would be the obvious solution, but I want to be portable, and Iron Python's current state isn't very promising, and I'm using libraries not supported by Iron Python.
The most common way to make a custom element is to subclass Frame. You can put whatever you want in that frame (image, buttons, etc), and then you can treat the whole thing as a single GUI element.
import Tkinter as tk
...
class CustomElement(tk.Frame):
def __init__(self, parent, meta, image_file, ...):
tk.Frame.__init__(self, parent)
# <create widgets for image, metadata, etc here>
You can then create a custom widget that acts as a container for these items. For example, you can use a canvas which makes it easy to line this objects up horizontally, and to which you can attach a scrollbar.
Finally, tkinter has a robust event management system that makes it possible to move things around with drag and drop. There isn't any built-in drag and drop per se, but you can create your own grab handles and custom bindings for click and release to implement it.
For an example of moving things on a canvas with the mouse, see this answer: https://stackoverflow.com/a/6789351/7432
Related
I wanted to ask if it is possible to draw a child window inside a parent window so that it will only be able to move inside the parent window and won't be able to move out of the parent window bounds.
If you mean having actual windows with title bar, menu, status bar etc. inside the parent window then the answer is:
No, Tcl/Tk and by extension Tkinter does not support this with its standard widgets.
There have been efforts in the past to implement widgets which emulate MDI as you can see on the TCL wiki, but most of them are over a decade old. You will probably have to implement it yourself or choose a different GUI toolkit if you really need to implement this kind of UI design.
If you do it yourself, you can use the Frame widget as the subwindow, and use place to put it in the containing window. Or, you can create it as an object on a canvas. You'll have to write all of the code to give the inner window borders and a title bar, and to manage moving it around, iconifying it, etc.
So i'm programming python program that uses wxPython for UI, with wx.TreeCtrl widget for selecting pictures(.png) on selected directory. I would like to add hover on treectrl item that works like tooltip, but instead of text it shows bitmap picture.
Is there something that already allows this, or would i have to create something with wxWidgets?
I am not too familiar with wxWidgets, so if i have to create something like that how hard would it be, lot of code is already using the treectrl, so it needs to be able to work same way.
So how would i have to go about doing this? And if there might be something i might be missing id be happy to know.
Take a look at the wx.lib.agw.supertooltip module. It should help you to create a tooltip-like window that displays custom rich content.
As for triggering the display of the tooltip, you can catch mouse events for the tree widget (be sure to call Skip so the tree widget can see the events too) and reset a timer each time the mouse moves. If the timer expires because the mouse hasn't been moved in that long then you can use tree.HitTest to find the item that the cursor is on and then show the appropriate image for that item.
I'd like to build a number of tkinter GUI apps and then stack them together either horizontally or vertically. I'd also like to navigate across the app easily once they become attached so that at any time I can focus on them.
One idea in my mind is that I can have a webpage like frame container, with a scrollbar, then drag other app's GUIs into it so that I can scroll across them.
To attach the windows, I understand that maybe I can get individual app's window through process info, but I just want to make sure if there is a built-in or better way of doing the things I want.
Seeing as you didn't capitalize tkinter, I'm going to assume that you are working in Python 3. If this is so, there are two options that I can think of: Using tkinter frames/grid geometry manager to place each widget side by side, and using tkinter.ttk Notebook to have multiple application tabs. you could also mess around with creating a scrollable tkinter Frame if you were dead set on the scrolling part, but from other Stackoverflow pages it appears that there is no native way to do that.
Example of tkinter.ttk Notebook
Is there an on-value-change type of event for data input widgets like Entry, Text, Spinner, Checkbutton, Radiobutton? By on-value-change, I mean the ability to detect when the value of a widget has changed due to keyboard input or cut/delete/paste (and Text edit_undo/edit_redo) activity? I see no such event described in the Tkinter event documentation [1].
Is the proper technique to link Tkinter variables to widget values I want to monitor and use these variables' .trace_variable( 'w', ... ) methods to bind to value changes? This seems like the right approach, but I haven't seen a lot of trace_variable() use in the Tkinter application source code that I've studied ... leading me to be cautious about using this approach.
[1] http://infohost.nmt.edu/tcc/help/pubs/tkinter/events.html
Different widgets call for different solutions. For example, check buttons and radio buttons have a command option, and with an entry widget you can use the built-in validation features.
For all the widgets that can be tied to a variable, doing a variable trace is a common solution. The text widget is one exception since you can't associate it with a variable without a lot of effort.
In the tcl/tk world I associate all my widgets to a single array (tcl's name for a hash map / dictionary) and then put a single trace on the array. Unfortunately tkinter doesn't directly support tcl arrays. However, support is somewhat easy to hack in. For more information see my response to this question: How to run a code whenever a Tkinter widget value changes?
I'm studying the Tkinter Listbox widget and have been unable to find solutions for the following functionality:
How can I create non-selectable horizontal separator items, eg. separators equivalent to the Tkinter Menu widget's .add_separator()? (Using chars like dashes and underscores looks awful).
How can I disable a specific item? I tried using .itemconfig( index, state='disabled' ) without success.
How can I enable keyboard navigation, eg. when a user's keyboard input automatically scrolls one forward to the closest item that begins with the text the user typed? Must I bind(<KeyPress>, ...) and manage this behavior myself?
Would some of the above functionality be easier to implement using a Text widget or the ttk.Treeview widget?
you cannot. The widget doesn't support that.
you can't disable certain items, the widget doesn't support a state attribute. That being said, you can monitor the selection and do the appropriate thing if the user selects something that is disabled, and use the item foreground to denote disabled-ness.
You will need to bind to keypress events and manage the behavior yourself. It's not particularly difficult, just a little tedious.
the text widget might be your best bet, though you'll have to add bindings to mimic the default bindings of the listbox.
Bottom line: Tkinter provides nothing that directly supports what you want to do, but the building blocks are all there. You'll just have to build it yourself.