我可以让倒计时窗口显示下次暂停的时间吗?

我可以让倒计时窗口显示下次暂停的时间吗?

偶尔当我需要去某个地方时,我会让我的计算机不处于挂起状态,但我会把它留给我绝对信任的人,而且我很快就会回来,所以没有必要挂起计算机(比如,如果是家人,我只是想去趟厕所,离我住的地方只有一小段距离,你知道,在这种情况下总是挂起我的机器并不方便),或者可能有其他原因我想要这样做,比如我想知道我是否应该在机器进入睡眠状态之前跑到机器旁边摇动鼠标,或者我是否可以以较慢的速度使用计算机。

无论如何,说到点子上,我希望能够启动一个倒计时(最好是一个透明的(透明部分不是必须的)窗口,位于屏幕右上角顶部栏下方的所有内容之上)显示,它将向我显示下一次暂停时间的倒计时。

这可以在我每次与机器交互时重置计时器,或者以某种方式直接与挂起系统交互以告知下一次挂起的时间(因为我假设存在某种倒计时)。如何实现这样的功能(当然,我不希望窗口始终打开,而是希望我能够随时运行命令来启动窗口,或者它甚至可以是终端窗口中的倒计时,我只需移动它,或者如果 GUI 位有问题,它会自动位于右上角)?

我正在运行带有 GNOME 3.18 的 Ubuntu GNOME 15.10,但该解决方案也适用于带有 GNOME 3.20 的 Ubuntu GNOME 16.04,因为我计划很快升级。

答案1

编辑

在原来的答案中,在下面,出现了倒计时窗口在任意空闲时间之后。重新阅读你的问题,你可能想要永久保留它。永久版本如下(更简单),原始答案在下面。


1a. 版本,永久显示倒计时时间

解决方案是一个背景脚本,显示一个半透明的倒计时窗口。该窗口的行为类似于通知:它始终显示在顶部,但(当然)您可以像往常一样在其他窗口中工作:

在此处输入图片描述在此处输入图片描述 在此处输入图片描述在此处输入图片描述

初始时间是激活挂起之前的空闲时间。鼠标键盘事件会重置该时间。

如图所示,该脚本带有不同的预设颜色选项(见下文)。

如何设置

  1. 该脚本需要xprintidle

    sudo apt-get install xprintidle
    
  2. 将以下脚本复制到一个空文件中,并将其另存为countdown.py
  3. 使用空闲时间作为参数来运行它:

    python3 /path/to/countdown.py <idle_time>
    

    例如

    python3 /path/to/countdown.py 300
    

    5分钟后进入暂停状态。

  4. 如果一切正常,请将其添加到启动应用程序:Dash > 启动应用程序 > 添加。添加命令:

     /path/to/runner.py <idle_time>
    

剧本

#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GObject, Pango
from threading import Thread
import subprocess
import time
import signal
import sys
import os

# --- set the color (index) below (1 is the first)
color = 1
# ---
textcolors = ["grey", "orange", "green", "blue", "white"]
# --- don't change anything below
txtcolor = textcolors[color-1]

countdown = int(sys.argv[1])
susp = os.path.dirname(os.path.realpath(__file__))+"/susp.sh"

class CountDown(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self)
        maingrid = Gtk.Grid()
        self.add(maingrid)
        maingrid.set_border_width(40)
        # set initial text for the spash window
        self.label = Gtk.Label(convert_seconds(countdown))
        self.label.modify_font(Pango.FontDescription('Ubuntu 22'))
        self.label.set_width_chars(10) 
        maingrid.attach(self.label, 0, 0, 1, 1)
        self.update = Thread(target=self.start_countdown, args=[countdown])
        # daemonize the thread
        self.update.setDaemon(True)
        self.update.start()

    def start_countdown(self, countdown):
        idle1 = idletime()
        t = countdown
        while True:
            time.sleep(1)
            idle2 = idletime()
            if idle2 < idle1:
                t = countdown
            else:
                t -= 1
            if t <= 0:
                subprocess.Popen(["systemctl", "suspend"])
            GObject.idle_add(self.label.set_text, convert_seconds(t),
                priority=GObject.PRIORITY_DEFAULT)
            idle1 = idle2

    def stop(self):
        Gtk.main_quit()

