为了账号安全,请及时绑定邮箱和手机立即绑定

我应该用 PyQt 重写我的 Tkinter,还是相反?

我应该用 PyQt 重写我的 Tkinter,还是相反?

慕码人8056858 2023-04-25 15:49:41
我写了一个 Tkinter 应用程序,我想添加屏幕截图,所以我从GitHub (screen-snip)中找到了一个用 PyQt 编写的单独程序,我正在导入并在我的 Tkinter 应用程序中使用它。然后我决定合并这些程序,以便提出一个关于为什么它们不能完全协同工作的问题。我学会了不要将 Tk 和 Qt 结合起来。所以现在我的问题是,我应该用 Qt 还是 Tk 重写我的程序?这种情况哪个更好?当您选择一个图像文件时,我当前的混合 Tk/Qt 程序可以工作,但现在 Qt 的屏幕截图部分会class MyWidget(QtWidgets.QWidget):导致它冻结然后崩溃。我认为问题可能是将 Qt 与 Tk 混合使用的结果,但我不确定。我最初有两个运行的 tkinter 实例,这让我可以用一个新窗口来显示屏幕,但导致窗口出现问题button,所以我通过尝试使用来替换它tk.Toplevelclass MyWidget(QtWidgets.QWidget):    def __init__(self, master):        super().__init__()        self.master = master        self.window = tk.Toplevel(self.master)那是我遇到麻烦的时候。该小部件根本不再工作,并且程序在没有任何线索或错误的情况下崩溃。知道为什么吗?
查看完整描述

1 回答

?
SMILET

TA贡献1796条经验 获得超4个赞

如评论中所述,最好是使用单个 GUI 工具包,因此您需要为 Qt 重写代码或使用 tkinter 重写剪切代码。我不太了解 Qt,所以我无法帮助您选择第一个选项。然而,屏幕截图实际上是使用 PIL 截取的,而不是某些 Qt 特定方法,因此可以在 tkinter 中重写截图代码。

您所需要的只是一个包含带有可拖动矩形的画布的全屏顶层,就像在Tkinter 中使用鼠标事件绘制矩形一样。使顶层全屏:toplevel.attributes('-fullscreen', True)

顶层需要部分透明,这可以通过toplevel.attributes('-alpha', <value>). 我正在使用 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()


查看完整回答
反对 回复 2023-04-25
  • 1 回答
  • 0 关注
  • 250 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信