Python 重新选择包含可拖动矩形画布的顶层,如中所示。要使toplevel全屏显示:toplevel.attributes('-fullscreen',True)

Python 重新选择包含可拖动矩形画布的顶层,如中所示。要使toplevel全屏显示:toplevel.attributes('-fullscreen',True),python,tkinter,pyqt5,Python,Tkinter,Pyqt5,toplevel需要部分透明,这可以通过toplevel.attributes('-alpha',)实现。我正在使用Linux(与XFCE桌面环境一起使用),我需要添加toplevel.attributes('-type',dock'),以使透明度正常工作 所有这些都放在一个类中,给出: import sys import tkinter as tk from PIL import ImageGrab import cv2 import numpy as np class MyWidget(t

toplevel需要部分透明,这可以通过
toplevel.attributes('-alpha',)
实现。我正在使用Linux(与XFCE桌面环境一起使用),我需要添加
toplevel.attributes('-type',dock')
,以使透明度正常工作

所有这些都放在一个类中,给出:

import sys
import tkinter as tk
from PIL import ImageGrab
import cv2
import numpy as np

class MyWidget(tk.Toplevel):
    def __init__(self, master):
        super().__init__(master)
        self.configure(cursor='cross')
        if sys.platform == 'linux':
            self.attributes('-type', 'dock')  # to make transparency work in Linux
        self.attributes('-fullscreen', True)
        self.attributes('-alpha', 0.3)

        self.canvas = tk.Canvas(self, bg='white')
        self.canvas.pack(fill='both', expand=True)

        self.begin_x = 0
        self.begin_y = 0
        self.end_x = 0
        self.end_y = 0

        self.canvas.create_rectangle(0, 0, 0, 0, outline='gray', width=3, fill='blue', 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
        self.end_x = self.begin_x
        self.end_y = self.begin_y
        self.canvas.coords('snip_rect', self.begin_x, self.begin_y, self.end_x, self.end_y)

    def mouseMoveEvent(self, event):
        self.end_x = event.x
        self.end_y = event.y
        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
        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)


if __name__ == '__main__':
    root = tk.Tk()
    tk.Button(root, text='Snip', command=lambda: MyWidget(root)).pack()
    root.mainloop()
导入系统 将tkinter作为tk导入 从PIL导入ImageGrab 进口cv2 将numpy作为np导入 类MyWidget(tk.Toplevel): 定义初始(自我,主): 超级()。\uuuu初始化\uuuuu(主) self.configure(cursor='cross') 如果sys.platform==“linux”: self.attributes('-type',dock')#使透明度在Linux中工作 self.attributes('-fullscreen',True) self.attributes('-alpha',0.3) self.canvas=tk.canvas(self,bg='white') self.canvas.pack(fill='both',expand=True) self.begin_x=0 self.begin_y=0 self.end_x=0 self.end_y=0 创建矩形(0,0,0,0,outline='gray',width=3,fill='blue',tags='snip') self.canvas.bind(“”,self.mousePressEvent) self.canvas.bind(“”,self.mousemovevent) self.canvas.bind(“”,self.mouseReleaseEvent) 打印('捕获屏幕…') def鼠标压力事件(自身、事件): self.begin\u x=事件.x self.begin_y=event.y self.end\u x=self.begin\u x self.end\u y=self.begin\u y self.canvas.coords('snip_rect',self.begin_x,self.begin_y,self.end_x,self.end_y) def mouseMoveEvent(自身、事件): self.end_x=event.x self.end_y=event.y self.canvas.coords('snip_rect',self.begin_x,self.begin_y,self.end_x,self.end_y) def mouseReleaseEvent(自身,事件): 自我毁灭 self.master.update_idletasks() self.master.after(100)#留出时间刷新屏幕,以免看到屏幕截图上的蓝色框 x1=最小值(自开始、自结束) y1=最小值(自开始、自结束) x2=最大值(自开始、自结束) y2=最大值(自开始、自结束) img=ImageGrab.grab(bbox=(x1,y1,x2,y2)) self.img=cv2.cvtColor(np.array(img),cv2.COLOR\u BGR2RGB) cv2.imshow(“捕获图像”,self.img) cv2.等待键(0) 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': root=tk.tk() 按钮(root,text='Snip',command=lambda:MyWidget(root)).pack() root.mainloop()
此程序的目的是将
按钮的图像更改为选定图像或屏幕剪贴。我简化了这段代码,但它是我用图像和文本创建指令数据的大型程序的一部分。此外,对于任何试图解决/回答这一问题的人来说:我很好奇您调试问题的常用方法,特别是在您没有收到任何错误消息的情况下。混合框架很少是一个好主意。为什么您同时需要Tk和Qt?你不能只使用其中一个吗?为什么必须使用tkinter?你不应该把这些库结合起来。我对Tk&Qt还不熟悉,在用Tk编写了我的大部分工作之后,我搜索了一个屏幕捕获解决方案,并在GitHub上找到了一个适合我的程序的解决方案。我想我需要在Qt中重新编写整个内容。真倒霉
import tkinter as tk
from tkinter import filedialog
from PIL import ImageTk, Image, ImageGrab
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
import numpy as np
import cv2


class ButtonImg:

    def __init__(self, master):
        self.newWindow = None
        self.master = master
        self.fontA = ("arial", 20, "bold")

        self.canvas = tk.Canvas(height = 5)
        self.canvas.pack()

        self.button = tk.Button(bg="#61B5DA", height = 5, text = "Select Image",
                                font = self.fontA, command = self.changeImage)
        self.button.pack(fill="both")

    def changeImage(self):
        print('open second window')
        self.newWindow = tk.Toplevel(self.master)
        img = AcquireImage(self.newWindow)
        self.master.wait_window(self.newWindow)
        print('close second window')

        if img.image_selected: # check if image was selected
            self.image = img.image_selected
            self.button.configure(image=self.image, height=self.image.height())


class AcquireImage:

    def __init__(self, master):
        self.master = master
        self.fontA = ("arial", 20, "bold")

        self.frame = tk.Frame(master, bg="#96beed")
        self.frame.pack(fill="both", expand=True)

        self.button1 = tk.Button(self.frame, text="Select Image File", padx=5, pady=5, bg="#6179DA",
                              font = self.fontA, command =lambda: self.show_dialogs(1))
        self.button1.grid(row=0, column=0, sticky="nsew")

        self.button2 = tk.Button(self.frame, text="Get Screen Snip", padx=5, pady=5, bg="#6179DA",
                              font = self.fontA, command=lambda: self.show_dialogs(2))
        self.button2.grid(row=0, column=1, sticky="nsew")

        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 = MyWidget(self.master)
            newWin.show()
            ret = newWin.img
            if ret:
                self.image_selected = ImageTk.PhotoImage(file = ret)


class MyWidget(QtWidgets.QWidget):
    def __init__(self, master):
        super().__init__()
        self.master = master
        self.window = tk.Toplevel(self.master)
        screen_width = self.thirdWin.winfo_screenwidth()
        screen_height = self.thirdWin.winfo_screenheight()
        self.setGeometry(0, 0, screen_width, screen_height)
        self.setWindowTitle(' ')
        self.begin = QtCore.QPoint()
        self.end = QtCore.QPoint()
        self.img = None

        self.setWindowOpacity(0.3)
        QtWidgets.QApplication.setOverrideCursor(
            QtGui.QCursor(QtCore.Qt.CrossCursor)
        )
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        print('Capture the screen...')
        self.show()

    def getRect(self):
        # a commodity function that always return a correctly sized
        # rectangle, with normalized coordinates
        width = self.end.x() - self.begin.x()
        height = abs(width * 2 / 3)
        if self.end.y() < self.begin.y():
            height *= -1
        return QtCore.QRect(self.begin.x(), self.begin.y(),
                            width, height).normalized()

    def paintEvent(self, event):
        qp = QtGui.QPainter(self)
        qp.setPen(QtGui.QPen(QtGui.QColor('black'), 3))
        qp.setBrush(QtGui.QColor(128, 128, 255, 128))
        qp.drawRect(self.getRect())

    def mousePressEvent(self, event):
        self.begin = event.pos()
        self.end = self.begin
        self.update()

    def mouseMoveEvent(self, event):
        self.end = event.pos()
        self.update()

    def mouseReleaseEvent(self, event):
        self.close()

        rect = self.getRect()
        self.img = ImageGrab.grab(bbox=(
            rect.topLeft().x(),
            rect.topLeft().y(),
            rect.bottomRight().x(),
            rect.bottomRight().y()
        ))
        #self.img.save('capture.png')
        self.img = cv2.cvtColor(np.array(self.img), cv2.COLOR_BGR2RGB)

        cv2.imshow('Captured Image', self.img)
        cv2.waitKey(0)
        #cv2.destroyAllWindows()

if __name__ == '__main__':
    root = tk.Tk()
    app = ButtonImg(root)
    root.mainloop()
import sys
import tkinter as tk
from PIL import ImageGrab
import cv2
import numpy as np

class MyWidget(tk.Toplevel):
    def __init__(self, master):
        super().__init__(master)
        self.configure(cursor='cross')
        if sys.platform == 'linux':
            self.attributes('-type', 'dock')  # to make transparency work in Linux
        self.attributes('-fullscreen', True)
        self.attributes('-alpha', 0.3)

        self.canvas = tk.Canvas(self, bg='white')
        self.canvas.pack(fill='both', expand=True)

        self.begin_x = 0
        self.begin_y = 0
        self.end_x = 0
        self.end_y = 0

        self.canvas.create_rectangle(0, 0, 0, 0, outline='gray', width=3, fill='blue', 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
        self.end_x = self.begin_x
        self.end_y = self.begin_y
        self.canvas.coords('snip_rect', self.begin_x, self.begin_y, self.end_x, self.end_y)

    def mouseMoveEvent(self, event):
        self.end_x = event.x
        self.end_y = event.y
        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
        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)


if __name__ == '__main__':
    root = tk.Tk()
    tk.Button(root, text='Snip', command=lambda: MyWidget(root)).pack()
    root.mainloop()