pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

软件和网站开发以及相关技术探讨
头像
langyxxl
帖子: 443
注册时间: 2012-01-17 22:17

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#16

帖子 langyxxl » 2013-10-13 21:11

你干脆把你的代码放出来,我们下载,直接看看,说不定能帮你修改对..
niuminguo
帖子: 20
注册时间: 2009-11-25 19:40

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#17

帖子 niuminguo » 2013-10-13 22:16

把代码删改了下,取了相关部分,打包。下载后解压,然后python test.py来运行。蓝色标题栏是用来拖动的。
附件
test.rar
(3.04 KiB) 已下载 96 次
nae6taiyie0T
帖子: 482
注册时间: 2013-09-13 0:42
系统: Debian sid

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#18

帖子 nae6taiyie0T » 2013-10-13 22:43

niuminguo 写了:
niuminguo 写了:
nae6taiyie0T 写了:
niuminguo 写了:代码如下:

代码: 全选


#!/usr/bin/env python

import gtk

class TitleBar(gtk.DrawingArea):
	def __init__(self,father):
		gtk.DrawingArea.__init__(self)

		self.motion=''
		self.begin_x=''
		self.begin_y=''
		self.end_x=''
		self.end_y=''
		
		self.father=father

		self.father_x,self.father_y=self.father.get_position()

		self.set_size_request(-1,80)
		self.connect('button-press-event',self.mouse_press)
		self.connect('button-release-event',self.mouse_release)
		self.set_events( gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK)

	def mouse_press(self,widget,event):
		if event.button == 1:
			self.begin_x,self.begin_y = event.x,event.y
			self.motion=self.connect('motion-notify-event',self.mouse_motion)
	def mouse_release(self,widget,event):
		self.disconnect(self.motion)
	def mouse_motion(self,widget,event):
		self.end_x,self.end_y = event.x,event.y
		x=self.father_x + int(self.end_x - self.begin_x)
		y=self.father_y + int(self.end_y - self.begin_y)
		self.father.move(int(x),int(y))

[/size]


self.father是drawingarea所在的窗体。目的是通过鼠标在drawingarea上拖动来拖动窗体移动。效果是可以拖动窗体移动,但是抖动的比较厉害。
因为你用的是实时计算, 当窗口移动后, 你绑定的操作都会被计算一遍, 这样有很大的计算量, 表现出来就是卡, 抖.

我的解决方法是用延时计算, 原理很简单, 这也是做GUI设计的一个基本技巧.
当移动事件触发之后, 你用GLib.timeout_add()来调用你真正的处理函数. 看例子:

代码: 全选

def on_window_move(self, *args):
    def _on_window_move(local_timestamp):
        # 如果这两个时间标记不相同, 就什么都不做.
        if local_timestamp != self.window_move_timestamp:
            return
        # 超过250ms, 进行实际的计算操作
        # ....

    self.window_move_timestamp = time.time()
    GLib.timeout_add(250, _on_window_move, self.window_move_timestamp)
适用的场景包括, 播放器的进度条的滑动, 窗口移动; 还有, 输入框的自动补全(自动完成)等.
当然, 这个方法对于需要实时得到窗口状态的操作不适用, 比如实时显示当前窗口的位置.

恰当地处理好时间, 在GUI设计中是很有意思的, 比如, 在手机上, 如何才能取消刚刚要发送的一条短信呢? 最简单的方法就是延迟几秒钟才发送(这个地在老罗他们的android ROM里加入的功能).


多说两句无关的, Gtk中提供的另一个简单易用的函数是GLib.idle_add(), 用它可以将后台线程处理好的数据转到主线程上显示.

还有, 提醒一下, pygtk这个gtk的绑定早在2011年就没更新了, 最后一个版本是2.24. 现在都转到了PyGObject上来了, 总体来说, 后者的API更加规范一下, 并且更强大, 具体可以看一下GObject Introspection.
非常感谢你的答复,你提到的方法我再试试看。另外,pygobject的东西我也会看看,非常重要的提醒,多谢!
这个方法我试过了,虽然不抖动了,但是移动不平滑,像是鼠标指针先移动过去了,窗口才过去,不是同步移动的。改变timeout值也不行,改的太小的时候又会出现抖动。
你这种需要算是实时显示~ 上面提到的方法需要变通一下的, 好吧, 我的错, 话只说了一半.

用过gnumeric吗? 里面的绘制的图形, 移动起来速度特别快, 完全不卡, 因为它使用了部分渲染的技巧: 图片随着鼠标移动时, 先只绘制四个边框(用虚线), 然后当用户放开鼠标时, 再将图片的内容重新绘制出来.
这种技巧, 极大地减少了计算量.
一个反例就是inkscape, 它里面的矢量图, 包括路径, 都是实时绘制的, 一个稍复杂的操作, CPU就跑到了100%(我的笔记本性能不太好).
nae6taiyie0T
帖子: 482
注册时间: 2013-09-13 0:42
系统: Debian sid

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#19

