私はtkinterで個人的に使うための非常に小さなプログラムを作っています。私は本当に奇妙な壁にぶつかりました。私はpywin32のバインディングとtkinterを混在させています。なぜなら、pywin32の構文と命名規則をすべて嫌うからです。そして、tkinterははるかに少ないコードでより多くの作業を行うように感じます。 pywin32のクリップボードの監視とtkinterのプログラムへの私のプログラムの反応との間の移行で、奇妙なことが起こっています。PyWin32を少し混ぜると、このTkinterコードがクラッシュするのはなぜですか?
ウィンドウとそのすべてのコントロールがtkinterで処理されています。 pywin32バインディングは、クリップボードが変わったときにクリップボードの監視とクリップボードへのアクセスを行っています。クリップボードがpywin32の作品を見ている方法について私が集めたことから、あなたはpywin32にあなたのウィンドウのhwnd値を提供する限り、あなたが望むものであればそれを動作させることができます。私はその部分をやっていて、プログラムが最初に始まるときに動作します。クリップボードが変更されても機能しないようです。
プログラムが起動すると、クリップボードをつかみ、それを検索ボックスと編集ボックスに入れます。クリップボードが変更されたとき、私が発射したいイベントは発射されています...プログラムが起動する前に完全に機能していたイベントが、今行われていることをするのではなく奇妙なハングを引き起こしています。クリップボードの内容をstdoutに出力することはできますが、クリップボードが変更されても同じデータをtkinterウィジェットに入れないでください。それは、クリップボードの変更通知によって解消された後に、私のtkinterウィジェットのいずれかとやりとりするようになると、それだけのようにハングアップします。
pywin32のエチケットは、私がtkinterを使っているプログラムに使用していたクリップボードを見ているサンプルコードを修正するのに欠けているようです。 Tkinterは明らかにスタックトレースやエラーメッセージを生成したくないので、pdbを使ってデバッグしようとしたらどうしたらいいか分からない。
は、ここでは、コードです:それは助けることができれば
#coding: utf-8
#Clipboard watching cribbed from ## {{{ http://code.activestate.com/recipes/355593/ (r1)
import pdb
from Tkinter import *
import win32clipboard
import win32api
import win32gui
import win32con
import win32clipboard
def force_unicode(object, encoding="utf-8"):
if isinstance(object, basestring) and not isinstance(object, unicode):
object = unicode(object, encoding)
return object
class Application(Frame):
def __init__(self, master=None):
self.master = master
Frame.__init__(self, master)
self.pack()
self.createWidgets()
self.hwnd = self.winfo_id()
self.nextWnd = None
self.first = True
self.oldWndProc = win32gui.SetWindowLong(self.hwnd, win32con.GWL_WNDPROC, self.MyWndProc)
try:
self.nextWnd = win32clipboard.SetClipboardViewer(self.hwnd)
except win32api.error:
if win32api.GetLastError() == 0:
# information that there is no other window in chain
pass
else:
raise
self.update_search_box()
self.word_search()
def word_search(self):
#pdb.set_trace()
term = self.searchbox.get()
self.resultsbox.insert(END, term)
def update_search_box(self):
clipboardtext = ""
if win32clipboard.IsClipboardFormatAvailable(win32clipboard.CF_TEXT):
win32clipboard.OpenClipboard()
clipboardtext = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard()
if clipboardtext != "":
self.searchbox.delete(0,END)
clipboardtext = force_unicode(clipboardtext)
self.searchbox.insert(0, clipboardtext)
def createWidgets(self):
self.button = Button(self)
self.button["text"] = "Search"
self.button["command"] = self.word_search
self.searchbox = Entry(self)
self.resultsbox = Text(self)
#Pack everything down here for "easy" layout changes later
self.searchbox.pack()
self.button.pack()
self.resultsbox.pack()
def MyWndProc (self, hWnd, msg, wParam, lParam):
if msg == win32con.WM_CHANGECBCHAIN:
self.OnChangeCBChain(msg, wParam, lParam)
elif msg == win32con.WM_DRAWCLIPBOARD:
self.OnDrawClipboard(msg, wParam, lParam)
# Restore the old WndProc. Notice the use of win32api
# instead of win32gui here. This is to avoid an error due to
# not passing a callable object.
if msg == win32con.WM_DESTROY:
if self.nextWnd:
win32clipboard.ChangeClipboardChain (self.hwnd, self.nextWnd)
else:
win32clipboard.ChangeClipboardChain (self.hwnd, 0)
win32api.SetWindowLong(self.hwnd, win32con.GWL_WNDPROC, self.oldWndProc)
# Pass all messages (in this case, yours may be different) on
# to the original WndProc
return win32gui.CallWindowProc(self.oldWndProc, hWnd, msg, wParam, lParam)
def OnChangeCBChain (self, msg, wParam, lParam):
if self.nextWnd == wParam:
# repair the chain
self.nextWnd = lParam
if self.nextWnd:
# pass the message to the next window in chain
win32api.SendMessage (self.nextWnd, msg, wParam, lParam)
def OnDrawClipboard (self, msg, wParam, lParam):
if self.first:
self.first = False
else:
#print "changed"
self.word_search()
#self.word_search()
if self.nextWnd:
# pass the message to the next window in chain
win32api.SendMessage(self.nextWnd, msg, wParam, lParam)
if __name__ == "__main__":
root = Tk()
app = Application(master=root)
app.mainloop()
root.destroy()
私はそれはおそらく働くだろうと思うが、私は更新をトリガするために、メインループのいくつかの並べ替えにポーリングする必要がありますブール変数は他の場所に置かれます。 この質問にお答えいただきありがとうございます。私はちょっと待ってから、プロジェクト全体をwxPythonに変換しました。私はwxPythonがそれほど好きではありませんが、この小さなプロジェクトでは、それを完全に採用するだけの頭痛にはならないでしょう。 – Erlog