How to embed a terminal in a Tkinter application?

Question:

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);  
Asked By: alessandro

||

Answers:

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.

Answered By: alessandro

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.

Answered By: Cameron Laird
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.