帖子 nae6taiyie0T » 2013-10-13 22:44

niuminguo 写了:把代码删改了下,取了相关部分,打包。下载后解压,然后python test.py来运行。蓝色标题栏是用来拖动的。
请换成tar.gz, zip, 7z, bz2等压缩格式, 谢谢~
nae6taiyie0T
帖子: 482
注册时间: 2013-09-13 0:42
系统: Debian sid

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#20

帖子 nae6taiyie0T » 2013-10-13 22:53

给你截个示意图.

请注意一下鼠标的位置.
附件
gnumeric2.png
nae6taiyie0T
帖子: 482
注册时间: 2013-09-13 0:42
系统: Debian sid

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#21

帖子 nae6taiyie0T » 2013-10-14 0:36

好吧, 我还是比较活跃的.

看了你的代码, 找到了错误.
你对event.x, event.x_root等距离有错误的理解, 不多说, 先上代码, 压缩包里有完整的修改后的代码, 以及我用gtk3重写的代码, 我建议你直接学PyGObject, pygtk确实过时了.

用gtk3重写的那个, 还加入了一个小特性, 当鼠标按下时鼠标会变成手形, 松开后又会恢复.

多数linux窗口管理器会提供一个很好的功能, 就是按住Alt键 再拖鼠标, 就可以移动窗口了.

如果你还想在ToolBar上面放一些按纽的话, 就真不推荐你这样写代码了, 因为在gtk3中, ToolBar可以直接拖放的, 请试试evince, nautilus你就会发现了. 至于GtkToolBar的背景, 也可以用图片来填充的, 可以在CSS中定义background-image. 是的, gtk3中可以直接用CSS来定义widget的style, 写起来很容易上手.

手动计算window position并不推荐, 没有必要, 因为gtk提供了类似的函数, gtk_window_begin_move_drag(), 还有一个类似的gtk_window_begin_resize_drag(), 这个是调整窗口大小的. 具体的用法可以参考devhelp里的解释.

也可以看一下我之前的一个小项目: https://github.com/LiuLang/gmeasure, 桌面上的测量工具, 类似于screenruler等, 但它的背景是可调节成透明的, 它有x, y两个轴, 很方便. 里面有用到上面说的两个函数, 代码很短, 不到200行.

我之前回答的那些, 太多余了, 因为我当时没读你的代码, 并没有找到根本的问题, 就算是胡扯吧.
附件
test-mod.tar.gz
修正好的代码
(20 KiB) 已下载 98 次
niuminguo
帖子: 20
注册时间: 2009-11-25 19:40

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#22

帖子 niuminguo » 2013-10-14 9:46

nae6taiyie0T 写了:
niuminguo 写了:把代码删改了下,取了相关部分,打包。下载后解压,然后python test.py来运行。蓝色标题栏是用来拖动的。
请换成tar.gz, zip, 7z, bz2等压缩格式, 谢谢~
不好意思,我刚开始用的tgz格式的,结果上传时发现不支持。所以误认为其他格式也不支持才用了rar.
附件
test.tar.gz
(3.11 KiB) 已下载 95 次
niuminguo
帖子: 20
注册时间: 2009-11-25 19:40

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#23

帖子 niuminguo » 2013-10-14 9:48

nae6taiyie0T 写了:
niuminguo 写了:把代码删改了下,取了相关部分,打包。下载后解压,然后python test.py来运行。蓝色标题栏是用来拖动的。
请换成tar.gz, zip, 7z, bz2等压缩格式, 谢谢~
不好意思,我刚开始用的tgz格式的,结果上传时发现不支持。所以误认为其他格式也不支持才用了rar.
附件
test.tar.gz
(3.11 KiB) 已下载 96 次
nae6taiyie0T
帖子: 482
注册时间: 2013-09-13 0:42
系统: Debian sid

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#24

帖子 nae6taiyie0T » 2013-10-14 10:03

niuminguo 写了:
nae6taiyie0T 写了:
niuminguo 写了:把代码删改了下,取了相关部分,打包。下载后解压,然后python test.py来运行。蓝色标题栏是用来拖动的。
请换成tar.gz, zip, 7z, bz2等压缩格式, 谢谢~
不好意思,我刚开始用的tgz格式的,结果上传时发现不支持。所以误认为其他格式也不支持才用了rar.
测试结果如何? 有问题的话就说出来吧.
niuminguo
帖子: 20
注册时间: 2009-11-25 19:40

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#25

