I'm wondering how difficult it will be to use invoke matplotlib from a Tcl interpreter and plot to a Tk canvas created on the Tcl side.
I'm wondering what the best way to do this is.
I'm guessing I'll have to create a python interpreter, pass the canvas handle from the Tcl side to python and make use of the C API in both languages. Or is there a more elegant way?
Getting this integration right won't be easy. However, here's what I'm thinking about:
Connecting Python and Tcl
You can run Python inferior to Tcl apparently. According to this wiki page, there's a package called tclpython which can do the basic integration work for you, and the page linked to appears live. The code appears to be here, though it might need some work to make it build. (I've never tried.)
Connecting matplotlib and Tk
You can make matplotlib draw on a Tkinter window, and as long as you can make that Tkinter window with the right options, it will show up. The key is that the underlying system window IDs can be found out from Tk with winfo id $nameOfTheWindow. If you create a frame with the -container option set to true (which turns off some things and turns on a few others; you'll need to set the size explicitly) then that particular frame will be suitable for use with TkAgg on the python/matplotlib side. The key will be to make a toplevel on that side that has the -use option set to the ID retrieved from winfo id. You probably need to make sure that the python side is running its rendering in a separate thread to the outer Tcl/Tk to make the event handling work right (unless you're keen on doing deep event loop hacking; the situation is that you're actually going to have Tcl/Tk inside Python inside Tcl/Tk, as Tkinter works by delegating to a subordinate Tcl/Tk, and getting all this glued together right will be “a bit tricky”).
If that doesn't work, get matplotlib to render as an image (GIF or PNG; the latter is preferred if you've got Tk 8.6) as you can just show that easily via a photo image. This is definitely going to be possible to do without thread games; it's just passing around pure data. Probably slower and not interactive, but that might not matter for what you're doing, and it is easier in the simple case.
You will probably need the second approach if you're on Windows or OSX, as Tk there doesn't actually use X11. (Unless you're using one of the more perverse configuration options, of course.)
Related
As far as I understand, it is not possible to modify the tkinter.colorchooser.askcolor as it uses the systems colorpicker dialog. Is this true?
from the source code: https://github.com/python/cpython/blob/3.9/Lib/tkinter/colorchooser.py
# this module provides an interface to the native color dialogue
# available in Tk 4.2 and newer.
The reason being is I wish to add an entry box to the dialog so that I would get the color code and user-entered text returned. Maybe it is possible to embed the dialog within a larger window? Is something like this possible, without using multiple windows?
I cannot find previous discussion anywhere else so I guess it is not a simple issue.
As far as I understand, it is not possible to modify the tkinter.colorchooser.askcolor as it uses the systems colorpicker dialog. Is this true?
Yes, that is true. At least on Windows and OSX. On Linux it's a custom dialog written in tcl/tk. You could start with that code and then make modifications to it, then write a tkinter wrapper around it. That wouldn't be particularly difficult if you know tcl/tk, but it's not exactly trivial either.
Maybe it is possible to embed the dialog within a larger window?
No, it's not.
I'm a comp sci student studying some compiler design and I have a quick question that bugs me to no end.
I'm currently writing an Interpreter in JavaScript (run on nodeJS) that takes statements like:
x = 4
print x
Which would result in the console output:
4
I can parse these statements pretty easily and have them output stuff to the console window. But how would this process work with GUI applications?
The way I understand it is, let's take Python for example.
When you run python in the command line, it launches a console application which takes in python commands and interprets them. (I know it translates to bytecode first, but it does eventually get interpreted).
So like if it sees 1+1, I understand how it can parse this and return 2 to the console window that it is already running. Python in this case is itself is a console app, so it's intuitive that console output from user-inputted instructions can also be on the console.
I've been able to do THAT. But this ALSO works in python:
from tkinter import*
t = Tk()
How does THAT work? Does the Python Interpreter/VM somehow call a Win32 API function? Or does it draw its own window?
Thank you in advance, for any help given to clarify this.
tkinter is essentially just a Python interface to the Tk library. This is an open source library that runs on all popular operating systems and provides a consistent API for GUI elements.
I don't think Python has any built-in GUI functions, it relies on external libraries like this.
Somebody at some point long ago wrote a library that could directly access the screen and turn pixels on or off. Then, they wrote a function that takes two x,y pairs and computes all the pixels that need to be turned on to draw a line. The library would then call the function to turn pixels on or off.
Someone else then created a library that sits on top of that library, and uses it to not just draw lines, but draw boxes or circles and so on.
Someone else creates a library on top of that which can read font descriptions and turn that into text on the screen. And then someone creates a library that combines the font library and the line library to create a library that creates windows and checkbuttons. And then someone figures out how to add color, and object rotation, and 3d effects, and on and on.
Ultimate we end up with something like tkinter, which is a library that has functions for creating an input widget, which calls a tcl/tk library which converts the python to tcl, and which calls an X11 or DirectX or Win32 or Cocoa or OpenGL library which takes the input and calls some other function that ultimately turns a pixel on or off on the physical display.
When you deal with programming, A LOT of what you are able to do comes down to existing libraries and APIs. If you had to reinvent the wheel every time, you'd never get anything meaningful done.
A simpler example is your print() call. This is mearly a wrapper that writes to stdout. The bash shell / OS you're using handles what happens to stdout. GUIs are more or less the same thing, with just a slightly more complicated path.
tkinter is a python library for generating GUI interfaces. It itself, is nothing more than a wrapper for the more general, Tk library. Tk is a general purpose GUI library that works across platforms. It does this by creating utilizing code that's customized for each operating system's GUI library. It's the OS* itself that ends up creating the GUI.
*This is kind of a generalization as in some operating systems (such as those that utilize something such as Gnome) the GUI interface is more decoupled from the OS than one would often think.
I am developing a cross platform app in Python using wxPython. The app is fully developed, and the graphics toolkit is set in stone, at least for the time being.
On Windows, everything looks great. On Linux, everything looks pretty good. On Mac, I am having trouble with a combobox/choice being hidden in the toolbar, even though it shows up fine on Windows.
Here is a snapshot of my app on Linux, noting the entire "CoeffConv ..." section is part of the perfectly displayed combobox:
And here is a snapshot of the same exact codebase on Mac:
I've tried with wx.ComboBox and wx.Choice with the same effect. I've made sure to call Realize() after I've added my toolbar items. I've made sure AddControl is called to actually add the object to the toolbar. It's definitely trying to render because the spacing is exactly what I would expect, given the contents of the choice field.
In fact, if I don't call AddControl, but I create the choice field with the toolbar as the parent, the box gets rendered but things aren't arranged properly due to the missing AddControl call:
As another check, I created a super simple toolbar with choice demo, and it works just fine:
So, here's the summary of things I know:
On Windows, the choice field works perfect, indicating the code isn't necessarily wrong.
On Linux, the choice field works perfect, supporting the idea that the code is actually OK.
On Mac, the choice field is present it seems, but somehow invisible, implying this is a problem with the Mac, or the Python distribution on Mac, or the combobox control in the wxPython distribution on Mac.
On Mac, I can get the choice to render (improperly but still) without an AddControl call, indicating the combobox can render properly, but something is goofy about the placement when added to the toolbar
However, On Mac, I can get a toolbar/choice to render totally fine in a dummy example, indicating it's something about my implementation...but I can't figure out what would cause it as I'm trying to make the exact same calls to the wx objects as in the dummy example.
I can't get the dummy example to reproduce the problem, but I'll keep trying. I'm happy to report out some object properties if they would be helpful in diagnosing. If someone has a clue for what could cause it to not show up, I'd really appreciate it!
While I couldn't find the root as to why it didn't work on Mac, I did find an issue that could help others.
First a little more background. In the app, we have multiple toolbars. Because of that, we are creating toolbars using plain wx.ToolBar objects and adding them to the app frame using sizers. This is in contrast to the more standard method of using self.CreateToolBar() which only allows a frame to have a single toolbar.
When I make a single change to the code to use the more natural CreateToolBar interface, the combobox immediately shows up. When I do that, the second toolbar is messed up, but at least the initial toolbar works perfectly. I'll be investigating how to get multiple toolbars on Mac, but it's a step in the right direction.
It's been a while, but there's another solution to this for wxPython 4 if you can't use CreateToolBar():
The widgets do get added to the bar and reserve the correct amount of space, but they fail to draw properly. You can resolve this by calling control.Hide() followed by control.Show() on each widget control, which then makes them draw properly.
I'm developing a python/tkinter application, and finding the default messagebox lacked flexibility, I programmed my own using Toplevel.
I was rather successful in recreating the messabox appearance, however, I could not find a way to obtain the icons displayed in normal tkinter messagebox (i.e. : error, warning, info icons...)
I did some research didn't find much, except that those image were stored in a win32 DLL file... Also tried looking into the tkinter messagebox module code, but its only an interface transferring from python to TCL code I can't find (and probably wouldn't be able to read anyway...)
Is there anyway to get files or rough equivalents (PhotoImage objects) for these icons using either python or TCL executed though Tk().tk.call()?
Or any other (thourghly explained then) way to achieve this?
Right now the best solution I can think of is to use screencapture, and save the icons to files, but I'd rather be able to access the original ones...
Thanks in advance !
The rough equivalents are available as (tk global variables):
::tk::icons::warning
::tk::icons::error
::tk::icons::information
::tk::icons::question
Like anything that is not documented, it is subject to change in the future, but these should be stable.
Is there any way I can create a UAC-like environment in Python? I want to basically lock the workstation without actually using the Windows lock screen. The user should not be able to do anything except, say, type a password to unlock the workstation.
You cannot do this without cooperation with operating system. Whatever you do, Ctrl-Alt-Del will allow the user to circumvent your lock.
The API call you're looking for Win32-wise is a combination of CreateDesktop and SetThreadDesktop.
In terms of the internals of Vista+ desktops, MSDN covers this, as does this blog post. This'll give you the requisite background to know what you're doing.
In terms of making it look like the UAC dialog - well, consent.exe actually takes a screenshot of the desktop and copies it to the background of the new desktop; otherwise, the desktop will be empty.
As the other answerer has pointed out - Ctrl+Alt+Delete will still work. There's no way around that - at least, not without replacing the keyboard driver, anyway.
As to how to do this in Python - it looks like pywin32 implements SetThreadDesktop etc. I'm not sure how compatible it is with Win32; if you find it doesn't work as you need, then you might need a python extension to do it. They're not nearly as hard to write as they sound.
You might be able to get the effect you desire using a GUI toolkit that draws a window that covers the entire screen, then do a global grab of the keyboard events. I'm not sure if it will catch something like ctrl-alt-del on windows, however.
For example, with Tkinter you can create a main window, then call the overrideredirect method to turn off all window decorations (the standard window titlebar and window borders, assuming your window manager has such things). You can query the size of the monitor, then set this window to that size. I'm not sure if this will let you overlay the OSX menubar, though. Finally, you can do a grab which will force all input to a specific window.
How effective this is depends on just how "locked out" you want the user to be. On a *nix/X11 system you can pretty much completely lock them out (so make sure you can remotely log in while testing, or you may have to forcibly reboot if your code has a bug). On windows or OSX the effectiveness might be a little less.
I would try with pygame, because it can lock mouse to itself and thus keep all input to itself, but i wouldn't call this secure without much testing, ctr-alt-del probably escape it, can't try on windows right now.
(not very different of Bryan Oakley's answer, except with pygame)