画面の終わりに達すると、Python Tkinterラップウィジェット
-
21-12-2019 - |
質問
TK Geometry Managerのための新しい行にパックのようなものはありますか?私はフレームの中にウィジェットを置くためにパックを使っています。高解像度画面では、ウィジェットは並べてフィットします。ただし、それを小さな画面に入れると、ウィジェットはフレーム内の部屋がなくなります。
基本的に、私たちはから行きます:
to:
プロセッサ入力フィールドから切り離す方法を確認できます。関連するコード:
options_frame = ttk.LabelFrame(
parent_frame, text="Blast Options")
options_frame.pack(side=TOP, fill=X, expand=1, padx=5, pady=5)
self._set_up_blast_options(options_frame)
def _set_up_blast_options(self, options_frame):
self.evalue = Tkinter.DoubleVar()
self.evalue.set(1)
self.word_size = Tkinter.IntVar()
self.word_size.set(4)
self.penalty_mismatch = Tkinter.DoubleVar()
self.penalty_mismatch.set(-4)
self.min_d_match = Tkinter.IntVar()
self.min_d_match.set(5)
self.proc_count = Tkinter.IntVar()
self.proc_count.set(cpu_count())
# evalue
e_value_label = ttk.LabelFrame(
options_frame, text="e-Value Threshold")
e_value_entry = ttk.Entry(e_value_label)
e_value_entry.insert(0, self.evalue.get())
e_value_entry.bind('<Return>', self._validate_e_value)
e_value_entry.bind('<FocusOut>', self._validate_e_value)
e_value_label.pack(side=LEFT, expand=1, pady=5, padx=5, fill=X)
e_value_entry.pack(side=TOP, expand=1, pady=5, padx=5, fill=X)
# word size
word_size_label = ttk.LabelFrame(
options_frame, text="Word Size")
word_size_entry = ttk.Entry(word_size_label)
word_size_entry.insert(0, self.word_size.get())
word_size_entry.bind('<Return>', self._validate_word_value)
word_size_entry.bind('<FocusOut>', self._validate_word_value)
word_size_label.pack(side=LEFT, expand=1, pady=5, padx=5, fill=X)
word_size_entry.pack(side=TOP, expand=1, pady=5, padx=5, fill=X)
penalty_mismatch_label = ttk.LabelFrame(
options_frame, text="Penalty Mismatch")
penalty_mismatch_entry = ttk.Entry(penalty_mismatch_label)
penalty_mismatch_entry.insert(0, self.penalty_mismatch.get())
penalty_mismatch_entry.bind(
'<Return>', self._validate_penalty_mismatch_value)
penalty_mismatch_entry.bind(
'<FocusOut>', self._validate_penalty_mismatch_value)
penalty_mismatch_label.pack(side=LEFT, expand=1, pady=5,
padx=5, fill=X)
penalty_mismatch_entry.pack(side=TOP, expand=1, pady=5,
padx=5, fill=X)
# Min D Nucleotides
min_d_match_label = ttk.LabelFrame(
options_frame, text="Minimal Number of D Nucleotides")
min_d_match_entry = ttk.Entry(min_d_match_label)
min_d_match_entry.insert(0, self.min_d_match.get())
min_d_match_entry.bind(
'<Return>', self._validate_min_match_value)
min_d_match_entry.bind(
'<FocusOut>', self._validate_min_match_value)
min_d_match_label.pack(side=LEFT, expand=1, pady=5, padx=5, fill=X)
min_d_match_entry.pack(side=TOP, expand=1, pady=5, padx=5, fill=X)
# how many cpus to use
proc_count_label = ttk.LabelFrame(
options_frame, text="Processors")
proc_count_entry = ttk.Entry(proc_count_label)
proc_count_entry.insert(0, self.proc_count.get())
proc_count_entry.bind(
'<Return>', self._validate_proc_count_value)
proc_count_entry.bind(
'<FocusOut>', self._validate_proc_count_value)
proc_count_label.pack(side=LEFT, expand=1, pady=5, padx=5, fill=X)
proc_count_entry.pack(side=TOP, expand=1, pady=5, padx=5, fill=X)
.
オプションのイベントバインディングと設定の多くが関係なく、まだ含めると思いました。最良の選択肢は、グリッドマネージャに切り替えることができますか?このフレームが別のものの内側に詰まっている問題は...などです。Grid Managerの使用を開始すると、同じフレームにパックされたグリッドマネージャを混在させることはできないため、すべてに使用する必要がありますか?
解決
AFAIK TKINTERに動的インタフェースを作成するための内蔵方法はありません。あなたの最善の策は、画面の解像度を取得し、次にグリッド/パックを適切に取得することです。
user32 = ctypes.windll.user32
get_screensize = (user32.GetSystemMetrics(0), user32.GetSystemMetrics(1))
.
たとえば....
widget1 = tkinter.Entry(root,width=20,etc)
widget2 = tkinter.Label(root,text='Hello',etc)
## Now perform update_idletasks() which will force
## Tkinter to calculate their size.
widget1.update_idletasks()
widget2.update_idletasks()
## Now calculate whether they'll fit.
if widget1.winfo_width() + widget2.winfo_width() > screensize[0]:## Not enough space
widget1.grid(row=0)
widget2.grid(row=1)
else:## Both will fit on one line.
widget1.grid(row=0,column=0)
widget2.grid(row=0,column=1)
. 他のヒント
一般的に、私はi_do_pythonの答えに同意しますが、私は小さな修正を1つにします。私はすべてのウィジェットを新しいフレームに入れます、そして私はラップするかどうかに関してlitmus testとしてフレームの幅を使うでしょう。そして、"<Configure>"
イベントのイベントハンドラをバインドすることができ、その後、アプリケーションのウィンドウ(したがってフレーム)のサイズ変更時にフレームの内容をラップする必要があるかどうかを確認します。
私はグリッドメソッドを使用して、ウィジェットをフレームにインテリジェントに挿入する関数を書きました。確かに改善することができますが、それは私のために働いています。通常、.grid()
を使用して親を埋める場合は、充填ウィジェットが幅が変わると、空白を無駄にすることができます。以下の関数は、親を論理列(コード内のdivisions
)に分割し、ウィジェットが複数の列にまたがることを可能にすることによってこれに対処します。その結果、無駄な無駄な空白を持つグリッドレイアウトがあります。 divisions
を高く設定すると、結果はより良いですが、デフォルト値はほとんどの場合に機能するはずです。
def smart_grid(parent, *args, **kwargs): # *args are the widgets!
divisions = kwargs.pop('divisions', 100)
force_f = kwargs.pop('force', False)
if 'sticky' not in kwargs:
kwargs.update(sticky='w')
try:
parent.win_width
except:
parent.win_width = -1
winfo_width = parent.winfo_width()
if 1 < winfo_width != parent.win_width or force_f:
parent.win_width = winfo_width
row = col = width = 0
argc = len(args)
for i in range(argc):
widget_width = args[i].winfo_width()
columns = max(1, int(widget_width * float(divisions) / winfo_width))
width += widget_width
if width > winfo_width:
width = widget_width
row += 1
col = 0
args[i].grid(row=row, column=col, columnspan=columns, **kwargs)
col += columns
parent.update_idletasks() # update() #
return row + 1
.
最終的には、w.winfo_reqwidth()
で書き換えるために数分かかります。