2016-04-13 7 views
0

だから、私は主に3つのエリアで構成ウィンドウが必要です小さなPythonの3プロジェクトがあります。データ入力フォームやステータスバーのようなフレームを作る方法は、Python 3の他のtkinterフレームの上に常に表示されますか?

  • ツールバー(上部)。
  • データベースデータを持つテーブル/ツリービュー(中央) - このテーブルはスクロールバーで下向きになるはずですが、まだツリービューで動作させる方法はわかりません。
  • ステータスバー(下)。

また、ステータスバーのすぐ上のユーザーの要求に応じてすばやくデータ入力フォームを追加しようとしています。私はpack()を使用して、このウィンドウのメイン構造を作成できたと思います。データ入力フォームも表示され、ユーザーが適切なボタンをクリックすると消えます。しかし、解決する方法がわからないことがいくつかあります。最初の1つは、ユーザーがウィンドウのサイズを小さくして小さくすると、ステータスバーとデータ入力フォームの両方がテーブル/ツリービューの下に表示されなくなることです。どうすればそれらを常に上に置くことができますか?ここで

は私のコードです:

#!/usr/local/bin/python3 
# encoding: utf-8 

from tkinter import * 
from tkinter import ttk 

entryform_visible = 0 


class mainWindow: 
    def __init__(self, master): 
     self.master = master 
     master.title("AppTittle") 
     master.minsize(width=700, height=200)   

     def show_entryform(): 
      global entryform_visible 
      if entryform_visible == 1: 
       hide_entryform() 
       return 
      else: 
       entryform_visible = 1 
       # Form for data entry (bottom of main window) 
       status_txt.set("Introducing new data...") 
       self.bottomframe.pack(side=BOTTOM, fill=X) 

     def hide_entryform(): 
      global entryform_visible 
      self.bottomframe.pack_forget() 
      entryform_visible = 0 
      status_txt.set("Introduction of data was cancelled.") 

     def add_register(): 
      hide_entryform() 
      status_txt.set("New register added!")     

     # Tool bar (buttons) 
     self.topframe = ttk.Frame(root, padding="3 3 12 12") 
     self.topframe.pack(side=TOP, fill=X) 
     btn_add = ttk.Button(self.topframe, text="Button1").pack(side=LEFT) 
     btn_add = ttk.Button(self.topframe, text="+", width=2, command=show_entryform).pack(side=RIGHT) 
     btn_add = ttk.Button(self.topframe, text="Button2").pack(side=RIGHT) 

     # Data table (center area of window) 
     self.mainframe = ttk.Frame(root) 
     self.mainframe.pack(side=TOP, fill=X) 

     tree = ttk.Treeview(self.mainframe, height=25, selectmode='extended') 
     tree['columns'] = ('id', 'name', 'descr') 
     tree.pack(side=TOP, fill=BOTH) 
     tree.column('#0', anchor=W, minwidth=0, stretch=0, width=0) 
     tree.column('id', anchor=W, minwidth=30, stretch=0, width=40) 
     tree.column('name', minwidth=30, stretch=1, width=30) 
     tree.column('descr', minwidth=100, stretch=1, width=200) 
     tree.heading('id', text="ID") 
     tree.heading('name', text="Name") 
     tree.heading('descr', text="Description") 

     # Data entry form 
     self.bottomframe = ttk.Frame(root, padding="3 3 12 12") 
     ttk.Label(self.bottomframe, text="Field 1").pack(side=LEFT) 
     text_input_obj = ttk.Entry(self.bottomframe, width=13) 
     text_input_obj.pack(side=LEFT) 
     text_input_obj.focus_set() 
     btn_add = ttk.Button(self.bottomframe, text="Add", command=add_register).pack(side=RIGHT) 
     # We are going to pack() this later (when the user clicks the '+' button) 

     # Status bar 
     self.statusframe = ttk.Frame(root, padding="2 2 2 2") 
     self.statusframe.pack(side=BOTTOM, fill=X) 
     status_txt = StringVar() 
     self.statusbar = ttk.Label(self.statusframe, textvariable=status_txt).pack(side=LEFT) 


root = Tk() 
appwindow = mainWindow(root) 
root.mainloop() 
+0

私は方法を考え出したと思います。 pack()引数に 'before = self.mainframe'を追加できることがわかりました。両方のフレーム(ステータスバーとフォーム)でそれを行うと、他のレイヤーの上に貼り付けられます。今では、スクロールバーがツリービューで動作するようにする方法を見つけなければなりません。 –

答えて

0

