Подтвердить что ты не робот

Как установить абсолютное положение окон цифр с помощью matplotlib?

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

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

4b9b3361

Ответ 1

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

import matplotlib
matplotlib.use("wx")
from pylab import *
figure(1)
plot([1,2,3,4,5])
thismanager = get_current_fig_manager()
thismanager.window.SetPosition((500, 0))
show()

за @tim в разделе комментариев ниже, вы можете перейти на

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

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

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

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

Ответ 2

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

import matplotlib.pyplot as plt

fig, ax = 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 минут, чтобы это выяснить. Надежда, которая помогает кому-то.

Ответ 3

Вдохновленный @theo ответом, я написал script для перемещения и изменения размера окна на определенную стандартную позицию на экране. Это было протестировано с помощью бэкэнда 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

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

import matplotlib
import matplotlib.pyplot as plt

def move_figure(f, x, y):
    """Move figure 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)
    plt.show()


f, ax = plt.subplots()
move_figure(f, 500, 500)

Ответ 5

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

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

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

Ответ 6

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

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()

Ответ 7

Для платформы 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')

Ответ 8

'''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)

Ответ 9

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

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, чтобы он всегда был доступен?