def get_screen():
    scr = [s.split("x") for s in subprocess.check_output([
        "xrandr"]).decode("utf-8").split() if "+0+0" in s][0]
    return int(scr[0]) - 300

def convert_seconds(sec):
    timedisplay = [
        str(int(sec/3600)),
        str(int((sec % 3600)/60)),
        str(int(sec % 60)),
        ]
    for i, n in enumerate(timedisplay):
        if len(n) == 1:
            timedisplay[i] = "0"+n
    return ":".join(timedisplay)

def idletime():
    return int(subprocess.check_output(
        "xprintidle"
        ).decode("utf-8").strip())/1000

def splashwindow():
    window = CountDown()
    window.set_decorated(False)
    window.set_resizable(False)
    window.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0,0,0,1))
    window.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse(txtcolor))
    window.set_opacity(0.6)
    window.move(get_screen(), 80)
    window.set_keep_above(True)
    window.show_all()
    Gtk.main()

GObject.threads_init()
splashwindow()

笔记

可以更改文本颜色,如答案第二版最底部所述。

1b. 根据评论中的要求:同一脚本的豪华版本:如果时间过去了一半,文本颜色将变为黄色,在暂停前 30 秒变为红色。

在此处输入图片描述>在此处输入图片描述>在此处输入图片描述

用法与 完全相同1a

剧本

#!/usr/bin/env python3
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GObject, Pango
from threading import Thread
import subprocess
import time
import signal
import sys
import os

# --- set the color (index) below (1 is the first)
color = 1
# ---
textcolors = ["grey", "orange", "green", "blue", "white", "yellow", "red"]
# --- don't change anything below

txtcolor = textcolors[color-1]
al_cl1 = textcolors[5]; al_cl2 = textcolors[6]
countdown = int(sys.argv[1])
alarm1 = int(countdown/2)
alarm2 = 30

class CountDown(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self)
        maingrid = Gtk.Grid()
        self.add(maingrid)
        maingrid.set_border_width(40)
        # set initial text for the spash window
        self.label = Gtk.Label(convert_seconds(countdown))
        self.label.modify_font(Pango.FontDescription('Ubuntu 22'))
        self.label.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse(txtcolor))
        self.label.set_width_chars(10) 
        maingrid.attach(self.label, 0, 0, 1, 1)
        self.update = Thread(target=self.start_countdown, args=[countdown])
        # daemonize the thread
        self.update.setDaemon(True)
        self.update.start()

    def mod_color(self, color):
        self.label.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse(color))

    def start_countdown(self, countdown):
        idle1 = idletime()
        t1 = countdown
        t2 = countdown
        while True:
            time.sleep(1)
            idle2 = idletime()
            if idle2 < idle1:
                t2 = countdown
                if t1 <= alarm1:
                    # print("change textcolor default")
                    GObject.idle_add(self.mod_color, txtcolor,
                        priority=GObject.PRIORITY_DEFAULT)
            else:
                t2 -= 1
            if all([t2 <= alarm2, t1 > alarm2]):
                # print("change textcolor red")
                GObject.idle_add(self.mod_color, al_cl2,          
                    priority=GObject.PRIORITY_DEFAULT)
            elif all([t2 <= alarm1, t1 > alarm1]):
                # print("change textcolor yellow")
                GObject.idle_add(self.mod_color, al_cl1,          
                    priority=GObject.PRIORITY_DEFAULT) 
            if t2 <= 0:
                subprocess.Popen(["systemctl", "suspend"])
            GObject.idle_add(self.label.set_text, convert_seconds(t2),
                priority=GObject.PRIORITY_DEFAULT)
            idle1 = idle2
            t1 = t2

    def stop(self):
        Gtk.main_quit()

