linux怎么截图,小窗口那种

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux怎么截图,小窗口那种相关的知识,希望对你有一定的参考价值。

如果是有虚拟机的话,可以用windows下的截图工具,比如qq截图之类。
linux 下 要是小窗口截图就只能装截图工具了 推荐一款小巧好用的截图工具scrot
scrot使用方法如下 :
一 快捷使用方法:
安装后输入命令 scrot -s rectangle.png 然后拖动鼠标画矩形框,矩形框内的图像会被截取出来,并保存至当前目录下的rectangle.png中。

二 详细使用方法:

1.安装,想安装其他软件一样,Fedora redhat下用 yum install scrot , Ubuntu下apt-get install scrot就可以了。
  2.使用一般用法就一般而言,使用 scrot 可以抓取整个桌面、某个指定的窗口、以及选择的矩形区域。
  抓取桌面:scrot desktop.png,该命令将当前的整个桌面抓取下来,并保存为 desktop.png 文件。可以在当前的目录中找到此图像文件。
  抓取窗口:scrot -bs window.png,选项 b 使 scrot 在抓取窗口时一同将外边框抓取下来,而 s 选项则让用户选择所要抓取的是何窗口。
  抓取区域:scrot -s rectangle.png,在执行此命令后,使用鼠标拖曳的矩形区域将被 scrot 抓取下来。
  高级使用对于普通的抓取使用 scrot 的基础便足以应付了。但在某些特殊情况之下,使用 scrot 抓取图像需要讲究一些技巧。
  延时抓取:scrot -cd 10 menu.png,此命令中的 d 选项用于延时抓取图像,其后的 10 代表延时 10 秒;前面的选项 c 显示倒计时。在抓取菜单或是命令提示时,该技巧将充分展示其魔力。
  生成缩图:scrot -t 50% thumb.png,这个命令在抓取图像的同时生成该图像的缩略图。选项 t 将打开此功能,其后的 50% 为原图的缩放百分比。
  更改品质:scrot -q 70 quality.jpg,此命令中的 q 选项用于更改所抓图像的品质,其数值介于 1-100 之间,默认为 75。数值越大,意味着图像品质越高;同时,图像的压缩率也就越低,占用空间越大。
  操作抓图:scrot action.png -e ‘mv $f ~/images/’,该命令将抓取的图像移动到 ~/images/ 目录。显然,操作图像的功能由 e 选项开启,其中的 $f 代表原图的路径/文件名。
  以上示例皆指定了需要保存的抓图的文件名称。实际上,如果不指定名称,那么 scrot 在抓取图像后会自动使用当前的日期时间、宽度高度的组合来生成文件名称。
参考技术A scrot安装下下,命令行使用
也可以用linuxdeepin封装过的有图形界面的scrot
其他gnome应该可以用PrtScn直接弄的,某些版本
参考技术B print screen 键 然后保存就行

即使窗口重叠,如何在 Qt(Python、Linux)中截取特定窗口的屏幕截图?

【中文标题】即使窗口重叠,如何在 Qt(Python、Linux)中截取特定窗口的屏幕截图?【英文标题】:How do I take a screenshot of a specfic window in Qt (Python, Linux), even if the windows are overlapped? 【发布时间】:2020-03-15 11:48:48 【问题描述】:

我正在尝试截取 PyQt5 中当前活动窗口的屏幕截图。我知道截取任何窗口的通用方法是QScreen::grabWindow(winID),其中winID 是implementation-specific ID depending on the window system。由于我正在运行 X 和 KDE,我计划最终使用 CTypes 来调用 Xlib,但现在我只是执行“xdotool getactivewindow”来获取 shell 中的 windowID。

