是否可以在Gtk窗口/窗口小部件中停用鼠标光标?

问题描述 投票:1回答:1

第一个我的问题:有没有一种方法可以简单地停用小部件或所有窗口中的鼠标光标?现在是问题的背景:

我正在编写一个要在其中显示视频的应用程序。播放视频时,我会使用键盘快捷键来显示和隐藏进度,也可以暂停。到目前为止,除了我的鼠标光标在窗口中之外,所有事情都可以正常工作,而没有任何按键事件在起作用。使它们再次起作用的唯一方法是将光标手动移出窗口。我宁愿不必手动移动光标,而且视频中的箭头也很烦人。这就是为什么我要问这个问题。

这里是一个代码示例:

import pafy, gi
gi.require_versions({'Gtk':'3.0', 'GdkX11':'3.0', 'Gst':'1.0', 'GstVideo':'1.0'})
from gi.repository import Gst, Gtk, GLib, GdkX11, GstVideo, GObject

vertical  = Gtk.Orientation.VERTICAL
horizontal = Gtk.Orientation.HORIZONTAL

link = #PLZ insrte here any youtube video link
vid = pafy.new(link)
best = vid.getbest()
uri = best.url

class GstWidget(Gtk.DrawingArea):

    def __init__(self):

        super().__init__()

        self.connect('draw', self.on_draw)
        self.connect('realize', self.on_realize)
        self.connect('unrealize', self.on_unrealize)

        # Create GStreamer pipeline
        self.pipeline = Gst.Pipeline()

        # Create bus to get events from GStreamer pipeline
        self.bus = self.pipeline.get_bus()
        self.bus.add_signal_watch()
        self.bus.connect('message::eos', self.on_eos)
        self.bus.connect('message::error', self.on_error)

        # This is needed to make the video output in our DrawingArea:
        self.bus.enable_sync_message_emission()
        self.bus.connect('sync-message::element', self.on_sync_message)

        # Create GStreamer elements
        self.playbin = Gst.ElementFactory.make('playbin', None)

        # Add playbin to the pipeline
        self.pipeline.add(self.playbin)

        # Set properties
        self.playbin.set_property('uri', uri)

    def on_realize(self, widget, data=None):
        print("on_relalize")

        window = widget.get_window()
        self.xid = window.get_xid()


    def on_draw(self, widget, cr):
        if self.playbin.get_state(0).state < Gst.State.PAUSED:
            allocation = widget.get_allocation()

            cr.set_source_rgb(0, 0, 0)
            cr.rectangle(0, 0, allocation.width, allocation.height)
            cr.fill()

        # self.on_realize(widget)

    def on_unrealize(self, widget, data=None):
        # to prevent racing conditions when closing the window while playing
        self.playbin.set_state(Gst.State.NULL)
        self.pipeline.set_state(Gst.State.NULL)

    def on_sync_message(self, bus, msg):
        if msg.get_structure().get_name() == 'prepare-window-handle':
            print('prepare-window-handle')

            print('on_sync', self.xid)
            self.playbin.set_window_handle(self.xid)

            print(msg)
            print(msg.src)


    def on_eos(self, bus, msg):
        self.pipeline.seek_simple(
            Gst.Format.TIME,
            Gst.SeekFlags.FLUSH | Gst.SeekFlags.KEY_UNIT,
            0
        )

    def on_error(self, bus, msg):
        err, debug = message.parse_error()
        print(f"Error: {err}", debug)



