How can I resize terminal window from Python? - python

I'm trying so hard and pushing myself to my limits, but I just can't figure out how to resize a terminal to my desire. Is there any way that someone can help me solve it? I would like the terminal to be solved with its unique code in different operating systems or you could just try to solve it in one or more lines of code.
#!usr/bin/python
# -*- coding: utf-8 -*-
### Requirements for default python
from __future__ import absolute_import
from __future__ import print_function
from __future__ import generators
### Available for all python sources
from sys import platform
from os import system
class MainModule(object):
def __init__(self, terminal_name, terminal_x, terminal_y):
self.terminal_name = terminal_name
self.terminal_x = terminal_x
self.terminal_y = terminal_y
if platform == "linux" or platform == "linux2":
# Code to resize a terminal for linux distros only
if platform == "win32" or platform == "win64":
# Code to resize a terminal for windows only
if platform == "darwin":
# Code to resize a terminal for mac only

As you seem to have discovered, the implementation is platform-specific. You'll have to write code to do this for each platform.
On Windows, there are Windows APIs that can be used to do this. You can leverage Windows APIs directly using the ctypes module. One example of this can be seen in the PyGetWindow package. Other tools like AutoHotkey (via ahk Python package), and PyWinAuto are alternative tools to do this for Windows.
# example using the AHK package on Windows
from ahk import AHK
ahk = AHK()
win = ahk.find_window(title=b'Untitled - Notepad')
win.move(x=200, y=300, width=500, height=800)
On MacOS, you can write an apple script to resize the window and launch osascript from a subprocess.
# Using applescript on MacOS
import subprocess
APPLICATION_NAME = "Safari"
X = 300
Y = 30
WIDTH = 1200
HEIGHT = 900
APPLESCRIPT = f"""\
tell application "{APPLICATION_NAME}"
set bounds of front window to {X}, {Y}, {WIDTH}, {HEIGHT}
end tell
"""
subprocess.run(['osascript', '-e', APPLESCRIPT], capture_output=True)
For Linux, as Jeff mentions in the comments, the Linux implementation will depend on the window manager used of which there are many. But for popular platforms like Ubuntu, you may rely on existing tools like the wmctrl package or similar packages.
# ref: https://askubuntu.com/a/94866
import subprocess
WINDOW_TITLE = "Terminal" # or substring of the window you want to resize
x = 0
y = 0
width = 100
height = 100
subprocess.run(["wmctrl", "-r", WINDOW_TITLE, "-e", f"0,{x},{y},{width},{height}"])
Though, if you are writing a game or similar, you can get around this a different way. For example, pygame lets you set your window size or in text-based terminal applications, curses (or a popular wrapper for curses, blessings) can be used to detect terminal size and you can resize your application dynamically, which may take some changing of your current code to do.
height = curses.LINES
width = curses.COLS
redraw(width, height) # you implement this to change how your app writes to the terminal

Related

Pyautogui in specific screen app in 2 monitors