举个例子,我用 QTimer 创建了一个 QMainWindow。当计时器被触发时,我通过执行“xdotool getactivewindow”来识别活动窗口ID,获取它的返回值,调用grabWindow() 来捕获活动窗口,并在QLabel 中显示屏幕截图。在启动时,我还将我的窗口设置为固定的 500x500 大小以供观察,并激活Qt.WindowStaysOnTopHint 标志,以便我的窗口在未聚焦时仍然可见。把它们放在一起,实现是下面的代码。

from PyQt5 import QtCore, QtGui, QtWidgets
import subprocess


class ScreenCapture(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
        self.setFixedHeight(500)
        self.setFixedWidth(500)

        self.label = QtWidgets.QLabel(self)

        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(500)
        self.timer.timeout.connect(self.timer_handler)
        self.timer.start()

        self.screen = QtWidgets.QApplication.primaryScreen()

    @QtCore.pyqtSlot()
    def timer_handler(self):
        window = int(subprocess.check_output(["xdotool", "getactivewindow"]).decode("ascii"))
        self.screenshot = self.screen.grabWindow(window)

        self.label.setPixmap(self.screenshot)
        self.label.setFixedSize(self.screenshot.size())


if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    window = ScreenCapture()
    window.show()
    app.exec()

为了测试实现,我启动了脚本并单击了另一个窗口。如果我的应用程序窗口和活动窗口之间没有重叠,它似乎可以正常工作。 See the following screenshot, when Firefox (right) is selected, my application is able to capture the active window of Firefox and display it in the QLabel.

但是,如果应用程序窗口和活动窗口之间存在重叠,则屏幕截图不会按预期工作。应用程序本身的窗口将被捕获,并创建一个积极的反馈。

如果应用程序窗口和活动窗口之间存在重叠。应用程序本身的窗口将被捕获,并创建一个积极的反馈。

我已经在 KDE 的设置中禁用了 3D 合成,但问题仍然存在。上述示例是在禁用所有复合效果的情况下拍摄的。

问题

    当应用程序窗口和活动窗口重叠时,为什么这个实现不能正常工作?我怀疑这是由图形系统(Qt 工具包、窗口管理器、X 等)之间某些形式的不需要的交互引起的问题,但我不确定。

    是否有可能解决这个问题? (注意:我知道我可以在截图之前hide(),然后再show(),但这并不能真正解决这个问题,即使存在重叠也会截图。)

【问题讨论】:

我认为现象是这样的:grabWindow 不记录到窗口而是记录到窗口占据的区域,在重叠的情况下你看到的效果和使用镜像一样另一面镜子:无限递归。 @eyllanesc 同意。我最初认为这个问题是由复合窗口管理器造成的,但就像你所说的那样,我重新检查了文档,是的,“grabWindow() 函数从屏幕上抓取像素,而不是从窗口中,即如果有是另一个窗口部分或完全覆盖您抓取的窗口,您也会从覆盖的窗口中获取像素。”,因此使用grabWindow()从一开始就注定要失败,看来我需要在较低级别进行编程才能获得“真正的”窗口,Qt 太高级了,无法完成这项工作...... 【参考方案1】:

正如@eyllanesc 所指出的,在Qt 中似乎不可能做到这一点,至少不能用QScreen::grabWindow,因为grabWindow() 实际上并没有抓住窗口本身,而只是占据了由窗户。 The documentation 包含以下警告。

grabWindow() 函数从屏幕而不是窗口中抓取像素,即,如果在您抓取的窗口上部分或全部有另一个窗口,您也会从覆盖的窗口中获取像素。鼠标光标一般不会被抓取。

结论是在纯 Qt 中不可能做到这一点。只有编写低级 X 程序才能实现这样的功能。由于该问题要求“在 Qt 中”提供解决方案,因此任何可能涉及更深层次的低级 X 解决方案的答案都超出了范围。此问题可以标记为已解决。

这里要吸取的教训:始终在使用函数或方法之前检查文档。


更新:我设法通过 Xlib 直接从 X 读取窗口来解决问题。有点讽刺的是,我的解决方案使用 GTK 抓取窗口并将其结果发送到 Qt... 无论如何,如果您不想使用 GTK,您可以直接使用 Xlib 编写相同的程序,但我使用 GTK 因为 Xlib 相关GDK 中的函数非常方便地演示基本概念。

为了获取屏幕截图,我们首先将窗口 ID 转换为适合在 GDK 中使用的GdkWindow,然后调用Gdk.pixbuf_get_from_window() 来抓取窗口并将其存储在gdk_pixbuf 中。最后,我们调用save_to_bufferv() 将原始pixbuf 转换为合适的图像格式并将其存储在缓冲区中。此时,缓冲区中的图像适合在任何程序中使用,包括Qt。

文档包含以下警告:

如果窗口不在屏幕上,则在被遮蔽/屏幕外区域中没有图像数据要放置在 pixbuf 中。与屏幕外区域对应的 pixbuf 部分的内容未定义。

如果您从中获取数据的窗口被其他窗口部分遮挡,则对应遮挡区域的 pixbuf 区域的内容未定义。

如果窗口没有被映射(通常是因为它被图标化/最小化或不在当前工作区上),那么将返回 NULL。

如果不能为返回值分配内存,则返回NULL。

还有一些关于合成的说明,

gdk_display_supports_composite 自 3.16 版以来已被弃用,不应在新编写的代码中使用。

合成是一种过时的技术,只能在 X11 上使用。

所以基本上,只能在 X11 下抓取一个部分被遮挡的窗口(在 Wayland 中不可能!),使用合成窗口管理器。我在没有合成的情况下对其进行了测试,发现禁用合成时窗口变黑了。但是,当启用合成时,它似乎可以正常工作。它可能适用于您的应用程序,也可能不适用于您的应用程序。但我认为如果你在 X11 下使用合成,它可能会起作用。

from PyQt5 import QtCore, QtGui, QtWidgets
import subprocess


class ScreenCapture(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowFlags(self.windowFlags() | QtCore.Qt.WindowStaysOnTopHint)
        self.setFixedHeight(500)
        self.setFixedWidth(500)

        self.label = QtWidgets.QLabel(self)
        self.screen = QtWidgets.QApplication.primaryScreen()

        self.timer = QtCore.QTimer(self)
        self.timer.setInterval(500)
        self.timer.timeout.connect(self.timer_handler)
        self.timer.start()

    @staticmethod
    def grab_screenshot():
        from gi.repository import Gdk, GdkX11

        window_id = int(subprocess.check_output(["xdotool", "getactivewindow"]).decode("ascii"))

        display = GdkX11.X11Display.get_default()
        window = GdkX11.X11Window.foreign_new_for_display(display, window_id)

        x, y, width, height = window.get_geometry()
        pb = Gdk.pixbuf_get_from_window(window, 0, 0, width, height)

        if pb:
            buf = pb.save_to_bufferv("bmp", (), ())
            return buf[1]
        else:
            return

    @QtCore.pyqtSlot()
    def timer_handler(self):
        screenshot = self.grab_screenshot()
        self.pixmap = QtGui.QPixmap()
        if not self.pixmap:
            return

        self.pixmap.loadFromData(screenshot)
        self.label.setPixmap(self.pixmap)
        self.label.setFixedSize(self.pixmap.size())
        

if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    window = ScreenCapture()
    window.show()
    app.exec()

现在它可以完美地捕捉一个活动窗口,即使上面有重叠的窗口。

【讨论】:

以上是关于linux怎么截图,小窗口那种的主要内容,如果未能解决你的问题,请参考以下文章

当程序成为前台窗口时,我的代码会截取程序的屏幕截图。屏幕截图的时间出现了一个小问题

电脑怎么窗口截屏

苹果电脑长截图怎么弄的

如何保存QQ里别人发的闪照,不可以截图

即使窗口重叠,如何在 Qt(Python、Linux)中截取特定窗口的屏幕截图?

delphi+被完全遮挡的窗口如何截图保存?