【问题标题】:Touchscreen scrolling Tkinter Python触摸屏滚动 Tkinter Python
【发布时间】:2019-05-16 09:28:14
【问题描述】:

我正在为带有 7 英寸触摸屏的 python 中的树莓派制作一个信息亭应用程序。 一切正常,现在,我正试图让滚动像在触摸屏上一样工作。我知道 raspbian 没有正确的触摸界面,因此,屏幕上的每次触摸都相当于鼠标点击,如果我移动手指触摸屏幕,就像拖动功能一样。

为了在 python 上实现这一点,我使用我的修改版本代码 Vertical Scrolled Frame 使用画布,我需要添加事件绑定 <ButtonPress-1><B1-Motion>

<ButtonPress-1> 可能会保存点击的 y 位置并为<B1-Motion> 启用bind_all 功能。

<B1-Motion> 可能会设置滚动设置向上或向下设置 <ButtonPress-1> 保存的 y 值与此事件的 event.y 之间的差异。

<ButtonRelease-1> 可能会通过滚动的<unbind_all> 禁用bind_all 功能。

我添加的事件代码是这样的,但我不知道如何使它正常工作,画布的.yview 函数以使我的函数按需要工作。

def moving(event):
    #In this part I don't know how to make my effect
    self.canvas.yview('scroll',event.y,"units")

def clicked(event):
    global initialy
    initialy = event.y
    self.canvas.bind_all('<B1-Motion>', moving)

def released(event):
    self.canvas.unbind_all('<B1-Motion>')

self.canvas.bind_all('<ButtonPress-1>',clicked)
self.canvas.bind_all('<ButtonRelease-1>', released)

【问题讨论】:

    标签: python tkinter scroll touchscreen


    【解决方案1】:

    Saad 的代码为基础,我对其进行了修改,使其适用于每个 S.O. (win, linux, mac) 使用yview_moveto 并且我已经应用了一些修改,正如我在这里解释的那样。

    编辑:我已经编辑了代码以显示完整的类。

    class VerticalScrolledFrame(Frame):
        """A pure Tkinter scrollable frame that actually works!
        * Use the 'interior' attribute to place widgets inside the scrollable frame
        * Construct and pack/place/grid normally
        * This frame only allows vertical scrolling
    
        """
        def __init__(self, parent, bg,*args, **kw):
            Frame.__init__(self, parent, *args, **kw)
    
            # create a canvas object and a vertical scrollbar for scrolling it
    
            canvas = Canvas(self, bd=0, highlightthickness=0,bg=bg)
            canvas.pack(side=LEFT, fill=BOTH, expand=TRUE)
    
            # reset the view
            canvas.xview_moveto(0)
            canvas.yview_moveto(0)
    
            self.canvasheight = 2000
    
            # create a frame inside the canvas which will be scrolled with it
            self.interior = interior = Frame(canvas,height=self.canvasheight,bg=bg)
            interior_id = canvas.create_window(0, 0, window=interior,anchor=NW)
    
            # track changes to the canvas and frame width and sync them,
            # also updating the scrollbar
            def _configure_interior(event):
                # update the scrollbars to match the size of the inner frame
                size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
                canvas.config(scrollregion="0 0 %s %s" % size)
                if interior.winfo_reqwidth() != canvas.winfo_width():
                    # update the canvas's width to fit the inner frame
                    canvas.config(width=interior.winfo_reqwidth())
            interior.bind('<Configure>', _configure_interior)
    
            def _configure_canvas(event):
                if interior.winfo_reqwidth() != canvas.winfo_width():
                    # update the inner frame's width to fill the canvas
                    canvas.itemconfigure(interior_id, width=canvas.winfo_width())
            canvas.bind('<Configure>', _configure_canvas)
    
            self.offset_y = 0
            self.prevy = 0
            self.scrollposition = 1
    
            def on_press(event):
                self.offset_y = event.y_root
                if self.scrollposition < 1:
                    self.scrollposition = 1
                elif self.scrollposition > self.canvasheight:
                    self.scrollposition = self.canvasheight
                canvas.yview_moveto(self.scrollposition / self.canvasheight)
    
            def on_touch_scroll(event):
                nowy = event.y_root
    
                sectionmoved = 15
                if nowy > self.prevy:
                    event.delta = -sectionmoved
                elif nowy < self.prevy:
                    event.delta = sectionmoved
                else:
                    event.delta = 0
                self.prevy= nowy
    
                self.scrollposition += event.delta
                canvas.yview_moveto(self.scrollposition/ self.canvasheight)
    
            self.bind("<Enter>", lambda _: self.bind_all('<Button-1>', on_press), '+')
            self.bind("<Leave>", lambda _: self.unbind_all('<Button-1>'), '+')
            self.bind("<Enter>", lambda _: self.bind_all('<B1-Motion>', on_touch_scroll), '+')
            self.bind("<Leave>", lambda _: self.unbind_all('<B1-Motion>'), '+')
    

    【讨论】:

    • 我将确切的代码粘贴到 VerticalScrolledFrame 中,但它没有显示 interior 框架。确保您没有对 VerticalScrolledFrame 进行任何其他修改,或者如果您这样做了,那么您可能应该发布整个课程。
    • 我已经对帖子进行了适当的更改,这是完整的课程。现在这对我有用。
    【解决方案2】:

    我用几行代码修改了VerticalScrolledFrame,它确实可以滚动你想要的方式。我用VerticalScrolledFrame 测试了代码,它在鼠标上运行良好。将以下代码添加到VerticalScrolledFrame

    self.offset_y = 0
    def on_press(evt):
        self.offset_y = evt.y_root
    
    def on_touch_scroll(evt): 
        if evt.y_root-self.offset_y<0: 
            evt.delta = -1
        else: 
            evt.delta = 1
        # canvas.yview_scroll(-1*(evt.delta), 'units') # For MacOS
        canvas.yview_scroll( int(-1*(evt.delta/120)) , 'units') # For windows
    
    self.bind("<Enter>", lambda _: self.bind_all('<Button-1>', on_press), '+')
    self.bind("<Leave>", lambda _: self.unbind_all('<Button-1>'), '+')
    self.bind("<Enter>", lambda _: self.bind_all('<B1-Motion>', on_touch_scroll), '+')
    self.bind("<Leave>", lambda _: self.unbind_all('<B1-Motion>'), '+')
    

    我希望你能发现这很有用。

    【讨论】:

    • 我想我明白你在做什么,我用yview_moveto()做了类似的事情,但没有按预期工作,但是,你的代码对我不起作用,我不'不知道是不是我做错了,事件触发正确,但是滚动仍然不起作用。
    • 这与event.delta 有关,因为它们在不同的系统上是不同的。检查此post。我知道在 Windows 上您将 delta 与 120 相除,但不确定 raspberry pi。
    • 我在 windows 下测试它,但我认为yview_moveto() 工作类似。我正在修改您的部分代码以使其按预期工作。非常感谢您的离去。
    • 是的,我试过了,它也可以用yview_moveto() 来完成,但这需要更多的代码行和一个相应变化的变量,它不会随着画布窗口的大小而变化。就像如果画布窗口的大小很大,那么滚动可能会变慢,具体取决于您给 yview_moveto() 的修改值。
    • 我已经修改了你的部分工作。如果您愿意,请尝试我的工作,再次感谢您的帮助。
    猜你喜欢
    • 2016-06-12
    • 1970-01-01
    • 2018-11-01
    • 2016-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多