72

tkinter ウィンドウを中央に配置しようとしています。ウィンドウのサイズと画面のサイズをプログラムで取得し、それを使用してジオメトリを設定できることは知っていますが、ウィンドウを画面の中央に配置する簡単な方法があるかどうか疑問に思っています。

4

12 に答える 12

76

最も単純な(しかしおそらく不正確な)方法は、tk :: PlaceWindowを使用することです。これは、トップレベルウィンドウのパス名を引数として取ります。メインウィンドウのパス名は.

import tkinter

root = tkinter.Tk()
root.eval('tk::PlaceWindow . center')

second_win = tkinter.Toplevel(root)
root.eval(f'tk::PlaceWindow {str(second_win)} center')

root.mainloop()

問題

単純なソリューションでは、タイトルバーとメニューバーのある最も外側のフレームが無視されます。これにより、真の中央からわずかにオフセットされます。

ソリューション

import tkinter  # Python 3

def center(win):
    """
    centers a tkinter window
    :param win: the main window or Toplevel window to center
    """
    win.update_idletasks()
    width = win.winfo_width()
    frm_width = win.winfo_rootx() - win.winfo_x()
    win_width = width + 2 * frm_width
    height = win.winfo_height()
    titlebar_height = win.winfo_rooty() - win.winfo_y()
    win_height = height + titlebar_height + frm_width
    x = win.winfo_screenwidth() // 2 - win_width // 2
    y = win.winfo_screenheight() // 2 - win_height // 2
    win.geometry('{}x{}+{}+{}'.format(width, height, x, y))
    win.deiconify()

if __name__ == '__main__':
    root = tkinter.Tk()
    root.attributes('-alpha', 0.0)
    menubar = tkinter.Menu(root)
    filemenu = tkinter.Menu(menubar, tearoff=0)
    filemenu.add_command(label="Exit", command=root.destroy)
    menubar.add_cascade(label="File", menu=filemenu)
    root.config(menu=menubar)
    frm = tkinter.Frame(root, bd=4, relief='raised')
    frm.pack(fill='x')
    lab = tkinter.Label(frm, text='Hello World!', bd=4, relief='sunken')
    lab.pack(ipadx=4, padx=4, ipady=4, pady=4, fill='both')
    center(root)
    root.attributes('-alpha', 1.0)
    root.mainloop()

tkinterを使用すると、返される値が正確であることを確認するために、ジオメトリを取得する前に常にupdate_idletasks()メソッド
を直接呼び出す必要があります。

外枠の寸法を決定する方法は4つあります。外枠を除い
winfo_rootx()て、ウィンドウの左上のx座標が表示されます。外枠の左上のx座標が表示されます。 それらの違いは、外枠の幅です。
winfo_x()

frm_width = win.winfo_rootx() - win.winfo_x()
win_width = win.winfo_width() + (2*frm_width)

との違いはwinfo_rooty()winfo_y()タイトルバー/メニューバーの高さです。

titlebar_height = win.winfo_rooty() - win.winfo_y()
win_height = win.winfo_height() + (titlebar_height + frm_width)

ウィンドウの寸法と位置は、geometryメソッドを使用して設定します。ジオメトリ文字列の前半は、外枠を除いたウィンドウの幅と高さで
あり、後半は、外枠の左上のx座標とy座標です。

win.geometry(f'{width}x{height}+{x}+{y}')

ウィンドウが動くのが見えます

ウィンドウが画面上を移動するのを防ぐ1つの方法は .attributes('-alpha', 0.0)、ウィンドウを完全に透明にして1.0、ウィンドウが中央に配置された後に設定することです。この目的のために、Windows 7では、withdraw()またはそれ以降のiconify()後に続くものdeiconify()はうまく機能しないようです。私deiconify()はウィンドウをアクティブにするためのトリックとして使用します。


オプションにする

デフォルトでは中央に配置するのではなく、ウィンドウを中央に配置するオプションをユーザーに提供することを検討することをお勧めします。そうしないと、コードがウィンドウマネージャーの機能に干渉する可能性があります。たとえば、xfwm4にはスマート配置があり、画面がいっぱいになるまでウィンドウを並べて配置します。また、すべてのウィンドウを中央に配置するように設定することもできます。その場合、ウィンドウが移動するのを確認する問題は発生しません(上記のとおり)。


マルチモニター

マルチモニターシナリオが懸念される場合は、screeninfoプロジェクトを調べるか、Qt(PySide2)またはGTK(PyGObject)で何ができるかを調べてから、tkinterの代わりにこれらのツールキットの1つを使用できます。GUIツールキットを組み合わせると、依存関係が不当に大きくなります。

于 2012-04-04T20:21:26.217 に答える
72

インスタンス (ウィンドウ)の幅と高さ (ピクセル単位) をそれぞれ返すメソッドwinfo_screenwidthとを使用してみてください。いくつかの基本的な計算を使用すると、ウィンドウを中央に配置できます。winfo_screenheightTk

