Как установить абсолютную позицию окон рисунка с помощью matplotlib? - PullRequest
33 голосов
/ 16 сентября 2011

Я пишу простое приложение на Python, которое использует matplotlib для отображения нескольких цифр на экране. Количество сгенерированных цифр зависит от пользовательского ввода и изменяется в течение всей жизни приложения. Пользователь имеет возможность выполнить команду «сюжет» для создания нового окна рисунка с выбранным рядом данных. Чтобы улучшить взаимодействие с пользователем, я хотел бы предоставить еще одну команду, которая программно упорядочит все окна с открытыми фигурами в некотором удобном порядке (например, расположит их по доступному экранному пространству).

Я считаю, что нашел API, которые позволяют мне регулировать размер окна рисунка (в пикселях), но не смогли найти способ установить их абсолютную позицию на экране. Есть ли способ сделать это, не вдаваясь в детали того, какой бэкэнд используется? Я хотел бы сделать это не зависящим от бэкэнда способом, чтобы не полагаться на детали реализации, которые могут измениться в будущем.

Ответы [ 10 ]

31 голосов
/ 13 ноября 2013

НАКОНЕЦ нашел решение для бэкэнда QT:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
mngr = plt.get_current_fig_manager()
# to put it into the upper left corner for example:
mngr.window.setGeometry(50,100,640, 545)

Если человек не знает x- и y-ширину, он может сначала прочитать их, например:

# get the QTCore PyRect object
geom = mngr.window.geometry()
x,y,dx,dy = geom.getRect()

и затем установите новую позицию с тем же размером:

mngr.window.setGeometry(newX, newY, dx, dy)

Я довольно часто искал это и, наконец, потратил 30 минут, чтобы это выяснить.Надеюсь, это кому-нибудь поможет.

13 голосов
/ 23 июня 2016

С помощью ответов на данный момент и некоторых моих собственных попыток, вот решение, которое проверяет текущий бэкэнд и использует правильный синтаксис.

import matplotlib
import matplotlib.pyplot as plt

def move_figure(f, x, y):
    """Move figure's upper left corner to pixel (x, y)"""
    backend = matplotlib.get_backend()
    if backend == 'TkAgg':
        f.canvas.manager.window.wm_geometry("+%d+%d" % (x, y))
    elif backend == 'WXAgg':
        f.canvas.manager.window.SetPosition((x, y))
    else:
        # This works for QT and GTK
        # You can also use window.setGeometry
        f.canvas.manager.window.move(x, y)

f, ax = plt.subplots()
move_figure(f, 500, 500)
plt.show()
12 голосов
/ 17 сентября 2011

не то, чтобы я знал, что это не зависит от бэкэнда, но определенно возможно сделать это для некоторых распространенных бэкэндов, например, WX, tkagg и т. Д.в разделе комментариев ниже вы можете вместо этого переключиться на

thismanager.window.wm_geometry("+500+0")

.Для TkAgg просто измените его на

thismanager.window.wm_geometry("+500+0")

Так что я думаю, что вы можете исчерпать все бэкэнды, которые способны сделать это, если навязывание определенного не подходит.

5 голосов
/ 13 марта 2015

Вдохновленный ответом @theo, я написал скрипт для перемещения и изменения размера окна в определенную стандартную позицию на экране. Это было протестировано с бэкэндом Qt4Agg:

import matplotlib.pyplot as plt

