Gtk4 GestureClick 未发出释放信号

问题描述 投票:0回答:3

当我将

Gtk.GestureClick
分配给
Gtk.Scale
时,没有发出
released
信号。

参见代码示例。

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class Main():
    def on_activate(self, app):
        win = Gtk.ApplicationWindow(application=app)
        gesture = Gtk.GestureClick.new()
        gesture.connect("pressed", self.press)
        gesture.connect("released", self.release)
        scale = Gtk.Scale()
        win.set_child(scale)
        scale.add_controller(gesture)
        win.present()

    def press(self, *_):
        print("pressed")

    def release(self, *_):
        print("released")

app = Gtk.Application(application_id='com.example.GtkApplication')
runner = Main()
app.connect('activate', runner.on_activate)

app.run(None)
python-3.x linux user-interface gtk gtk4
3个回答
3
投票

我实际上查看了GTK“GestureClick”小部件的源代码,在代码中发现“释放”信号仅在单击事件结束时(gtk_gesture_click_end)发出。 该事件与 GTK 手势小部件的“结束”信号相关。 因此,作为测试,我修改了“self.release”函数以利用小部件继承的“end”事件,如下所示。

gesture.connect("end", self.release)

然后,在打印“按下”后立即在终端上打印出“释放”一词,但它是作为单击事件的一部分执行的,并且不会等待鼠标按钮的实际释放。

您可以尝试我的小代码更改只是为了看看效果。 我不太愿意将此称为错误,因为此时我对 GTK 手势还不太有经验。 不过,请测试一下。 此时您可能只需要依赖点击事件。

其他发现。

简单来说,在回顾其他 GTK4 单击手势示例时,“按下”和“释放”手势都可以与其他小部件一起使用。 显然,比例小部件有一些特殊之处。 我修改了您的示例代码,将标签小部件替换为比例小部件。

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class Main():
    def on_activate(self, app):
        win = Gtk.ApplicationWindow(application=app)
        gesture = Gtk.GestureClick.new()
        gesture.connect("pressed", self.press)
        gesture.connect("released", self.release)
        label = Gtk.Label(label="This is a label widget")
        win.set_child(label)
        win.set_default_size(400, 200)
        label.add_controller(gesture)
        win.present()
        
    def press(self, *_):
        print("pressed")
    
    def release(self, *_):
        print("released")
    
app = Gtk.Application(application_id='com.example.GtkApplication')
runner = Main()
app.connect('activate', runner.on_activate)

app.run(None)

以下是在标签小部件上单击并释放鼠标按钮的终端输出结果。

Press and Release Label

仅供参考,只是为了确认这个问题似乎与缩放小部件有关,我用 C 语言构建了一个类似的程序来测试缩放小部件与其他小部件。 同样,秤小部件不会发出释放信号。 至少缩放小部件的特性在不同语言中是一致的。 所以看起来底线是缩放小部件不会发出释放信号。 我希望额外的信息有帮助。

问候。


0
投票

我有同样的问题,但我暂时用 gtk 按钮修复了。使用取消信号来释放。它对我有用。

