저는 tkinter에서 개인적인 사용을위한 아주 작은 프로그램을 만들고 있습니다. 그리고 저는 정말 이상한 벽에 뛰어 들었습니다. 필자는 pywin32 바인딩과 tkinter를 혼합합니다. 왜냐하면 pywin32의 구문 및 명명 규칙과 관련이 없기 때문에 tkinter는 훨씬 적은 코드로 더 많은 작업을 수행 할 수 있습니다. pywin32 클립 보드 시청과 tkinter에서 내 프로그램의 반응 사이의 전환에서 이상한 일이 발생합니다.약간의 PyWin32와 혼합 할 때이 유효한 Tkinter 코드가 왜 충돌합니까?
내 창과 모든 컨트롤이 tkinter에서 처리되고 있습니다. 클립 보드가 바뀌면 pywin32 바인딩은 클립 보드 감시 및 클립 보드 액세스를 수행합니다. 클립 보드가 pywin32 작업을 보는 방식에 관해서 내가 수집 한 것부터, pywin32에 윈도우의 hwnd 값을 제공하는 한 원하는 모든 작업을 할 수 있습니다. 나는 그 부분을하고 있으며 프로그램이 처음 시작할 때 작동합니다. 클립 보드가 바뀌면 작동하지 않는 것 같습니다.
프로그램이 실행되면 클립 보드를 잡고 검색 상자와 편집 상자에 넣습니다. 클립 보드가 수정되면 발사하고 싶은 이벤트가 시작됩니다 ... 프로그램이 시작될 때 완전히 작동했던 이벤트를 제외하고는 이제 수행해야 할 작업을 수행하는 대신 이상한 응답이 발생합니다. 클립 보드가 변경되면 클립 보드 내용을 표준 출력으로 인쇄 할 수 있지만 같은 데이터를 tkinter 위젯에 넣지는 않습니다. 그것은 클립 보드 변경 알림에 의해 해고 된 후 내 tkinter 위젯 중 하나와 상호 작용하기 시작하면 중단됩니다.
필자가 tkinter를 사용하는 프로그램에 사용했던 샘플 코드를 클립 보드에서 보는 것에 적응하지 못했던 pywin32 에티켓이있는 것처럼 느껴집니다. 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