I am new to python and want to learn this from the basic.
I want to open two other application like notepad in a single window. I searched for any examples by using "tkinter". Any idea for implementing this using "tkinter".
PS: two tabs one in left and one in right so that one tab will be having notepad and other will have a media player (let say) and i should be able to close the single parent window for closing this child windows.
On Unix systems with X server the XEmbed protocol exists for such purpose, but it requires the child application to be specifically prepared for that (here's a related question).
On Windows this can be accomplished using the Win32 API. You have to get the handles of the parent and child windows and use the SetParent function.
Here's a proof of concept:
from tkinter import Tk
from win32gui import SetParent, FindWindow, SetWindowPos
import time
import subprocess
def attach_window(window_class, parent, x, y, width, height):
child = FindWindow(window_class, None)
SetParent(child, parent)
SetWindowPos(child, 0, x, y, width, height, 0)
def main():
root = Tk()
subprocess.Popen('C:\\Windows\\system32\\notepad.exe')
subprocess.Popen('C:\\Windows\\system32\\calc.exe')
# Give child processes enough time to launch
time.sleep(0.5)
# Get the HWND of the parent window
parent = int(root.frame(), 16)
attach_window('Notepad', parent, 0, 0, 400, 200)
attach_window('CalcFrame', parent, 0, 205, 420, 320)
root.geometry('500x500')
root.mainloop()
if __name__ == '__main__':
main()
Keep in mind that you have to install PyWin32 for this to work.
I don't think you will be able to do this easily. Notepad is using its own toolkit which, most probably, is not compatible with the one you are using.
If you want to open eg. an editor, look for a widget in the toolkit of your choice which does what you want (or nearly). Eg. if you want an editor, use the GtkTextView in GTK, or, if you want something that can do code editing, look at GtkSourceView, etc. Same goes for media applications.
The 'include' applications as part of a project works only to a certain point. You can eg, include text-mode applications in a terminal window, but graphical apps are much harder.
For what you need, you will have to use libraries like tkinter or pyqt. As you want to learn it from the basic, I would suggest you to pick a GUI library and start learning it. Eventually you will know how to get the result that you desire.
Related
I have a 3d rendering program that rotates the world around an observer based on the position the mouse is on the screen. The amount in radians that the world is rotated is defined by this line
glob.worldx=-(w.winfo_pointerxy()[0]-xy[0])/250
Where xy[0] is the x coordinate of the center of the screen
This means that the amount that the observers field of view can be rotated is limited by the distance the mouse can go. If I could get the mouse to come back to the center of the screen I could solve this problem. Any ideas?
The good news is that there is a way to do it.
The intermediate news is that it's not well documented.
The bad news is that it only works on some platforms.
The other intermediate news is that you can step outside of Tk on at least some platforms.
The way to do this in Tcl/Tk is by generating a <Motion> event with -warp 1. The documentation on this is sparse, and scattered around a few different pages (start at bind), but the details are described here. Basically, it's just this:
event generate . <Motion> -warp 1 -x 50 -y 50
So, how do you do this from Tkinter?
Well, event_generate isn't documented anywhere, and neither is the <Motion> event, or the warp parameter… but it's pretty simple to figure out if you know how Tk maps to Tkinter:
window.event_generate('<Motion>', warp=True, x=50, y=50)
And this does indeed generate an event, as you can see by binding <Motion>. Here's a simple test program:
from tkinter import *
root = Tk()
def key(event):
root.event_generate('<Motion>', warp=True, x=50, y=50)
def motion(event):
print('motion {}, {}'.format(event.x, event.y))
root.bind('<Key>', key)
root.bind('<Motion>', motion)
root.mainloop()
Run it, click the window to make sure it has focus, move the cursor around, and you'll see it print out something like this:
motion 65, 69
motion 65, 70
motion 65, 71
Then hit a key, and it'll print out this:
motion 50, 50
Which is great… except that it may not actually be able to move your cursor, in which case all this does is trick Tk into thinking the cursor moved.
From skimming various forums, it looks like:
Mac: Does not work.
You must have Tk 8.6.something or later (see issue 2926819). And you probably have 8.5.something.
But it's not hard to go right to the Cocoa API.
Windows: Usually works.
You must have Tk 8.4.something or later. I couldn't find the bug for this, but you can count on 8.4 with any official Windows binary install of Python 2.7 or 3.x+.
You also must not be running a full-screen app (which you generally aren't, with Tk).
On Vista and later, in some cases it won't work. This may have something to do with not owning the desktop session or not being a local console session, or it may have to do with needing Administrator or other privileges.
If it doesn't work, it's easy to go right to the Win32 API.
X11 (most linux, *BSD, etc.): Usually
Your window manager must not have disabled other clients from warping the pointer. Fortunately, that doesn't seem to be a common thing to do.
If you have this problem, there's no way around it.
Other platforms (iOS, Android, etc.): No idea.
For Mac, you want to generate and send an NSMouseMoved event. The easy way to do this is with pyobjc (which is built in if you're using Apple's Python; otherwise you have to install it):
app = Foundation.NSApplication.sharedApplication()
event = Foundation.NSEvent.mouseEventWithType_location_modifierFlags_timestamp_windowNumber_context_eventNumber_clickCount_pressure_(
Foundation.NSMouseMoved, (50, 50), 0, 0,
app.mainWindow().windowNumber(), None, 0, 0, 0.0)
app.sendEvent_(event)
For Windows, you want to call the SetCursorPos API, or generate and send a MOUSEEVENT. The former will not work with, e.g., DirectX games; the latter may not work with remote desktops. For this case, you probably want the former. Either way, the easiest way to do this is to install pywin32, and then it's just:
win32api.SetCursorPos((50, 50))
For anyone interested in moving the cursor to an absolute position on the screen (using #abarnert's tkinter method):
# Moves the mouse to an absolute location on the screen
def move_mouse_to(x, y):
# Create a new temporary root
temp_root = tk.Tk()
# Move it to +0+0 and remove the title bar
temp_root.overrideredirect(True)
# Make sure the window appears on the screen and handles the `overrideredirect`
temp_root.update()
# Generate the event as #abarnert did
temp_root.event_generate("<Motion>", warp=True, x=x, y=y)
# Make sure that tcl handles the event
temp_root.update()
# Destroy the root
temp_root.destroy()
This function shouldn't interfere with other tkinter windows. Please note that this function creates a new window that is refreshed twice so it might be slow and the user might notice the window created.
I've been looking into using the wx python package on Windows 7. Specifically, I would like to be able to get the image data of a existing window (i.e. not a window opened by the python program). It appears I can do this by getting the window's device context, creating a compatible device context, copying the bitmap, and then using it how I like from there. The problem is that I can't seem to find the way to get the device context (or the handle) of an existing window. I only see ways to get them from windows the python program using wx created. How might I be able to go about doing this? Thank you much!
wx may not have a way to do this.
The Windows APIs you need are pretty simple, and you can use them through win32api (or ctypes if you prefer, but that's a lot more work).
First, I don't know how you're planning to identify the window you want. If you have its class and name, you can just FindWindow (or, if it may not be a top-level window, FindWindowEx). If you want to search by something else, you will probably need to call EnumWindow (plus EnumChildWindows recursively, if you're not sure it's a top-level window).
At this point, you can just call wx.Windows.AssociateHandle to attach a wx.Window object to the HWND.
If you can't do that for whatever reason, GetDC gives you a display context for an HWND. You can then create a memory DC, or get the DC for the native window under underlying your wx window, and BitBlt from one to the other.
Just to expand on the other answer, try this code (untested, I'm not on Windows right now)...
# first use FindWindow or FindWindowEx to determine window handle
frame = wx.Frame(None)
frame.AssociateHandle(handle)
dc = wx.ClientDC(frame)
width, height = dc.GetSize()
bitmap = wx.EmptyBitmap(width, height)
mdc = wx.MemoryDC(bitmap)
mdc.Blit(0, 0, width, height, dc, 0, 0)
del mdc
bitmap.SaveFile('output.png', wx.BITMAP_TYPE_PNG)
I'm a bit confused with some gtk and gnome concepts. I'm trying to get list of non minimized windows on my gnome2 desktop, but after reading the pygtk documentation and inspecting the results, I can't understand the results.
Neither of the two snippets below appears to work.
First I tried this..
>>> gtk.gdk.window_get_toplevels()
[<gtk.gdk.Window object at 0xb74339b4 (GdkWindow at 0x8a4c170)>]
>>> gtk.gdk.window_get_toplevels()[0].get_children()
[]
then this
>>> d = gtk.gdk.DisplayManager()
>>> d.get_default_display().get_screen(0).get_root_window().get_children()
[<gtk.gdk.Window object at 0x89dcc84 (GdkWindow at 0x8a4c170)>, <gtk.gdk.Window object at 0x89dccac (GdkWindow at 0x8a4c0c0)>]
As seen in the console output, the second option returns two windows. But I haven't been able to figure out what they are. None of them has any children and I allways get those two windows regardless how many windows I have on my desktop.
Could anybody explain the hierarchy of objects of the typical gtk based desktop environment?
I can't understand why the above code doesn't work.
Please refrain from posting alternative solutions that resource to wnck, xlib, qt, etc. I'm more interested in understanding what I am doing wrong than in getting advice such us checking other libraries.
Your constraint is like saying "I want to build a CD player using only a banana. Please refrain from posting alternative solutions that resort to lasers." GTK can't do that, you're using the wrong tool for the job.
Here's an explanation of what a "window" actually means and why your code doesn't work:
First off, you need to understand the difference between a gtk.Window and a gtk.gdk.Window. A GTK window is a top level GTK widget that can contain other widgets. It is usually linked to a window on your desktop, but doesn't have to be - in GTK 3 there is an OffscreenWindow.
A GDK window, on the other hand, is platform-dependent. On an X desktop it is a thin wrapper around an X window, which is not necessarily a toplevel desktop window. On other systems it exists to abstract away the windowing system. A GDK window receives events, so some GTK non-window widgets have their own GDK windows. "Window" is really a terrible name for these objects, but it was inherited from X and it's probably not going to change.
Each GTK process only knows about its own windows. You can get a list of the toplevel GTK windows of your own application using gtk.window_list_toplevels(). Getting the children of these windows should return you the GTK widgets that they contain. However, you can't descend into the widget hierarchy of other processes' windows. For example, what if another process has a window with a child widget that is a custom widget that your process doesn't know about? What should it report as the type of that widget?
Getting a list of the toplevel GDK windows with gtk.gdk.window_get_toplevels() is basically the same as getting a list of the toplevel X windows, as far as I understand it. You have no way of knowing what kind of windows they are - they might be the Gnome Panel, or they might be Qt windows, or they might be something else altogether that doesn't correspond with a desktop window.
Libwnck (link to the overview of what it does) can get you a list of non-minimized windows, and their titles, but it won't allow you to see inside them. There's no way to do that. Libwnck uses GDK internally, so technically you could do it using GDK, but why would you bother if there's already a library that does that for you? If you really want to do it yourself, look at the libwnck source code.
The windows you get are the windows that were created within your process. To get the list of windows, you need to query the properties of the root window, like this:
import gtk.gdk
root = gtk.gdk.get_default_root_window()
for id in root.property_get('_NET_CLIENT_LIST')[2]:
w = gtk.gdk.window_foreign_new(id)
if w:
print(w.property_get('WM_NAME')[2])
Please note that GDK is a thin layer over underlying OS graphics engine (X11/Quartz/Aqua/GDI etc) and result may differ on different NIX devices.
I am trying to rebuild the functionality of the desktop's "highlight to select" feature so that I can use it in my own app. When I say "highlight to select" I mean the selection box that shows up if you click and drag on your desktop (native to all main-stream OS).
I've been working for hours trying to recreate it, and simply can't find a way. I've tried PyGTK, Xlib for python, and a couple other weird hacks. All of which have their own problems that won't allow me to move forward.
I generally don't ask for straight up example code without providing some sort of starting point, but in this project I don't even know where to start. How would you do this?
Here's the requirements:
Must draw on the root window (or a transparent layer that "appears" to be the root)
Must return the coordinates of the selection (x, y, height width)
Update: Forgot some details.
I am using Ubuntu 10.10
I have dual monitors (though, I don't think that should matter)
I don't mind downloading any extra libraries that are necessary
I don't know if this is what you're looking for, but what if you created another window in your module, and have your code show it when you release drag? You could fetch the cursor's current position, and have it draw the window there.
This should help you get the mouse position on the root window.
So, your code may look a little like this (this is untested code!) I'm only showing the relevant portions of what goes inside __ init __.
def __init__(self):
...
#Some of your code here.
...
win = gtk.Window(gtk.WINDOW_TOPLEVEL)
#Note that I am creating a popup window separately.
popwin = gtk.Window(gtk.WINDOW_POPUP)
#I am setting "decorated" to False, so it will have no titlebar or window controls.
#Be sure to compensate for this by having another means of closing it.
popwin.set_decorated(False)
def ShowPopup():
#You may need to put additional arguments in above if this is to be an event.
#For sake of example, I'm leaving this open ended.
#Get the cursor position.
rootwin = widget.get_screen().get_root_window()
curx, cury, mods = rootwin.get_pointer()
#Set the popup window position.
popwin.move(curx, cury)
popwin.show()
def HidePopup():
#This is just an example for how to hide the popup when you're done with it.
popwin.hide()
...
#More of your code here.
...
#Of course, here is the code showing your program's main window automatically.
win.show()
A very simplistic approach, but it should give the appearance of what you're wanting.
I am fairly new to Python programming, and completely new to cross-platform GUI building (only previous GUI experience is through visual basic and Java).
I've written some python code to screen-scrape data from a website, and now I want to build a GUI that will reside in the Mac OS X menubar, and in Window's task bar (i.e., the system tray).
The most useful general page on cross-plaform Python GUIs for me was this one (despite its name indication Window GUIs). And some stackoverflow questions came in useful as well (especially this one, and the accepted answer of this one about splitting up the GUI and cli code).
I think I will go for either wxPython or QT because I want the GUI to look as native as possible.
However, as I've said the fairly simple GUI will mainly live in the taskbar/menubar.
Should this influence my decision?
Here's an example for PyQt. This works for me on MacOS X; I haven't tried it on other platforms. Note that the QSystemTrayIcon class will raise exceptions if it doesn't have an icon – I grabbed the RSS feed svg from Wiki commons for my icon.svg (but you can give QIcon a PNG directly and not mess around with QtSvg).
import PyQt4
from PyQt4 import QtCore, QtGui, QtSvg
app = QtGui.QApplication([])
i = QtGui.QSystemTrayIcon()
m = QtGui.QMenu()
def quitCB():
QtGui.QApplication.quit()
def aboutToShowCB():
print 'about to show'
m.addAction('Quit', quitCB)
QtCore.QObject.connect(m, QtCore.SIGNAL('aboutToShow()'), aboutToShowCB)
i.setContextMenu(m)
svg = QtSvg.QSvgRenderer('icon.svg')
if not svg.isValid():
raise RuntimeError('bad SVG')
pm = QtGui.QPixmap(16, 16)
painter = QtGui.QPainter(pm)
svg.render(painter)
icon = QtGui.QIcon(pm)
i.setIcon(icon)
i.show()
app.exec_()
del painter, pm, svg # avoid the paint device getting
del i, icon # deleted before the painter
del app
See this related SO answer on how to accomplish Windows system tray/OS X menu bar functionality in wxPython.