What would these GUI elements represent in MVC terms? - python

I have a Listbox in tkinter in this Listbox. We can choose an image, all images are in a array in the model, but I don't known if the Listbox corresponds to MVC "View" or a "Controller", and if it's a Controller, how to add an image that we have just imported to it in accordance with MVC.

The Listboxor any other widget in tkinter is both part of the view and part of the controller, in the sense that it is a view (obviously) but it is also acting as a controller when you register callbacks in your code, and the widget catches relevant user interactions (events) and directs them to the registered code (with the help of tkinter event mainloop).
What you can do if you like, is to put your business code in a separated module (your model), make your tkinter registered callbacks call the functions in the model, and if the model changes because of that, update the widgets (the view) by notification, using the observer pattern (see a Python example) here. Essentially you keep a list of observers in the model, and when the model changes you'll call an update() or notify() method of them.
That will require you more work, which is a drawback in many cases, but has the power of updating your UI automatically anytime a change in the model affects some widget.
Note that I am not recommending all that work for simple cases (like using a few controls), unless you have good reasons for it. Wanting to use MVC looks like a desire to really separate concerns, but evaluate the effort first...

Related

Background process and tkinter

Looking for help on where to start with this, not too good with Python. What I trying to do is use tkinter for a gui interface but i need to be able to process recieved data and update labels widgets as information changes. I all ready have the communication portion of my program working fine in the shell but when I try to tie it to tkinter it will stop processing as soon as the interface is generated. Anyone have a simple code for me to modify to my needs or point me to a reference example somewhere. Spent days so far trying different options and I still have yet to find something that works.
Thanks for any help
Convert your working program into functions that you can register as callbacks in the tkinter UI (say buttons, or other widgets), that is, make it event-driven, and then, for background processing register some of the functions with the after widget method. The root.mainloop() will never return (only on UI close), use it as the last instruction.
So you can't just write your logic in a top-down structure, and hope that it will work well with the UI. The mainloop will be permanently looping, and will call specific funtions in your code, as appropriate to the received events from the user, or to callbacks you registered to run after some time with after.
See here for the after part
Take a look here for structuring tkinter programs. It should have enough info and links for you to study and learn how to do it in a right way.

tkinter Model-View-Controller: deeply-nested widgets calling the controller

I'm refactoring a tkinter GUI along a MVC design pattern. The Controller module imports a View class, and the View class makes requests to the Controller. I have a few ways of registering a change to an entry widget (StringVar trace, binding, etc.), but what if the widget is deeply nested and the callback is at a much higher level? What is the best way to have a request propagate upwards? For example, what if the View has a Frame that has a Frame that has a Widget that changes status?
The two solutions that occur to me are:
Russian Doll approach: Every inner layer is instantiated with either a reference to the View or the Controller, so the widget can directly make a request (e.g. to ViewReference.call_controller(input), or ControllerAlias.request(input). This leaves a trail of breadcrumbs from View to widget.
Family Tree approach: recursively call the parents and ask if they have an "ask controller to do thing" method. If not, ask their parents. This seems more fragile and awkward.

GUI: Vertical list of arbitrary elements with TkInter

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

On-value-change type of event for widgets or use .trace_variable() technique?

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?

How to control a frame from another frame?

I'm writing a small app which has 2 separate frames.
The first frame is like a video player controller. It has Play/Stop/Pause buttons etc. It's named controller.py.
The second frame contains OpenGL rendering and many things inside it, but everything is wrapped inside a Frame() class as the above. It's named model.py.
I'm up to the final part where I have to "join" these two together.
Does anyone know how to control a frame (model.py) from another frame (controller.py)?
I would like to do something like a movie player when you clicks play it pops up a new window and play until the stop button is clicked.
If you know how, please let me know. (Just tell me in general no need to specific).
Theres not much too it, you create an instance of your model class in your controller and call its methods. So for example when you click the models stop button its handler calls the appropriate method of your model class to stop playback.
If you would like your frames to be decoupled somewhat, you could use pubsub, and simply setup some listeners in your model for messages from your controller.
Here's a tutorial I just found on communciating between two frames using pubsub, it's not exactly what you want to do, but it should be enough to get you started in the right direction if you decide to use pubsub.
I'd definitely use PubSub as it's probably the cleanest way I can think of to do it. You can also do it with wx.PostEvent or use a modal frame.

Categories

Resources