27
votes

I want to embed a terminal in my main Tkinter window. I would like to have a sub window where a terminal (Bash based terminal) would run. I would like also to be able to let my program interact with the terminal, at least I would like to read the current working directory and/or set it.

I don't know if it is really impossible. I was able to do it in the past with Perl/Tk, so maybe it can be replicated here.

The code I used then was something like:

$frame3=$mw->Frame(-borderwidth=>2, -relief=>'groove', # -label=>'stuff for thought',
                             -labelBackground=>CADRAWWINCOLOR,-background=>CADRAWWINCOLOR);                 

$cv=$frame3->Canvas(-height=>$cvheight,-width=>$cvwidth,-background=>CADRAWWINCOLOR,
                             -bg => CADRAWWINCOLOR,
                             -relief => 'sunken')->pack(-expand => 1, -fill => 'both');

# this Frame is needed for including the xterm in Tk::Canvas 
my $xtermContainer = $cv->Frame(-container => 1);
my $xtid = $xtermContainer->id();
# converting the id from HEX to decimal as xterm requires a decimal Id
my ($xtId) = sprintf hex $xtid;

my $dcontitem = $cv->createWindow($xtermWidth/2,$xtermHeight/2,
                                       -window => $xtermContainer,
                                       -width => $xtermWidth,
                                       -height => $xtermHeight,
                                       -state => 'normal');

system("xterm -into $xtId -fn $fontname -geometry $geometry +sb -bg black -fg white -e ./xtermjob.pl $AAfname 5 &"); 

where $mw was the main Tk window.

Of course, I completely agree with Bryan: though I never programmed with a GUI library before, my program (rather large, a kind of wiki) is running very well, with a surprisingly low amount of code devoted to the GUI itself.

I tried translating this Perl code, but I'm stumbling on the ID problem.

The only place where I found some reference to a way to extract the ID from Tkinter is in Effbot, but when I use it, I get 'AttributeError: Frame instance has no attribute 'window_id', so there must be something wrong:

termf = Frame(root)
termf.pack(side=BOTTOM, fill=X)
id=termf.window_id()  
os.system("xterm -into %d -fn -misc-fixed-medium-r-normal--8-80-75-75-c-50-iso10646-1 -geometry 150x150+0+0 +sb -bg black -fg white -e /root/.bashrc &" % id);  
2
You can embed vte in a pygtk app, but I don't know of a similar thing in tkinter. Any particular reason you are using tkinter? - Keith
just the fact that I found it easier to learn than other widgets! - alessandro
@Keith: why do you say pygtk has more of a future? Tkinter has been around a long time and is part of the python core. I don't see it being taken out of python for a very, very long time. - Bryan Oakley
@Keith: I think you are wrong with the "only get so far" comment. I've created some very complex, successful commercial apps based of of Tk (admittedly, with tcl/tk rather than python/tkinter). The fact is, many, many applications don't need anything Tkinter doesn't provide, especially when you consider the addition of the ttk widgets in the most recent versions of Tkinter. - Bryan Oakley
@Keith: you seem to imply that this is possible with pygtk. This question (stackoverflow.com/questions/5993390/…) asks how to do that in pygtk - could you answer it so we could see how to do it in your favorite toolkit? It's a tough problem to solve and I'd like to see how you do it in that toolkit. - Bryan Oakley

2 Answers

32
votes

I am happy to say that it is in fact possible to do it, and you can do it with just a few lines of code (I don't know if it is so easy with other toolkits):

from Tkinter import *
import os

root = Tk()
termf = Frame(root, height=400, width=500)

termf.pack(fill=BOTH, expand=YES)
wid = termf.winfo_id()
os.system('xterm -into %d -geometry 40x20 -sb &' % wid)

root.mainloop()

The problem before was to use the wrong function for wid.

0
votes

Alessandro already reported five hours before what he regards as an adequate model. For those who come across this item during future searches, I'll record a few more background facts I know:

It was fortunate that Bryan was here to draw attention to the differences between window_id() and winfo_id(), and to counter the errors others made in writing about various toolkits.

It's interesting to me how stackoverflow compares to more specialized channels. In this case, the Tkinter mailing list http://mail.python.org/pipermail/tkinter-discuss/2011-September/002968.html swiftly and accurately responded to the question.

Tkinter would be an improvement on at least some of the moon-rocket software.