Kivy:如何创建透明背景/画布,使按钮看起来漂浮在桌面上

2024-01-28

我正在尝试创建一个在单板计算机(特别是使用 armbian 的 OrangePi One/PC)上运行的视频播放应用程序。我在使用 ffpyplayer(kivy 使用的视频播放器)创建流畅的视频时遇到问题。

因此,我决定简单地运行在视频前面生成按钮控件的应用程序,并尝试使应用程序的背景清晰,以便视频和 kivy 按钮都可见。正如链接帖子中的建议:Kivy 视频播放器无法在 Raspberry 3B+ 上运行 https://stackoverflow.com/questions/51601976/kivy-video-player-is-not-working-on-raspberry-3b

我在以下地方看到过类似的事情:https://github.com/kivy/kivy/pull/5252 https://github.com/kivy/kivy/pull/5252我在上传到单板计算机之前在 Windows 计算机上测试程序,但无法成功创建空白背景。我主要尝试修改 .kv 文件,但是我找不到任何可以调整以创建所需结果的设置。

为了简单起见,我上传了一个较短的代码,其布局与我的主代码完全相同:

Kivy代码:my.kv

#:kivy 1.0 
<MyGrid>

    background_color: 0, 0, 0, 0 # only creates a black colour
    #opacity: 0.5 #just affects the widgets not the background

    canvas.before:
        Color:
            rgba: 0, 0, 0, 1
        Rectangle:
            pos: self.pos
            size: self.size


    #variable name: ID
    name: name #declare global variables
    email: email 

    GridLayout:
        cols:1
        size: root.width-200, root.height-200 #make the widget fit the screen and then minus a border from it
        pos: 100, 100 #offset the position to compensate for the boarder

        GridLayout: 
            cols: 2

            Label:
                text: "Name: "

            TextInput:
                id: name
                multiline:False

            Label:
                text: "email: "

            TextInput:
                id: email 
                multiline: False

        Button:
            text: "submit"
            on_press: root.btn() #if there was an event. ie button was pressed

Python代码:

    import kivy
    from kivy.app import App 
    from kivy.uix.label import Label
    from kivy.uix.gridlayout import GridLayout
    from kivy.uix.textinput import TextInput
    from kivy.network.urlrequest import UrlRequest
    from kivy.uix.boxlayout import BoxLayout
    from kivy.uix.button import Button
    from kivy.uix.widget import Widget
    from kivy.properties import ObjectProperty
    from kivy.core.window import Window
    
    class MyGrid(Widget): #creates apps layout and contents
            #declaire global variables to pass to and from .kv file. note the variables names must be the same between the 2 files 
            name = ObjectProperty(None) #initialise as none and then after reading the .kv file it will populate it 
            email = ObjectProperty(None)
            
            def btn(self): #function btn which occurs. it needs to be in here 
                print ("name: ", self.name.text, " email: ", self.email.text)
                self.name.text = ""
                self.email.text = ""
    
    class MyApp(App): #creates the app
        def build(self):
            return MyGrid()
    
    if __name__ == '__main__': #runs the app 
      

  MyApp().run()

所附照片显示了使用 ffpyplayer 与视频一起运行的应用程序,或多或少是最终目标。目标是绿色将成为桌面。示例图片 https://i.stack.imgur.com/7832o.jpg.

任何指导将不胜感激!


只是为了回答我的问题,以防有人遇到类似的问题。

