AttributeError:'_tkinter.tkapp'对象没有属性'mousePressEvent'

时间:2020-08-11 18:40:06

标签: python tkinter

我遇到两个要交互的​​tkinter类时遇到麻烦。我认为这是由于我对Tk.Toplevel缺乏了解。我的代码没有创建一个全新的全屏窗口来抓屏,而是给出了一个错误:

AttributeError: '_tkinter.tkapp' object has no attribute 'mousePressEvent'

有人可以帮助我理解我代码中的父子关系层次结构吗?我并不是要任何人重写我的代码,我只是想了解我已经拥有的东西,因此我可以找出问题所在。我在SO中没有找到与多个窗口交互的多个类的许多示例-因此很难掌握继承的相互作用。

这是我认为的结构:

    • 对象:AquireImage
      • 方法:show_dialogs()
      • 对象:ScreenSnip
        • 方法:get_snip()
        • 方法:mousePressEvent()
        • 方法:mouseMoveEvent()
        • 方法:mouseReleaseEvent()

这准确吗?

代码

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()

1 个答案:

答案 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”