帖子 niuminguo » 2013-10-14 10:10

nae6taiyie0T 写了:
niuminguo 写了:
nae6taiyie0T 写了:
niuminguo 写了:把代码删改了下,取了相关部分,打包。下载后解压,然后python test.py来运行。蓝色标题栏是用来拖动的。
请换成tar.gz, zip, 7z, bz2等压缩格式, 谢谢~
不好意思,我刚开始用的tgz格式的,结果上传时发现不支持。所以误认为其他格式也不支持才用了rar.
测试结果如何? 有问题的话就说出来吧.
太好了,可以拖动了。看来还是我理解上的错误,浪费了大家这么多时间,实在不好意思啊。多谢了,现在开始学习pygobject。另外,你用gtk3实现的那个手型的小特性也超级赞!太谢谢你了!
nae6taiyie0T
帖子: 482
注册时间: 2013-09-13 0:42
系统: Debian sid

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#26

帖子 nae6taiyie0T » 2013-10-14 10:26

niuminguo 写了:
nae6taiyie0T 写了:
niuminguo 写了:
nae6taiyie0T 写了:
niuminguo 写了:把代码删改了下,取了相关部分,打包。下载后解压,然后python test.py来运行。蓝色标题栏是用来拖动的。
请换成tar.gz, zip, 7z, bz2等压缩格式, 谢谢~
不好意思,我刚开始用的tgz格式的,结果上传时发现不支持。所以误认为其他格式也不支持才用了rar.
测试结果如何? 有问题的话就说出来吧.
太好了,可以拖动了。看来还是我理解上的错误,浪费了大家这么多时间,实在不好意思啊。多谢了,现在开始学习pygobject。另外,你用gtk3实现的那个手型的小特性也超级赞!太谢谢你了!
嘻嘻~

关于pygobject的资料, 给你推荐一些.
基础的: https://python-gtk-3-tutorial.readthedo ... index.html

cairo方面的:http://zetcode.com/gfx/pycairo/ , 因为gtk中可以很方便地使用cairo, 用于2D绘图的, 命令也简单.

参考书的话, http://www.gtkbook.com/ , Foundations of GTK+ Development, 英文版, 比较旧了, 基于gtk2的, 但里面对gtk有了详细的讲解, 我入门时读的这本书, 只能说, 关于gtk的参考书真的不多, 但是它很容易入手, 再加入容易查API, 开发起来也不难.

工具的话, 我写PyGObject用的是vim.
当然了, devhelp, glade这几个也是必需的.
如果要使用dbus的话, 还要加上d-feet这个dbus浏览器
niuminguo
帖子: 20
注册时间: 2009-11-25 19:40

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#27

帖子 niuminguo » 2013-10-14 11:41

nae6taiyie0T 写了:
niuminguo 写了:
nae6taiyie0T 写了:
niuminguo 写了:
nae6taiyie0T 写了:
niuminguo 写了:把代码删改了下,取了相关部分,打包。下载后解压,然后python test.py来运行。蓝色标题栏是用来拖动的。
请换成tar.gz, zip, 7z, bz2等压缩格式, 谢谢~
不好意思,我刚开始用的tgz格式的,结果上传时发现不支持。所以误认为其他格式也不支持才用了rar.
测试结果如何? 有问题的话就说出来吧.
太好了,可以拖动了。看来还是我理解上的错误,浪费了大家这么多时间,实在不好意思啊。多谢了,现在开始学习pygobject。另外,你用gtk3实现的那个手型的小特性也超级赞!太谢谢你了!
嘻嘻~

关于pygobject的资料, 给你推荐一些.
基础的: https://python-gtk-3-tutorial.readthedo ... index.html

cairo方面的:http://zetcode.com/gfx/pycairo/ , 因为gtk中可以很方便地使用cairo, 用于2D绘图的, 命令也简单.

参考书的话, http://www.gtkbook.com/ , Foundations of GTK+ Development, 英文版, 比较旧了, 基于gtk2的, 但里面对gtk有了详细的讲解, 我入门时读的这本书, 只能说, 关于gtk的参考书真的不多, 但是它很容易入手, 再加入容易查API, 开发起来也不难.

工具的话, 我写PyGObject用的是vim.
当然了, devhelp, glade这几个也是必需的.
如果要使用dbus的话, 还要加上d-feet这个dbus浏览器
好的,多谢了啊,太感谢你了。:)
头像
langyxxl
帖子: 443
注册时间: 2012-01-17 22:17

Re: pygtk 实现的无边框窗口的拖动 拖动时窗口抖动太厉害 不平滑

#28

帖子 langyxxl » 2013-10-14 20:54

感觉学到了很多.....
大神,就是不一样啊!!
回复