func (c *Control) topCenter() *gtk.Box {
    boxroot := gtk.NewBox(gtk.OrientationHorizontal, 0)
    boxroot.SetHExpand(true)

    root := gtk.NewOverlay()
    root.SetCSSClasses([]string{"player-control-scale"})
    root.SetHExpand(true)

    c.cacheadjustment = gtk.NewAdjustment(0, 0, 1, 1, 10, 0)
    c.cacheprocess = gtk.NewScale(gtk.OrientationHorizontal, c.cacheadjustment)
    c.cacheprocess.AddCSSClass("timescalebuffer")
    root.SetChild(c.cacheprocess)

    c.timeadjustment = gtk.NewAdjustment(0, 0, 1, 1, 10, 0)
    c.timeprocess = gtk.NewScale(gtk.OrientationHorizontal, c.timeadjustment)
    c.timeprocess.AddCSSClass("timescale")

    tsstext := gtk.NewLabel("testing")
    timepopover := gtk.NewPopover()
    timepopover.SetSizeRequest(80, 0)
    timepopover.SetChild(tsstext)
    timepopover.SetPosition(gtk.PosTop)
    timepopover.SetAutohide(false)
    boxroot.Append(timepopover)
    timepopover.AddCSSClass("timePopup")

    motionctrl := gtk.NewEventControllerMotion()
    c.timeprocess.AddController(motionctrl)

    motionctrl.ConnectEnter(func(x, y float64) {
        glib.IdleAddPriority(glib.PRIORITY_HIGH_IDLE, func() {
            rect := gdk.NewRectangle(int(x), 0, 0, 0)
            timepopover.SetPointingTo(&rect)
            timepopover.Show()
        })
    })

    motionctrl.ConnectLeave(func() {
        glib.IdleAddPriority(glib.PRIORITY_HIGH_IDLE, func() {
            timepopover.Hide()
        })
    })

    motionctrl.ConnectMotion(func(x, y float64) {
        glib.IdleAddPriority(glib.PRIORITY_HIGH_IDLE, func() {

            rect := gdk.NewRectangle(int(x), 0, 0, 0)
            timepopover.SetPointingTo(&rect)
            prr := math.Round(percent.PercentOf(int(x), c.timeprocess.AllocatedWidth()))
            step := c.timeadjustment.StepIncrement()
            value := (step*math.Round(prr*(c.duration-0)/step) + 0) / 100
            drtime, _ := time.ParseDuration(fmt.Sprintf("%fs", value))
            c.Lock()
            c.lastValPos = drtime
            c.Unlock()

            currentTime := parsing.NewTime().Duration(drtime)
            tsstext.SetText(currentTime)
            if drtime.Seconds() < 0 {
                timepopover.Hide()
            } else if drtime.Seconds() > c.duration {
                timepopover.Hide()
            } else {
                if !timepopover.IsVisible() {
                    timepopover.Show()
                }
            }

        })
    })

    root.AddOverlay(c.timeprocess)

    // add button for temp fixed when gtk scale not emitted release signal
    c.btntracks = gtk.NewButton()
    c.btntracks.SetCSSClasses([]string{"transparent-btn"})

    clickges := gtk.NewGestureClick()
    c.timeprocess.AddController(clickges)

    clickges.ConnectPressed(func(nPress int, x, y float64) {
        fmt.Println("ConnectPressed")
        c.Lock()
        c.seekOnHold = true
        c.Unlock()
    })

    // use cancel for release signal
    clickges.ConnectCancel(func(sequence *gdk.EventSequence) {
        fmt.Println("ConnectCancel")
        c.Lock()
        c.seekOnHold = false
        c.Unlock()

        glib.IdleAddPriority(glib.PRIORITY_HIGH_IDLE, func() {
            c.Lock()
            val := c.lastValPos.Seconds()
            c.Unlock()
            c.timeadjustment.SetValue(val)
            c.main.player.Bridge().Seek(val)
        })
    })

    c.btntracks.SetChild(root)
    c.timeprocess.SetSensitive(false)
    c.cacheprocess.SetSensitive(false)
    c.btntracks.SetSensitive(false)
    boxroot.Append(c.btntracks)

    return boxroot
}

并为透明按钮添加css

.transparent-btn{
    background:transparent;
    box-shadow: none;
    border-radius: 0px;
    border: 0px;
    text-shadow: none; 
    -gtk-icon-shadow: none;
    padding: 0px;
    &:hover{
        box-shadow: none;
        background: transparent;
    }
}

0
投票

我找到了一种更简单的方法...将 GtkScale 小部件放入 GtkBox(或其他容器)中,将 GtkGestureClick 附加到父级并将其传播阶段设置为 GTK_PHASE_CAPTURE。这样你就会受到压力并被释放。

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