Well, let's separate this doubt into parts.
First question, how can I make pyautogui.locateOnScreen() in a specific app window on windows? Example, search for an image only in the windows calculator?
The second question is I have 2 monitors, how do I search for an image on a specific monitor?
I make a simple code, but not working because my calculator is opened on my second monitor.
def main():
try:
while True:
button7location = pyautogui.locateOnScreen('images/calc7Key.png', region=(0,0,1920, 1080), confidence=.5)
print(button7location)
except KeyboardInterrupt:
print('\nDone.')
main()
Unfortunately pyautogui currently doesn't work with multiple monitors, you can find it in their FAQ
Q: Does PyAutoGUI work on multi-monitor setups.
A: No, right now PyAutoGUI only handles the primary monitor.
As of searching specific area you can use optional region=(startXValue,startYValue,width,height) parameter as shown here.
this answer may be late but for those looking, the answer is here :
https://github.com/asweigart/pyautogui/issues/321
quote - Resolve for me
If still relevant for someone on windows:
In my opinion the issue is, that the current version of pyscreeze
utilizing >ImageGrab (Pillow) on windows only uses single-screen grab.
A dirty quick fix in pyscreeze could be:
enable all_screen grabbing:
In file: pyscreeze/__init__.py, function: def _screenshot_win32(imageFilename=None, region=None):
change im = ImageGrab.grab() to im = ImageGrab.grab(all_screens= True)
handle new introduced negative coordinates due to multiple monitor:
In file: pyscreeze/__init__.py, function: def locateOnScreen(image, minSearchTime=0, **kwargs): behind retVal = locate(image, screenshotIm, **kwargs) >add
if retVal and sys.platform == 'win32':
# get the lowest x and y coordinate of the monitor setup
monitors = win32api.EnumDisplayMonitors()
x_min = min([mon[2][0] for mon in monitors])
y_min = min([mon[2][1] for mon in monitors])
# add negative offset due to multi monitor
retVal = Box(left=retVal[0] + x_min, top=retVal[1] + y_min, width=retVal[2],height=retVal[3])
don't forget to add the import win32api
In file: pyscreeze/__init__.py:
if sys.platform == 'win32': # TODO - Pillow now supports ImageGrab on macOS.
import win32api # used for multi-monitor fix
from PIL import ImageGrab

Python interpreter, Pygtk and GtkGrid

i've to use GtkGrid because i need to draw a rectangle for every item i have.
(i would add a Drawing area to every GtkGrid's cell and draw the rectangle by cairographics library)
But there was a problem: python 2.7 doesn't support GtkGrid, so i surfed the web and i simply changed the first line of my file (and installed python3.3).
#!/usr/bin/python3.3
try:
import pygtk
pygtk.require("2.0")
except:
print("PyGtk Not Availible")
sys.exit(1)
try:
import gtk
import gtk.glade
except:
print("GTK Not Availible")
sys.exit(1)
Now it cannot rescue anymore Pygtk or GTK libraries.. and with python2.7 all work fine..
Maybe the best solution would be to avoid newer python interpreters and change GtkGrid into something else..
Help me please
EDIT::
Just cut and pasted an example from Pygtk examples
#!/usr/bin/python3.3
# example drawingarea.py
import pygtk
pygtk.require('2.0')
import gtk
import operator
import time
import string
class DrawingAreaExample:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.set_title("Drawing Area Example")
window.connect("destroy", lambda w: gtk.main_quit())
self.area = gtk.DrawingArea()
self.area.set_size_request(400, 300)
self.pangolayout = self.area.create_pango_layout("")
self.sw = gtk.ScrolledWindow()
...
With Python 2.7 it works, with Python 3.3: No module named 'pygtk'
Just to make this clear: You have to decide wether you want to use the gi.introspection bindings (which are up to date and mostly autogenerated) or the pygtk wrapper around gtk+-2.0 (hand crafted, as of now pygtk3 is still work in progress, correct me if I am wrong).
Mixing these will get you in trouble further or later.
Also your initial issue was, GtkGrid (part of gtk+-3.0) was part of the gi.introspection bindings which (usually) require Python 3.x.y, whereas you used pygtk2 with Python 2.7.x. Changing to Python 3.3 just made the bindings availiable to you.
In gtk2 GtkGrid was called GtkTable, see https://developer.gnome.org/gtk2/stable/GtkTable.html.
Try this:
#!/usr/bin/env python
# -*- coding: utf-8; -*-
from gi.repository import Gtk
grid = Gtk.Grid()
You need to use GTK+ 3, not python3.3 (in order to have a Gtk.Grid)... if i understand what you mean...
Edited.

Resizing the curses terminal doesn't resize the program window

I'm on Windows, where the curses module is not native, so I am using the Windows curses module for python 3.2, found here.
My goal is to resize the terminal, which is currently at a small 25 lines x 80 columns size. First I tried the curses.resizeterm(lines, cols) command, which is apparently not found in the windows curses module (and hasattr(curses, 'resizeterm') returned false). So I look at the alternative module unicurses, which is also for windows, but that doesn't even have a resize command.
So I do more reading and learn about the environment variables 'LINES' and 'COLS' which, when set by os.environ, should resize the terminal. And they do, kind of. The terminal itself gets resized, but the Windows program displaying the terminal is still the same size as before, 25 x 80. I have confirmed that the two variables have indeed been changed, writing a little thing to display them in the top left corner. In addition, the box() function does draw a border around the screen as if it the variables were changed.
So, can anyone explain either 1) how to resize the "Windows window" to match the terminal or 2) how to get resizeterm() to work on my python installation? The relevant code of my program and a picture of how it looks are attached below.
import random, sys, math, curses, os
from curses import *
curses.use_env(True)
os.environ['LINES'] = "80"
os.environ['COLS'] = "60"
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
curses.start_color()
stdscr.keypad(1)
curses.curs_set(0)
LINES, COLS = stdscr.getmaxyx()
This code might help:
import curses
screen = curses.initscr()
# Check if screen was re-sized (True or False)
resize = curses.is_term_resized(y, x)
# Action in loop if resize is True:
if resize is True:
y, x = screen.getmaxyx()
screen.clear()
curses.resizeterm(y, x)
screen.refresh()