def get_screen():
    scr = [s.split("x") for s in subprocess.check_output([
        "xrandr"]).decode("utf-8").split() if "+0+0" in s][0]
    return int(scr[0]) - 300

def convert_seconds(sec):
    timedisplay = [
        str(int(sec/3600)),
        str(int((sec % 3600)/60)),
        str(int(sec % 60)),
        ]
    for i, n in enumerate(timedisplay):
        if len(n) == 1:
            timedisplay[i] = "0"+n
    return ":".join(timedisplay)

def idletime():
    return int(subprocess.check_output(
        "xprintidle"
        ).decode("utf-8").strip())/1000

def splashwindow():
    window = CountDown()
    window.set_decorated(False)
    window.set_resizable(False)
    window.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0,0,0,1))
    window.set_opacity(0.6)
    window.move(get_screen(), 80)
    window.set_keep_above(True)
    window.show_all()
    Gtk.main()

GObject.threads_init()
splashwindow()




2. 原答案:版本,空闲x时间后显示倒计时

以下设置将显示下次暂停的倒计时(在任意时间长度内):

在此处输入图片描述

窗口是总是位于所有其他窗口的顶部,与通知气泡完全一样。

该设置取代了“正常”挂起设置,这意味着您需要从系统设置中禁用挂起。

关于解决方案

脚本中暂停的命令是:

 systemctl suspend

不需要sudo。结果是你需要至少 15.04使用此解决方案。
该脚本是在Ubuntu(Unity)上编写和测试的15.10,但其中没有特定于 Unity 的代码。我认为它在所有默认的 Ubuntu 版本上都能正常工作 >15.04

怎么运行的

要进行设置(下面有详细版本),只需将涉及的三个脚本复制到同一个目录中,并按指示准确命名。要运行,只需运行主脚本(运行时间检查)。

  • 如果空闲时间超过某个限制,则会调用倒计时窗口。
  • 如果在倒计时期间计算机变为非空闲状态(鼠标或键盘事件),则窗口将关闭(其 pid 被终止)。
  • 如果计时器已结束倒计时,它会运行一个简单的脚本来暂停