def move_figure(position="top-right"):
    '''
    Move and resize a window to a set of standard positions on the screen.
    Possible positions are:
    top, bottom, left, right, top-left, top-right, bottom-left, bottom-right
    '''

    mgr = plt.get_current_fig_manager()
    mgr.full_screen_toggle()  # primitive but works to get screen size
    py = mgr.canvas.height()
    px = mgr.canvas.width()

    d = 10  # width of the window border in pixels
    if position == "top":
        # x-top-left-corner, y-top-left-corner, x-width, y-width (in pixels)
        mgr.window.setGeometry(d, 4*d, px - 2*d, py/2 - 4*d)
    elif position == "bottom":
        mgr.window.setGeometry(d, py/2 + 5*d, px - 2*d, py/2 - 4*d)
    elif position == "left":
        mgr.window.setGeometry(d, 4*d, px/2 - 2*d, py - 4*d)
    elif position == "right":
        mgr.window.setGeometry(px/2 + d, 4*d, px/2 - 2*d, py - 4*d)
    elif position == "top-left":
        mgr.window.setGeometry(d, 4*d, px/2 - 2*d, py/2 - 4*d)
    elif position == "top-right":
        mgr.window.setGeometry(px/2 + d, 4*d, px/2 - 2*d, py/2 - 4*d)
    elif position == "bottom-left":
        mgr.window.setGeometry(d, py/2 + 5*d, px/2 - 2*d, py/2 - 4*d)
    elif position == "bottom-right":
        mgr.window.setGeometry(px/2 + d, py/2 + 5*d, px/2 - 2*d, py/2 - 4*d)


if __name__ == '__main__':

    # Usage example for move_figure()

    plt.figure(1)
    plt.plot([0, 1])
    move_figure("top-right")

    plt.figure(2)
    plt.plot([0, 3])
    move_figure("bottom-right")
4 голосов
/ 15 мая 2015

Для Qt4Agg это работало для меня.

fig = figure()
fig.canvas.manager.window.move(0,0)

Протестировано на Win7, mpl версии 1.4.2, python 2.7.5

2 голосов
/ 14 июня 2013

Это также работает:

fig = figure()
fig.canvas.manager.window.Move(100,400)

Если вы хотите отправить график на изображение и открыть его с помощью диспетчера изображений по умолчанию (который, вероятно, запоминает положение), используйте это с здесь :

fig.savefig('abc.png')
from PIL import Image
im = Image.open("abc.jpg")
im.rotate(0).show()
1 голос
/ 27 мая 2018

У меня сработало следующее.

import matplotlib  
matplotlib.use("TkAgg") # set the backend  

if backend == 'TkAgg':  
    f.canvas.manager.window.wm_geometry("+%d+%d" % (x, y))
1 голос
/ 06 января 2015
'''This is a way to resize the window to a given fraction of the screen.
It uses the screenSize in pixels. User specifies the fx and fy fraction
of the sreen or just a fraction. Couldn't fine how to really position the
window though. No hints in the current figmanager could be found.
But of course, this could be combined with mgr.canvas.move()

'''

import matplotlib.pyplot as plt
#pylab

def screenPos(f):
   '''reset window on screen to size given by fraction f
   where f may by a scalar or a tuple, and where all values
   are 0<=f<=1
   '''
   if type(f)==float: f=(f,) # assert we have a tuple
   mgr = plt.get_current_fig_manager()
   mgr.full_screen_toggle() # primitive but works
   py = mgr.canvas.height()
   px = mgr.canvas.width()
   mgr.resize(f[0]*px,f[-1]*py)
   return f[0]*px,f[-1]*py

px,py = screenPos(0.8)
1 голос
/ 11 января 2013

Для платформы Windows вы можете установить и использовать модуль pyfig из Pyfig .

Пример того, как управлять окнами с рисунками, приведен ниже:

import pylab as p
import pyfig as fig
for ix in range(6): f = p.figure(ix)
fig.stack('all')
fig.stack(1,2)
fig.hide(1)
fig.restore(1)
fig.tile()
fig.pile()
fig.maximize(4)
fig.close('all')
0 голосов
/ 09 мая 2015

Как насчет определения функции для поднятия окна на верхний уровень и перемещения его к верхнему левому углу (например) следующим образом:

def topfig():
    figmgr = get_current_fig_manager()
    figmgr.canvas.manager.window.raise_()
    geom = figmgr.window.geometry()
    x,y,dx,dy = geom.getRect()
    figmgr.window.setGeometry(10, 10, dx, dy)

Затем, когда вы открываете новую фигуру, вы простовведите "topfig ()".Есть ли способ предварительно определить topfig, чтобы он всегда был доступен?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...