Python appscript OSAX display_dialog: how to move it to foreground

I am playing around with the example from here; esp. I have this code:
from osax import *
sa = OSAX()
print sa.display_dialog("Python says hello!",
buttons=["Hi!", "Howdy!", "Duuuude!"],
default_button=3)
The dialog always opens in the background. How can I open it in (or move it to) the foreground?
Add an activate command to give your Python process the window manager application focus.
sa = OSAX()
sa.activate()
print sa.display_dialog(...)
You can also choose to not GUIfy your Python process by targeting a faceless background app as described here.
This works for now:
def go_foreground():
from AppKit import NSApp, NSApplication
NSApplication.sharedApplication()
NSApp().activateIgnoringOtherApps_(True)
go_foreground()

How to embed some application window in my application using any Python GUI framework

I want some application to look like widget inside my Python application.
That's all. I dont need any interaction between them. I'm interested in solutions in any GUI toolkit for both windows and x windows.
It would be nice to have a solution with Tkinter but it's not crucial.
Using GTK on X windows (i.e. Linux, FreeBSD, Solaris), you can use the XEMBED protocol to embed widgets using gtk.Socket. Unfortunately, the application that you're launching has to explicitly support it so that you can tell it to embed itself. Some applications don't support this. Notably, I can't find a way to do it with Firefox.
Nonetheless, here's a sample program that will run either an X terminal or an Emacs session inside a GTK window:
import os
import gtk
from gtk import Socket, Button, Window, VBox, HBox
w = Window()
e = Button("Emacs")
x = Button("XTerm")
s = Socket()
v = VBox()
h = HBox()
w.add(v)
v.add(s)
h.add(e)
h.add(x)
v.pack_start(h, expand=False)
def runemacs(btn):
x.set_sensitive(False); e.set_sensitive(False)
os.spawnlp(os.P_NOWAIT, "emacs",
"emacs", "--parent-id", str(s.get_id()))
def runxterm(btn):
x.set_sensitive(False); e.set_sensitive(False)
os.spawnlp(os.P_NOWAIT, "xterm",
"xterm", "-into", str(s.get_id()))
e.connect('clicked', runemacs)
x.connect('clicked', runxterm)
w.show_all()
gtk.main()
Not enough reputation to comment on Glyphs answer. To make xterm work, in addition to the comments above one needs to also add
XTerm*allowSendEvents: True
to ~/.Xresources. (and perhaps reload those, with xrdb -load ~/.Xresources)

Categories

Resources