当我将
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)
我实际上查看了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)
以下是在标签小部件上单击并释放鼠标按钮的终端输出结果。
仅供参考,只是为了确认这个问题似乎与缩放小部件有关,我用 C 语言构建了一个类似的程序来测试缩放小部件与其他小部件。 同样,秤小部件不会发出释放信号。 至少缩放小部件的特性在不同语言中是一致的。 所以看起来底线是缩放小部件不会发出释放信号。 我希望额外的信息有帮助。
问候。
我有同样的问题,但我暂时用 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;
}
}
我找到了一种更简单的方法...将 GtkScale 小部件放入 GtkBox(或其他容器)中,将 GtkGestureClick 附加到父级并将其传播阶段设置为 GTK_PHASE_CAPTURE。这样你就会受到压力并被释放。