最初のものは、ユーザーがそれを 小さくし、ウィンドウのサイズを変更する場合、ステータスバーおよびデータ入力フォームが 下の表を消えるの両方ということです/ツリー表示。どうすればそれらを常に上に置くことができますか?

これは、パッカーの仕組みと関係があります。使用可能なスペースが必要なスペースよりも小さい場合、ウィジェットを切り落とし始めます。これは、ウィジェットがどのようにパックされたかの逆の順序で行います。

この場合、下部フレームが最後にパックされているため、ウィンドウを縮小してすべてに収まるようにウィンドウを縮小すると、最初にパックが展開された可能性のあるウィンドウを縮小してから、パックされた最後のウィジェットから始まるウィジェット。この場合は最後にパックされたので、チョップされるのはself.statusframeです。

これを解決するには2通りの方法があります。 1つは、すべてをルートウィンドウにパックする順序を単純に逆にすることです。もう一つは、最初にツリーウィジェットを非常に小さくしてから、それを大きくしてスペースを埋めることです。ツリービューの自然なサイズは小さいので、tkinterはウィジェットをビューから削除する前に縮小します。あなたは、この第二の技術を行う場合、あなたはそれが出て起動時にウィンドウを大きくするwm_geometryを使用することができます(そうでない木がに成長する任意のスペースを持っていません)

私のアドバイスは、常にグループあなたpackgrid文をしています。このような変更は非常に簡単で、コードの視覚化が容易になります。例えば、第一の技術を使用して、私は、関数の底にメインエリアのパックを移動します。これにより

# layout the main GUI 
self.topframe.pack(side=TOP, fill=X) 
self.statusframe.pack(side=BOTTOM, fill=X) 
self.mainframe.pack(side=TOP, fill=BOTH, expand=True) 

を、スペースを取得するときにタイトなパックは、ツリーを切り落とすために開始します。しかし、木が大きいので、それが消え始める前にチョップがたくさんあります。

これを実行すると、レイアウトに別の問題が発生します。つまり、ツリービューを拡張して、余分なスペースを埋め込むことができません。mainframe

tree.pack(side=TOP, fill=BOTH, expand=True) 

これは別の問題を引き起こします。つまり、あなたのポップアップbottomframeが隠れてしまうことがあります。これは、packがこの種の状況でうまく動作するように設計されていないためです。これもまた、packが追加された逆の順序でウィジェットを切り詰めるようになるからです。最後に追加しているので、最初に切り取られたウィジェットです。ユーザーがウィンドウのサイズを小さくすると、ウィンドウのサイズを小さくすると、ウィンドウが表示されないことがあります。

この特定の場合のより良い解決策は、ではなく、この1つのウィジェットの使用パックです。代わりに、 "ポップアップ"したいので、placeを使うことができます。 placeは、他のウィジェットの上にウィジェットをポップアップするのに最適です。あなたがする必要がある唯一の他の事は、このフレームは、あなたがliftで行うことができますステータスバー、より積層順で高くなっていることを確認している。

def show_entryform(): 
    ... 
    self.bottomframe.place(relx=.5, rely=1, anchor="s", relwidth=1.0) 
    self.bottomframe.lift() 

そして、もちろん、place_forget代わりのpack_forget使用:

def hide_entryform(): 
    ... 
    self.bottomframe.place_forget() 
    ... 
+0

私は非常に明確なヒントを、それ以来行ってきた変更のいくつかと組み合わせようとしています。それはかなりストレートですね。私はしかし、新たな疑念を持っています。 'bottomframe'を' pack'から 'place'に変更すると、パックされた' statusframe'の上に置かれます。常に表示されたい(ウィンドウの一番下にあります)。私は 'pack'に戻ってもいいでしょうか、何らかの調整をしてこのフレームの' place 'をまだ勧めていますか?私は、 'bottomframe'を' statusframe'の真上に表示しようとしています。 –

+0

@Victor:あなたが望むものを達成する方法はたくさんあります。あなたがステータスバーの上にそれを望んでいるかどうかわかりませんでした。グリッドはウィジェットの表示方法を記憶しているので、ウィジェットを隠して復元する方が簡単であるため、最も簡単で正直なところ、「グリッド」に切り替えることです。つまり、 'place'を使ってポップアップをステータスウィンドウの上(または中央のウィンドウの一番下)に置くことができます。ドキュメントを読む - ウィジェットを別のウィジェットに対して相対的に配置するオプションがあります( 'in_'オプションを探してください) –

+0

' place'を使って正しく取得できました: 'self.bottomframe.place(in_ =以前の 'pack'ベースのフォームと比較して、どういうわけか、私は何かを得ました。ボトムフレームが画面に表示されたときに起こっていた奇妙な瞬きを取り除きます:) –