import tkinter as tk
from PyQt4 import QtGui    # or PySide

def center(toplevel):
    toplevel.update_idletasks()

    # Tkinter way to find the screen resolution
    # screen_width = toplevel.winfo_screenwidth()
    # screen_height = toplevel.winfo_screenheight()

    # PyQt way to find the screen resolution
    app = QtGui.QApplication([])
    screen_width = app.desktop().screenGeometry().width()
    screen_height = app.desktop().screenGeometry().height()

    size = tuple(int(_) for _ in toplevel.geometry().split('+')[0].split('x'))
    x = screen_width/2 - size[0]/2
    y = screen_height/2 - size[1]/2

    toplevel.geometry("+%d+%d" % (x, y))
    toplevel.title("Centered!")    

if __name__ == '__main__':
    root = tk.Tk()
    root.title("Not centered")

    win = tk.Toplevel(root)
    center(win)

    root.mainloop()

update_idletasks返される値が正確であることを確認するために、ウィンドウの幅と高さを取得する前にメソッドを呼び出しています。

Tkinterは、水平または垂直に拡張された 2 つ以上のモニターがあるかどうかを認識しません。したがって、すべての画面の合計解像度が得られ、ウィンドウは画面の中央のどこかに表示されます。

一方、 PyQtはマルチモニター環境も表示しませんが、左上モニターの解像度のみを取得します(4つのモニター、2つの上と2つの下が正方形を作っていると想像してください)。そのため、ウィンドウをその画面の中央に配置することで作業を行います。PyQtTkinterの両方を使用したくない場合は、最初から PyQt を使用する方がよいでしょう。

于 2010-07-28T13:06:24.503 に答える
28

この回答は、初心者を理解するのに適しています

#
import tkinter as tk

win = tk.Tk()  # Creating instance of Tk class
win.title("Centering windows")
win.resizable(False, False)  # This code helps to disable windows from resizing

window_height = 500
window_width = 900

screen_width = win.winfo_screenwidth()
screen_height = win.winfo_screenheight()

x_cordinate = int((screen_width/2) - (window_width/2))
y_cordinate = int((screen_height/2) - (window_height/2))

win.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate))

win.mainloop()
于 2018-05-30T05:33:19.750 に答える
2

PYTHON Tkinter でウィンドウをセンタリングする これは tkinter で最も簡単なことです。なぜなら、ウィンドウの寸法とコンピュータ画面の寸法だけを知っておく必要があるからです。私は何とか誰かを助けることができる次のコードを思いつき、彼らがフォローアップできるようにいくつかのコメントを追加しました.

コード

    #  create a window first
    root = Tk()
    # define window dimensions width and height
    window_width = 800
    window_height = 500
    # get the screen size of your computer [width and height using the root object as foolows]
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    # Get the window position from the top dynamically as well as position from left or right as follows
    position_top = int(screen_height/2 -window_height/2)
    position_right = int(screen_width / 2 - window_width/2)
    # this is the line that will center your window
    root.geometry(f'{window_width}x{window_height}+{position_right}+{position_top}')
    # initialise the window
    root.mainloop(0)
于 2020-09-11T13:36:39.350 に答える
0

この方法はクロスプラットフォームであり、複数のモニター/画面で機能し (アクティブな画面をターゲットにします)、Tk 以外のライブラリは必要ありません。ルート ウィンドウは、不要な「点滅」やアニメーションなしで中央に表示されます。

import tkinter as tk

def get_geometry(frame):
    geometry = frame.winfo_geometry()
    match = re.match(r'^(\d+)x(\d+)\+(\d+)\+(\d+)$', geometry)
    return [int(val) for val in match.group(*range(1, 5))]

def center_window(root):
    """Must be called after application is fully initialized
    so that the root window is the true final size."""
    # Avoid unwanted "flashing" by making window transparent until fully ready
    root.attributes('-alpha', 0)

    # Get dimensions of active screen/monitor using fullscreen trick; withdraw
    # window before making it fullscreen to preserve previous dimensions
    root.withdraw()
    root.attributes('-fullscreen', True)
    root.update_idletasks()
    (screen_width, screen_height, *_) = get_geometry(root)
    root.attributes('-fullscreen', False)

    # Restore and get "natural" window dimensions
    root.deiconify()
    root.update_idletasks()
    (window_width, window_height, *_) = get_geometry(root)

    # Compute and set proper window center
    pos_x = round(screen_width / 2 - window_width / 2)
    pos_y = round(screen_height / 2 - window_height / 2)
    root.geometry(f'+{pos_x}+{pos_y}')
    root.update_idletasks()
    
    root.attributes('-alpha', 1)

# Usage:
root = tk.Tk()
center_window(root)

ウィンドウのジオメトリが変更されるたびに、 をupdate_idletasks()呼び出して、操作を強制的に同期/即時に実行する必要があることに注意してください。Python 3 の機能を使用しますが、必要に応じて Python 2.x に簡単に適応させることができます。

于 2020-12-13T08:00:22.593 に答える