class Master(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self, title="Gst_test")

        button = Gtk.Button(label="Play")
        button.connect("clicked", self.on_button_clicked)

        self.add(button)

    def on_button_clicked(self, widget):

        for child in self.get_children():
            child.destroy()

        self.video_player = GstWidget()

        #main container
        self.main_box = Gtk.Box(orientation=vertical)

        #for the progress bar
        self.hbox = Gtk.Box(orientation=horizontal)

        #here we gona make our progressbar.
        self.slider = Gtk.Scale.new_with_range(horizontal, 0, 100, 0.5)
        # self.slider_handler_id = self.slider.connect("value-changed", self.on_slider_seek)
        self.hbox.pack_start(self.slider, True, True, 2)

        self.main_box.pack_start(self.video_player, True, True, 0)
        self.add(self.main_box)

        # set focus on the main_box and connect it to the key_pressed method
        self.main_box.set_can_focus(True)
        self.main_box.grab_focus()
        self.main_box.connect("key-press-event", self.key_pressed)

        self.show_all()

        #adding the progress bare after the show_all so we don't have it by default
        self.main_box.pack_start(self.hbox, False, False, 0)

        if self.video_player.playbin.get_state(0).state != Gst.State.PAUSED:
            self.video_player.pipeline.set_state(Gst.State.PLAYING)
        else:
            self.video_player.pipeline.set_state(Gst.State.PAUSED)

    def key_pressed(self, widget, event):
        #is the pressed key the up-arrow?
        if event.get_keyval()[1] == 65362:
            self.show_all()
        #is the pressed key the down-arrow?
        elif event.get_keyval()[1] == 65364:
            self.hbox.hide()
        #is key F11?
        elif event.get_keyval()[1] == 65480:
            print(f"{self.is_fullscreen=}")
        #is the pressed key the space-bar?
        elif event.get_keyval()[1] == 32:
            if self.video_player.playbin.get_state(0).state == Gst.State.PLAYING:
                self.video_player.pipeline.set_state(Gst.State.PAUSED)
                self.show_all()
            else:
                if self.video_player.playbin.get_state(0).state == Gst.State.PAUSED:
                    self.video_player.pipeline.set_state(Gst.State.PLAYING)
                    self.hbox.hide()
        #if it is any of the previous, just tell me which is.
        else:
            print(f"{__name__=} @ line 160, {event.get_keyval()}")



if __name__ == "__main__":
    Gst.init(None)
    root = Master()
    root.connect("delete-event", Gtk.main_quit)
    root.show_all()
    Gtk.main()

我尝试在哪里寻找答案的斜线:我在documentations中进行了搜索,但是在Gtk,Gdk,Gst中都找不到如何执行此操作的方法。我在网上发现了一些有关Gst Navigate的文章,但是它是用C编写的,我从没学过,所以对我没有帮助。而“导航”则不在我刚刚链接的文档中。

我还在stackoverflow here中发现了一些问题,但是已经有5年历史了,如今似乎不起作用。 Gtk.Gdk.Pixmap似乎不再可用。也许还有另一个名字?

谢谢您的时间

python gtk gstreamer pygtk
1个回答
0
投票

问题:停用Gtk窗口/窗口小部件中的鼠标光标?

与为窗口小部件设置新的/不同的Cursor相同。您必须等待realize信号。如果尚未创建小部件的Gdk.Window,则无法更改光标。

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib


class ApplicationWindow(Gtk.ApplicationWindow):
    def __init__(self):
        super().__init__()
        self.connect("destroy", Gtk.main_quit)
        self.set_size_request(100, 70)

        self.connect("realize", self.on_realize)
        GLib.timeout_add(interval=5000, function=self.reset_cursor)

    def on_realize(self, widget):
        # Step 1: Get the Gdk.Display for the toplevel for this widget.
        display = widget.get_display()

        # Step 2: Create a new Cursor of type BLANK_CURSOR
        cursor = Gdk.Cursor.new_for_display(display, Gdk.CursorType.BLANK_CURSOR)

        # Step 3: Get the widget’s Gdk.Window and set the new Cursor
        widget.get_window().set_cursor(cursor)

    def reset_cursor(self):
        cursor = Gdk.Cursor.new_from_name(self.get_display(), 'default')
        self.get_window().set_cursor(cursor)

if __name__ == "__main__":
    ApplicationWindow()
    Gtk.main()

使用Python测试:3.5-gi .__ version __:3.22.0

© www.soinside.com 2019 - 2024. All rights reserved.