事实证明使用Kivynot对我来说可行有两个原因:

  1. 虽然可以像示例中那样使 kivy 应用程序透明https://github.com/kivy/kivy/pull/5252 https://github.com/kivy/kivy/pull/5252它需要一个模板图像来完成。由于我希望我的应用程序在不同尺寸的屏幕上运行,并且我对生成图像一无所知,因此我决定不使用此方法。

  2. 将按钮应用程序缩小,使其仅覆盖视频的一部分,效果很好。这变得有问题,因为视频使用另一个程序运行,这意味着视频将在应用程序前面打开,并且我会失去控制,直到我专门单击该应用程序。在 Windows 上可以通过启动视频然后延迟生成按钮或在创建视频屏幕后最小化并重新打开应用程序来克服此问题。不幸的是,这种方法并没有转化为单板计算机,以最大化视频播放性能我没有使用桌面环境,只使用X Window系统(X11),即使使用基本的窗口管理器,我也遇到了很多最小化和最大化的困难视窗。

我的解决方案是转向 Tkinter,因为它能够强制窗口位于前面并且可以使其透明。下面是 Tkinter 中的等效代码,虽然它尚未完成,但它具有我在原始问题中提到的功能:

from functools import partial
import tkinter as tk
import threading
import time
import vlc
global videoscreen_button_num
videoscreen_button_num = 0

global button_timer
global show_button
button_timer = 0
show_button = False


class video_window:
    def __init__(self, master, channel): #create the windows
    self.master = master
    self.frame = tk.Frame(self.master)

    reset_encoder = tk.Button(self.frame, text = 'Reset Encoder', width = 25, command = self.close_windows) #create buttons to control the video
    reset_video = tk.Button(self.frame, text = 'Refresh Video', width = 25, command = self.close_windows)
    return_button = tk.Button(self.frame, text = 'Return to Main Menu', width = 25, command = self.close_windows)

    return_button.grid(row=0, column=0)
    reset_video.grid(row=0, column=1)
    reset_encoder.grid(row=0, column=2)

    unselected_colour = "SteelBlue1" 
    selected_colour = "RoyalBlue1"

    return_button.config(background = selected_colour)
    reset_video.config(background = unselected_colour)
    reset_encoder.config(background = unselected_colour)

    self.frame.pack()

    self.video_button_ids = [] 
    self.video_button_ids.append(reset_encoder)
    self.video_button_ids.append(reset_video)
    self.video_button_ids.append(return_button)

    Instance = vlc.Instance() #'--verbose 2'.split())
    self.player = Instance.media_player_new()
    Media = Instance.media_new(channel)
    Media.get_mrl()
    self.player.set_media(Media)
    #player.set_fullscreen(False)
    self.player.play()
    self.player.set_fullscreen(True)

    master.attributes('-topmost', 'true') #force the window to be infront 

    time.sleep(5) #give player time to load before spawning the control buttons

    master.bind('<Key>', partial(self.press_button) )

    master.mainloop()

    self.timed_opacity_thread = threading.Thread(target=self.timed_opacity) #make a thread which manage when the opacity of the buttons will turn on and off
    self.timed_opacity_thread.start()

def press_button(self, event): #tells the program what to do if a button is pressed 
    print("pressed button in video screen")

    if show_button == True: #if the opacity is set to be visable simple extend the time 
        global button_timer
        button_timer = time.perf_counter()
    else: # if the opacity is off turn it back on and place it into a thread to that other tasks can be performed at the same time.
        self.timed_opacity_thread = threading.Thread(target=self.timed_opacity)
        self.timed_opacity_thread.start()

    global videoscreen_button_num
    old_button_num = videoscreen_button_num
    print("button pressed", event.keycode)
    if event.keycode == 40 : #up button
        if videoscreen_button_num == 2:
            videoscreen_button_num = 0
        else:
            videoscreen_button_num = videoscreen_button_num + 1

    if event.keycode == 38 : #down
        if videoscreen_button_num == 0 :
            videoscreen_button_num = 2
        else:
            videoscreen_button_num = videoscreen_button_num - 1
        
    if event.keycode == 37: #right
        if videoscreen_button_num == 2:
            videoscreen_button_num = 0
        else:
            videoscreen_button_num = videoscreen_button_num + 1 

    if event.keycode == 39 : #left
        if videoscreen_button_num == 0 :
            videoscreen_button_num = 2
        else:
            videoscreen_button_num = videoscreen_button_num - 1    
    
    if event.keycode == 13: #enter
        print("pressed enter")
        self.video_button_ids[videoscreen_button_num].invoke()

    print("old button = ", old_button_num)
    print ("new button = ", videoscreen_button_num)

    print ("old object = ", self.video_button_ids[old_button_num])
    print ("new object = ", self.video_button_ids[videoscreen_button_num])

    unselected_colour = "SteelBlue1" 
    selected_colour = "RoyalBlue1"

    self.video_button_ids[old_button_num].config(background = unselected_colour)
    self.video_button_ids[videoscreen_button_num].config(background = selected_colour)

    print("")

