如何使用matplotlib设置图形窗口的绝对位置?

Jas*_*n R 34 python matplotlib

我正在编写一个简单的Python应用程序,它使用matplotlib在屏幕上显示一些数字.生成的数字数量基于用户输入和整个应用程序生命周期的变化.用户能够发出"绘图"命令以生成具有所选数据系列的新图形窗口.为了改善用户体验,我想提供另一个命令,它将以一种方便的方式以编程方式排列所有打开的图形窗口(例如,将它们平铺在可用的屏幕空间中).

我相信已经找到了允许我调整图窗口大小的API(以像素为单位),但是没有成功找到在屏幕上设置其绝对位置的方法.有没有办法在不深入了解正在使用的后端的细节的情况下做到这一点?我想以后端不可知的方式执行此操作,以便我可以避免依赖可能在将来更改的实现细节.

K.-*_*Aye 33

最终找到了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)
Run Code Online (Sandbox Code Playgroud)

如果一个人不知道x和y宽度,可以先读出它们,如下所示:

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

然后设置相同大小的新位置:

mngr.window.setGeometry(newX, newY, dx, dy)
Run Code Online (Sandbox Code Playgroud)

我经常搜索这个,最后投入了30分钟来找到它.希望能帮助别人.

  • 比接受的答案要好得多. (3认同)
  • 请注意,我们也可以使用fig.canvas.manager代替mngr = get_current_fig_manager() (3认同)
  • 首先,`fig, ax = subplots()` 不起作用。它必须是`fig, ax = plt.subplots()`。然后,在`mngr.window.setGeometry()` 上,我得到“# AttributeError: SetPosition”。 (2认同)
  • 在 Pycharm 中,我得到 `AttributeError: '_tkinter.tkapp' object has no attribute 'setGeometry'` (2认同)

cxr*_*ers 14

在目前为止的答案的帮助和我自己的一些修修补补,这是一个检查当前后端并使用正确语法的解决方案.

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()
Run Code Online (Sandbox Code Playgroud)

  • 不错,但将 `plt.show` 移到函数外,因为它会阻塞。你可能想要这个的主要原因是当你有很多数字时! (2认同)
  • 好提示。我将其添加到我的 ipython 启动脚本中。还在“move_figure”函数中添加了“if isinstance(f,int) : f = plt.figure(f)”,以便它可以处理图形编号或对象。(即“move_figure(1,500,500)”) (2认同)

nye*_*e17 12

我不知道这是一种与后端无关的方法,但绝对有可能为一些常见的后端做到这一点,例如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()
Run Code Online (Sandbox Code Playgroud)

根据下面评论部分的@tim,您可能想切换到

thismanager.window.wm_geometry("+500+0")
Run Code Online (Sandbox Code Playgroud)

代替.对于TkAgg,只需将其更改为

thismanager.window.wm_geometry("+500+0")
Run Code Online (Sandbox Code Playgroud)

所以我认为你可以用尽所有能够做到这一点的后端,如果强加某个后端不是一个选择.

  • Dunno为什么,但对我来说(Windows,Python Idle,Python 2.7,从Notepad ++开始)`thismanager.window.wm_geometry("+ 500 + 0")`工作,`thismanager.window.SetPosition((500,0) )`didnt ;-) (3认同)
  • 尝试这两种解决方案,我得到“MainWindow”对象没有属性“SetPosition”和“MainWindow”没有属性“wm_geometry” (2认同)

ott*_*erb 7

对于 Qt4Agg,这对我有用。

fig = figure()
fig.canvas.manager.window.move(0,0)
Run Code Online (Sandbox Code Playgroud)

在 Win7、mpl 版本 1.4.2、python 2.7.5 上测试


div*_*nex 5

受@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")
Run Code Online (Sandbox Code Playgroud)