我遇到两个要交互的tkinter类时遇到麻烦。我认为这是由于我对Tk.Toplevel
缺乏了解。我的代码没有创建一个全新的全屏窗口来抓屏,而是给出了一个错误:
AttributeError: '_tkinter.tkapp' object has no attribute 'mousePressEvent'
有人可以帮助我理解我代码中的父子关系层次结构吗?我并不是要任何人重写我的代码,我只是想了解我已经拥有的东西,因此我可以找出问题所在。我在SO中没有找到与多个窗口交互的多个类的许多示例-因此很难掌握继承的相互作用。
这是我认为的结构:
这准确吗?
代码
import tkinter as tk
from PIL import ImageGrab, ImageTk, Image
import cv2
import numpy as np
from tkinter import filedialog
class ScreenSnip(tk.Toplevel):
def __init__(self, master):
super().__init__(master)
def get_snip(self):
self.configure(cursor='cross')
self.attributes('-fullscreen', True)
self.attributes('-alpha', 0.4)
self.canvas = tk.Canvas(self, bg='dark gray')
self.canvas.pack(fill='both', expand=True)
self.begin_x = 0
self.begin_y = 0
self.end_x = 0
self.end_y = 0
self.click_drag = False
self.canvas.create_rectangle(0, 0, 0, 0, outline='#0052d6', width=2, fill='white', tags='snip_rect')
self.canvas.bind('<ButtonPress-1>', self.mousePressEvent)
self.canvas.bind('<B1-Motion>', self.mouseMoveEvent)
self.canvas.bind('<ButtonRelease-1>', self.mouseReleaseEvent)
print('Capture the screen...')
def mousePressEvent(self, event):
self.begin_x = event.x
self.begin_y = event.y
print(self.begin_x,self.begin_y)
def mouseMoveEvent(self, event):
self.click_drag = True
self.end_x = event.x
self.cur_y = event.y
width = self.end_x - self.begin_x
height = abs(width * 2/3)
if self.cur_y < self.begin_y:
height *= -1
self.end_y = self.begin_y + height
self.canvas.coords('snip_rect', self.begin_x, self.begin_y, self.end_x, self.end_y)
def mouseReleaseEvent(self, event):
self.destroy()
self.master.update_idletasks()
self.master.after(100) # give time for screen to be refreshed so as not to see the blue box on the screenshot
if not self.click_drag: # if the user just clicks, instead of clicking and dragging
self.begin_x -= 300
self.begin_y += 200
self.end_x = self.begin_x + 600
self.end_y = self.begin_y - 400
x1 = min(self.begin_x, self.end_x)
y1 = min(self.begin_y, self.end_y)
x2 = max(self.begin_x, self.end_x)
y2 = max(self.begin_y, self.end_y)
img = ImageGrab.grab(bbox=(x1, y1, x2, y2))
self.img = cv2.cvtColor(np.array(img), cv2.COLOR_BGR2RGB)
cv2.imshow('Captured Image', self.img)
cv2.waitKey(0)
font1 = ("arial", 18, "bold")
class AcquireImage:
def __init__(self, master):
self.master = master
self.fontA = ("arial", 20, "bold")
self.frame = tk.Frame(master, bg="#1B2631")
self.frame.pack(fill="both", expand=True)
self.button1 = tk.Button(self.frame, text="Select Image File", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command =lambda: self.show_dialogs(1))
self.button1.grid(row=0, column=0, sticky="nsew")#, padx=10, pady=10)
self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=10, pady=10, bg="#d9a193",
font = self.fontA, command=lambda: self.show_dialogs(2))
self.button2.grid(row=0, column=1, sticky="nsew")#, padx=10, pady=10)
self.image_selected = None
def show_dialogs(self, method):
if method == 1:
ret = filedialog.askopenfilename() #filedialog.askopenfilename(initialdir='/home/user/images/')
if ret:
self.image_selected = ImageTk.PhotoImage(file = ret)
self.master.destroy()
elif method == 2:
newWin = ScreenSnip.get_snip(self.master)
ret = newWin.img
if ret:
self.image_selected = ImageTk.PhotoImage(file = ret)
def main():
root = tk.Tk()
AcquireImage(root)
root.mainloop()
if __name__ == '__main__':
main()
答案 0 :(得分:0)
此答案来自@jasonharper的评论:
private void configureSystemClockMock(final int clockJump) { AtomicInteger callCount = new AtomicInteger(); Answer<Integer> answer = invocation -> { callCount.addAndGet(1); return callCount.get() * clockJump; }; PowerMockito.mockStatic(System.class); PowerMockito.doAnswer(answer).when(System.class); System.currentTimeMillis(); }
的实例确实具有ScreenSnip
属性。但是,您永远不会创建任何此类实例。相反,你 尝试在类本身上调用mousePressEvent
,最终 为其get_snip()
参数提供了完全不合适的值。
我犯的错误在这里:
self
我尝试创建一个新对象newWin = ScreenSnip.get_snip(self.master)
,而没有将父对象放在正确的位置,同时尝试调用方法newWin
。这就是解决问题的方法:
get_snip
首先使用父级从类中创建对象newWin = ScreenSnip(self.master)
newWin.get_snip()
然后调用方法“ get_snip”