How can the size of the tk embedded xterm be dynamic?

两盒软妹~` 提交于 2020-03-01 01:48:08

问题


One can write a simple python script to embed an xterm into a tk frame:

from Tkinter import *
import subprocess

root = Tk()
termf = Frame(root, height=800, width=1000)

termf.pack(fill=BOTH, expand=YES)
wid = termf.winfo_id()

After the window is established

proc = subprocess.Popen('xterm -into %d -sb ' % wid,shell=True)
root.mainloop()

On my computer it looks like How can I make the embedded xterm be dynamically sized to the size of the termf frame even when resizing the frame(by dragging the corner)?

Response to answer by @tinmarino


回答1:


As was pointed out in the comments above you can use .bind() on the Tk() window in order to get a call back every time the window is configured.

from tkinter import *

root = Tk()

def callback(event):
    print(event.width, event.height)

root.bind("<Configure>", callback)

root.mainloop()

I don't have the ability to test how you can use this to resize the xterm window on Windows 10. So I'll leave this answer here for anyone who wants to edit it or use this answer to build their own.




回答2:


Implementation of @EthanField solution. 3 functions:

  1. main create gui, xterm and plug the pipes
  2. on_resize is called when the frame containing the terminal is resized
  3. get_xterm_pts is parsing the output for the pts to feed stdin to xterm
import tkinter as tk
import subprocess as sp
from re import match
from threading import Thread
from queue import Queue


def main():
    # Init
    root = tk.Tk()
    queue = Queue()

    # Pack main frame
    termf = tk.Frame(root, width=800, height=800)
    termf.pack(fill=tk.BOTH, expand=tk.YES, padx=0, pady=0)
    wid = termf.winfo_id()

    # Allow window resize
    sp.Popen("""echo '*VT100.allowWindowOps: true' | xrdb -merge""", shell=True)

    # Craft command
    cmd = (
        # Create into me
        f'xterm -into {wid} -geometry 100x50 '
        # Log to stdout
        r'-sb -l -lc -lf /dev/stdout '
        # Launch `ps` command: output, tty, = for remove header
        """-e /bin/bash -c "ps -o tt=;bash" """
        r'| tee'
    )
    print('Launching:', cmd)

    # Spawn Xterm
    process = sp.Popen(
        cmd, shell=True, stdout=sp.PIPE, stderr=sp.PIPE)
    print('Xterm pid:', process.pid)

    # Get pts
    thread = Thread(target=lambda: get_xterm_pts(termf, process, queue))
    thread.start()

    # Set resize callback
    termf.bind("<Configure>", lambda event: on_resize(event, queue))

    # Start
    root.mainloop()


def on_resize(event, queue):
    """On resize: send escape sequence to pts"""
    # Magic && Check
    magic_x, magic_y = 6.1, 13
    print('Resize (w, h):', event.width, event.height)
    if not queue.queue: return

    # Calculate
    width = int(event.width / magic_x)
    height = int(event.height / magic_y)
    print('To (lin,col):', height, width)
    ctl = f"\u001b[8;{height};{width}t"

    # Send to pts
    with open(queue.queue[0], 'w') as f:
        f.write(ctl)


def get_xterm_pts(parent, process, queue):
    """Retrieve pts(`process`) -> `queue`"""
    while True:
        out = process.stdout.readline().decode()
        print('Xterm out' + out)

        match_pts = match(r'pts/\d+', out)
        if match_pts:
            pts = '/dev/' + match_pts.group(0)
            print('-----------> pts:', pts)
            queue.put(pts)
            break

        if out == b'' and process.poll() is not None:
            break

    # Resize now
    fake_event = tk.Event()
    fake_event.width = parent.winfo_width()
    fake_event.height = parent.winfo_height()
    on_resize(fake_event, queue)


if __name__ == '__main__':
    main()

The search of the pts of the new shell in a new thread seems a lot, but we want the pts of the interactive shell and not the sh which spawn it. I actually tried pip -> pts with some Popen ps, and it was less resilient.

11844 pts/1    00:00:00 sh      <- pid returned to Popen
11847 pts/1    00:00:00 xterm   <- then ...
11848 pts/1    00:00:00 tee     <- that is how a pipe work, first plug, then spawn (apparently) (seems logical)
11854 pts/35   00:00:00 bash    <- then favorite shell is Michel 


来源:https://stackoverflow.com/questions/40351862/how-can-the-size-of-the-tk-embedded-xterm-be-dynamic

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!