ScrolledWindow 通过拖动滚动(模拟触摸屏上的手指)

Posted

技术标签:

【中文标题】ScrolledWindow 通过拖动滚动(模拟触摸屏上的手指)【英文标题】:ScrolledWindow scroll by drag (simulate finger on touchscreen) 【发布时间】:2017-05-13 00:49:53 【问题描述】:

我正在使用 python 和 GTK+3 构建一个应用程序,并使用 ScrolledWindow 内的 TreeView 以表格形式显示数据。

是否可以通过拖动树视图行来配置滚动窗口以执行滚动?就像我们在(移动)触摸屏上所做的那样。

在文档中,ScrolledWindows 具有动态滚动属性,但是:

    不知道怎么用 我没有触摸屏,只是想用鼠标模拟一下。

我不需要跨平台的解决方案,只需要 Ubuntu。

谢谢。

【问题讨论】:

这不是一个答案,但我希望你意识到 Pygtk 已经过时了。 This是Gtk3和Python的使用教程。 谢谢。但实际上,这就是我使用的。窗口创建就是这样,导入来自 gi.repository。所以我想,我已经在使用 gkt3了。 最新的 Gtk+-3.0 已经在大多数 *view 小部件上内置了动态滚动。 (不确定从哪个版本开始,Fedora 23 已经有了) @JoséFonte 我确实读过有关动态滚动属性的信息。但它不起作用。可能是因为我没有触摸屏。如何使用鼠标(拖动)启用该功能? @Lee 我认为您必须在操作系统级别模拟鼠标的触摸,也许某些工具会为您提供。但实际上,鼠标的行为不像触摸屏。 【参考方案1】:

一个可能的解决方案是连接到button press eventbutton release event。这将传入小部件(树视图)和一个事件。该事件有一个 .x 和 .y 属性,可用于检测鼠标移动的距离。

事件属性的文档已关闭:(

更新:

我知道如何完全按照您的要求进行操作。观察button press eventbutton release eventmotion notify event 必须在树视图上。这是使用 Gtk Builder。

glade.ui 文件的代码:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
  <requires lib="gtk+" version="3.0"/>
  <object class="GtkListStore" id="liststore1">
    <columns>
      <!-- column-name gchararray1 -->
      <column type="gchararray"/>
    </columns>
  </object>
  <object class="GtkWindow" id="window">
    <property name="visible">True</property>
    <property name="can_focus">False</property>
    <property name="title" translatable="yes">window</property>
    <property name="default_width">500</property>
    <property name="default_height">400</property>
    <signal name="destroy" handler="on_window_destroy" swapped="no"/>
    <child>
      <object class="GtkScrolledWindow" id="scrolledwindow1">
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="events"/>
        <property name="shadow_type">in</property>
        <child>
          <object class="GtkTreeView" id="treeview1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="events"/>
            <property name="model">liststore1</property>
            <signal name="button-press-event" handler="button_press_event" swapped="no"/>
            <signal name="button-release-event" handler="button_release_event" swapped="no"/>
            <signal name="motion-notify-event" handler="motion_notify_event" swapped="no"/>
            <child internal-child="selection">
              <object class="GtkTreeSelection" id="treeview-selection1"/>
            </child>
            <child>
              <object class="GtkTreeViewColumn" id="treeviewcolumn1">
                <property name="title" translatable="yes">column</property>
                <child>
                  <object class="GtkCellRendererText" id="cellrenderertext1"/>
                  <attributes>
                    <attribute name="text">0</attribute>
                  </attributes>
                </child>
              </object>
            </child>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

.py文件的代码:

#!/usr/bin/python

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GdkPixbuf, Gdk
import os, sys

UI_FILE = "glade.ui"

class GUI:
    def __init__(self):

        self.builder = Gtk.Builder()
        self.builder.add_from_file(UI_FILE)
        self.builder.connect_signals(self)

        liststore = self.builder.get_object('liststore1')
        for i in range (100):
            liststore.append([str(i)])

        self.v_scroll = self.builder.get_object('scrolledwindow1').get_vadjustment ()
        self.mouse_down = False
        self.previous_y = 0
        self.previous_position = 0
        window = self.builder.get_object('window')
        window.show_all()

    def button_press_event (self, treeview, event):
        if event.button == 1:
            self.mouse_down = True
            self.previous_y = event.y
            self.previous_position = self.v_scroll.get_value()

    def button_release_event (self, treeview, event):
        self.mouse_down = False

    def motion_notify_event (self, scrolled_window, event):
        if self.mouse_down == False:
            return
        current_y = event.y
        y_movement = (self.previous_y - current_y)
        scroll_position = (self.previous_position + y_movement)
        self.v_scroll.set_value(scroll_position)

    def on_window_destroy(self, window):
        Gtk.main_quit()

def main():
    app = GUI()
    Gtk.main()

if __name__ == "__main__":
    sys.exit(main())

变量名应该能很好地解释它们的作用。如果我理解错了,请纠正我。

【讨论】:

我应该将事件连接到哪里?树视图、滚动窗口还是其他? 树状视图。很抱歉没有澄清。 虽然我不确定该怎么做,但我会尝试。谢谢。 感谢您的帮助@theGtknerd。有用!我会发布一些关于 gtk 的新问题,如果你看到它,希望你不会介意提供帮助。谢谢。 @Lee 实际上,我每天都会检查 SO 的 Gtk 问题。我认为 Gtk 是一项伟大的技术,我希望 Gtk 拥有广泛的用户群。如果您觉得我的帮助有用,请将其传递给其他人 :-)

以上是关于ScrolledWindow 通过拖动滚动(模拟触摸屏上的手指)的主要内容,如果未能解决你的问题,请参考以下文章

javascript 拖拽移动滚动条

如何在 ios 模拟器上模仿两指滚动/拖动手势?

如何在ios模拟器中缩放图像?

新的macbook pro怎么把三指拖动窗口给调出来

windows触控手势

验证码的识别