如何设置

  1. 该脚本需要xprintidle

    sudo apt-get install xprintidle
    
  2. 将以下三个脚本复制到单独的空文件中,保存在同一个目录,确切名称如下:

    A. 保存(准确)为win.py

    #!/usr/bin/env python3
    import gi
    gi.require_version('Gtk', '3.0')
    from gi.repository import Gtk, Gdk, GObject, Pango
    from threading import Thread
    import subprocess
    import time
    import signal
    import sys
    import os
    
    # --- set the color (index) below (1 is the first)
    color = 1
    # ---
    textcolors = ["grey", "orange", "green", "blue", "white"]
    # --- don't change anything below
    txtcolor = textcolors[color-1]
    
    countdown = int(sys.argv[1])
    susp = os.path.dirname(os.path.realpath(__file__))+"/susp.sh"
    
    class CountDown(Gtk.Window):
    
        def __init__(self):
            Gtk.Window.__init__(self)
            maingrid = Gtk.Grid()
            self.add(maingrid)
            maingrid.set_border_width(40)
            # set initial text for the spash window
            self.label = Gtk.Label(convert_seconds(countdown))
            self.label.modify_font(Pango.FontDescription('Ubuntu 22'))
            self.label.set_width_chars(10) 
            maingrid.attach(self.label, 0, 0, 1, 1)
            self.update = Thread(target=self.start_countdown, args=[countdown])
            # daemonize the thread
            self.update.setDaemon(True)
            self.update.start()
    
        def start_countdown(self, countdown):
            t = countdown
            while t > 0:
                time.sleep(1)
                t -= 1
                GObject.idle_add(self.label.set_text, convert_seconds(t),
                    priority=GObject.PRIORITY_DEFAULT)
                print(t)
            subprocess.Popen(["/bin/bash", susp])
            self.stop()
    
        def stop(self):
            Gtk.main_quit()
    
    def get_screen():
        scr = [s.split("x") for s in subprocess.check_output([
            "xrandr"]).decode("utf-8").split() if "+0+0" in s][0]
        return int(scr[0]) - 300
    
    def convert_seconds(sec):
        timedisplay = [
            str(int(sec/3600)),
            str(int((sec % 3600)/60)),
            str(int(sec % 60)),
            ]
        for i, n in enumerate(timedisplay):
            if len(n) == 1:
                timedisplay[i] = "0"+n
        return ":".join(timedisplay)
    
    def splashwindow():
        window = CountDown()
        window.set_decorated(False)
        window.set_resizable(False)
        window.override_background_color(Gtk.StateType.NORMAL, Gdk.RGBA(0,0,0,1))
        window.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse(txtcolor))
        window.set_opacity(0.6)
        window.move(get_screen(), 80)
        window.set_keep_above(True)
        window.show_all()
        Gtk.main()
    
    GObject.threads_init()
    splashwindow()
    

    B. 保存为runner.py

    #!/usr/bin/env python3
    import subprocess
    import time
    import os
    import sys
    
    window_mod = os.path.dirname(os.path.realpath(__file__))+"/win.py" 
    
    suspend = int(sys.argv[1])
    countdown = int(sys.argv[2])
    
    w = False
    while True:  
        time.sleep(1)
        idletime = int(subprocess.check_output(
            "xprintidle"
            ).decode("utf-8").strip())/1000
        if all([idletime > suspend-countdown, w == False]):
            subprocess.Popen(["python3", window_mod, str(countdown)])
            w = True
        elif all([idletime < suspend-countdown, w == True]):
            try:
                procdata = subprocess.check_output([
                    "pgrep", "-f", window_mod
                    ]).decode("utf-8").strip()
                procs = procdata.splitlines()
            except subprocess.CalledProcessError:
                pass
            else:
                for p in procs:
                    subprocess.Popen(["kill", p])
            w = False
    

    C. 保存(准确)为susp.sh

    #!/bin/bash
    
    sleep 3
    systemctl suspend
    
  3. 使所有三个脚本可执行,并再次确保它们位于同一个目录中。

  4. 你实际上已经完成了。

    • 禁用“常用”暂停设置
    • 测试运行脚本的挂起时间(应应用挂起之前的空闲时间)和倒计时时间(以秒为单位)作为参数,例如:

      /path/to/runner.py 600 300
      

      将空闲时间设置为 10 分钟,计数器在挂起前 5 分钟启动。

  5. 如果一切正常,请将其添加到启动应用程序:Dash > 启动应用程序 > 添加。添加命令:

     /path/to/runner.py <idle_time> <countdown_time>
    

笔记

  1. 在的头部部分win.py,您可以为显示的文本设置不同的颜色:

    # --- set the color (index) below (1 is the first)
    color = 1
    # ---
    textcolors = ["grey", "orange", "green", "blue", "white"]
    
  2. 玩弄这些行中的值:

    maingrid.set_border_width(10)
    

    return int(scr[0]) - 200 
    

    (来自函数get_screen,其中 200 是窗口左侧到屏幕右侧的距离),并且

    window.move(get_screen(), 35)
    

    (其中 35 是窗口和屏幕顶部之间的距离),您可以轻松更改窗口的几何形状,例如:

    在此处输入图片描述

玩得开心 :)

答案2

你可以安装一个程序xprintidle来给你提供计算机的空闲时间,但你必须想出某种脚本来在屏幕上显示它

我不擅长编写脚本,所以这是我能想到的所有帮助...希望它能给你一个起点。

相关内容