def timed_opacity(self): #make the buttons fade when no user input is detected for a while and then reappear when a user input is detected
    self.master.attributes('-alpha', 1)
    
    global button_timer 
    global show_button
    button_timer = time.perf_counter()
    show_button = True
    while time.perf_counter() - button_timer < 10:
        pass

    self.master.attributes('-alpha', .5)
    show_button = False

def close_windows(self):
    self.player.stop()
    global show_button 

    self.master.destroy() #get rid of window, app still runs, not sure how to kill app 
    
def refresh_video(self):
    print("refresh video funtion")
    self.player.Refresh()

def main(): 
    root = tk.Tk()
    app = video_window(root, 'rtsp://192.168.8.20/4') #the location of the video you wish to play
    root.mainloop()

if __name__ == '__main__':
    main()

希望这可以帮助别人

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kivy:如何创建透明背景/画布,使按钮看起来漂浮在桌面上 的相关文章

随机推荐

  • 使用未在 swagger 中公开的 HTTP 内容上传 API 文件

    我正在将 swagger 接口实现到现有的 Web API 中 当前的 API 控制器公开了一个异步上传函数 该函数使用Request Content异步传输图像 已使用的代码在中进行了解释this http www c sharpcorn
  • 如何在UIButton中实现两个IBAction而不重叠?

    I drag 2 IBA行动 from a UIButton 第一个是 touchDown 事件 第二个是拖动 Inside IBAction clickButton UIButton sender NSLog Click Button I
  • Rabbitmq-设计消息重放服务

    我正在尝试设计一种重播机制 使用户能够重播队列中的消息 对于包含多个队列和多个消费者的交换器 我提出的最佳设计是 创建一个记录器服务 它将 创建一个队列并将所有路由键绑定到它 消耗来自交换器的所有消息 将所有消息保存到数据库 订阅者请求重播
  • 选择一个有效的选择。该选择不是可用的选择之一

    在我的应用程序中 我有一个下拉列表 部门 它取决于之前从下拉列表 学院字段 中选择的值 我正在使用 ajax 来获取工作正常的新值 但是 当我尝试保存表单时 我得到选择一个有效的选择 该选择不是可用的选择之一 这是我的模型 from dja
  • php : 解析 html : 从 body 中提取脚本标签并在 之前注入?

    我不关心库是什么 但我需要一种从库中提取 元素的方法页面的内容 作为字符串 然后我想在 之前插入提取的 理想情况下 我想将 提取为两种类型 1 外部 具有 src 属性的 2 嵌入式 之间有代码的 到目前为止 我已经尝试过 phpDOM S
  • KSQL查询线程数

    有没有办法指定在 KSQL Server 上运行的 KSQL 查询应消耗的线程数 换句话说就是查询的并行性 KSQL Server 上可以运行的应用程序数量有限制吗 何时或如何决定横向扩展 是的 您可以指定ksql streams num
  • Linux 上的编译器支持 Objective-C 块吗?

    如何在Linux上编译以下代码 使用 Ubuntu 10 10 Maverick Meerkat include
  • 单点登录、同一服务器上的多个域、Ruby on Rails

    如果我有一台具有多个域的服务器 那么在同一域上实现单点登录解决方案的首选方法是什么 我目前正在使用该设备 在不同的域上放置了几百万个 cookie 但我陷入了困境 除了实现 SSO 之外 我还需要将各种 cookie 迁移到中央域 对于各种
  • MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA 不会调用 onActivityResult

    我试图用意图 MediaStore INTENT ACTION STILL IMAGE CAMERA 来调用相机 然而 使用StartActivityForResult不打电话onActivityResult 我该如何解决这个问题 get
  • 当 getBluetoothLeAdvertiser 返回一个对象时,为什么 isMultipleAdvertisementSupported() 返回 false?

    我正在尝试在我的设备上使用 BLE 传输 这是我使用的代码和输出 check BLE support Log i TAG BLE supported getPackageManager hasSystemFeature PackageMan
  • Numpy *.npz 内部文件结构

    任何人都可以分享一些有关 npz 中内部数据组织的信息吗 一些文档等 就是找不到东西 这是文档 npz 文件的格式 http docs scipy org doc numpy reference generated numpy savez
  • kubernetes 节点关闭/崩溃恢复?

    我们有一个带有主节点 foo 1 和两个工作节点 foo 2 和 foo 3 的集群 我们有一个在 foo 3 上运行的 pod 由 Kubernetes 决定 我们特意关闭 foo 3 作为实验 我的期望是 Kubernetes 会 看到
  • SocksSocketImpl Finalize 方法内存泄漏

    我们的 Web 应用程序之一出现了内存不足的情况 此应用程序在弹性负载均衡器后面的 Aamzon EC2 上的 Tomcat 上运行 从堆转储来看 大部分内存被 SocksSocketImpl 对象消耗 Yourkit 显示 99 的对象处
  • UITableView didSelectRow 返回错误的行索引值[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 当我选择一行时 它会返回更大或更小的行索引值 但永远不会返回正确的值 如图所示 我选择了14 返回了16 这是我使用的代码 IBO
  • 使用 data.table 包重新编码变量

    如果我想使用 R 重新编码变量data table 语法是什么 我看到了一些 ans 但发现它们不合适 例如如果我有一个名为gender 我想将性别 0 重新编码为未知 1 为男性 2 为女性 这是我尝试的方法 Name lt c John
  • 应用程序购买推荐链接[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有没有什么方法可以创建指向 App Store 的引用链接 并在链接中添加一些设备 ID 例如 b7a
  • 区分注册和使用 Meteor.loginWithExternalService() 登录

    Meteor 提供了一组loginWithExternalService 方法 例如loginWithTwitter 允许用户创建帐户或通过这些第三方身份验证提供商重新登录 但有没有办法区分这两种行为呢 即让人们sign in与 Twitt
  • 不为特定列更改创建修订

    我有一个经过审核的模型 其中有一列我必须定期更新 我不想为此专栏的每次更改创建修订版 即使属性 X 已更改 是否有任何配置不创建修订版 执行您要求的操作的唯一开箱即用的方法是实施有条件审计 文档中描述的条件审核方法要求用户提供自己的事件侦听
  • 来自基于 OWIN 的 WebAPI 的飞行前选项 CORS 令牌请求出现 400 错误

    确实很奇怪 我尝试向 WebAPI2 基于 OWIN 发出 CORS 请求以获取身份验证令牌 每隔一段时间它总是失败 就像第一个请求失败 但第二个请求将通过 第三个失败了 但第四个会成功 我不明白为什么它有一半的时间有效 我检查浏览器请求
  • Kivy:如何创建透明背景/画布,使按钮看起来漂浮在桌面上

    我正在尝试创建一个在单板计算机 特别是使用 armbian 的 OrangePi One PC 上运行的视频播放应用程序 我在使用 ffpyplayer kivy 使用的视频播放器 创建流畅的视频时遇到问题 因此 我决定简单地运行在视频前面