wxPython:将 wx.Button 拖放到面板上会冻结应用程序

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

我正在尝试构建一个应用程序,用户可以在面板周围拖放一些按钮。 我首先遇到了关于鼠标捕获事件丢失的错误,最后我发现我必须捕获此事件以防止该错误。

但是现在,当我运行应用程序时,我可以拖放按钮,但是在释放鼠标左键后应用程序完全冻结。

我必须从终端使用 Ctrl+C 来停止它,否则我的鼠标在桌面环境中的任何其他窗口中都无法使用。

我怀疑是鼠标捕获事件处理不好的问题。

我在 Ubuntu 16.04 下工作,并从包 (apt) 安装了 Python 3.5。 我尝试了从包(apt)安装的 wxPython 4.0.0 以及从 pip 安装的最新 wxPython 4.0.4。

在这两种情况下,单击或拖放按钮后应用程序都会完全冻结。

import wx


class DragButton(wx.Button):
    def __init__(self, parent, id=wx.ID_ANY, label="", pos=(0, 0)):
        super().__init__(parent=parent, id=id, label=label, pos=pos)
        self._dragging = False

        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.Bind(wx.EVT_MOTION, self.OnMouseMove)
        self.Bind(wx.EVT_MOUSE_CAPTURE_LOST, lambda evt: None)

    def OnLeftDown(self, evt):
        print("Left down")
        if  not self.HasCapture():
            self.CaptureMouse()
        x, y = self.ClientToScreen(evt.GetPosition())
        originx, originy = self.GetPosition()
        dx = x - originx
        dy = y - originy
        self.delta = ((dx, dy))

    def OnLeftUp(self, evt):
        print("Left UPPPP")
        if self.HasCapture():
            self.ReleaseMouse()

    def OnMouseMove(self, evt):
        if evt.Dragging() and evt.LeftIsDown():
            x, y = self.ClientToScreen(evt.GetPosition())
            fp = (x - self.delta[0], y - self.delta[1])
            self.Move(fp)


class GDomFrame(wx.Frame):
    def __init__(self, parent, title):
        super().__init__(parent, title=title, size=(350, 300))

        self._init_ui()
        self.Centre()


    def _init_ui(self):
        panel = wx.Panel(self)

        self.button = DragButton(panel, label="Drag me", pos=(10, 10))


if __name__ == '__main__':
    print("wxPython version: {}".format(wx.__version__))
    app = wx.App()
    ex = GDomFrame(None, title='GDom Application')
    ex.Show()
    app.MainLoop()

通过此代码,我希望有一个可以在面板上移动多次的按钮。

python python-3.x wxpython
1个回答
2
投票

我测试过类似的脚本。它在 Windows 上运行良好,但在 ubuntu 16.04 上运行不佳。我是这样解决问题的。

def OnLeftDown(self, evt):
    print("Left down")
    if not self.HasCapture():
        self.CaptureMouse()
        self.ReleaseMouse() # <------

我的脚本:

import wx

class Mywin(wx.Frame): 
    def __init__(self, parent, title): 
        super(Mywin, self).__init__(parent, title = title,size = (400,200))  
        self.InitUI()
        self.Centre() 

    def InitUI(self):
        self.panel = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL) 
        self.btn = wx.Button(self.panel,-1,"click Me",pos=(10, 10)) 
        vbox.Add(self.btn,0,wx.ALIGN_CENTER) 

        self.btn.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
        self.btn.Bind(wx.EVT_MOTION,  self.OnMouseMove)
        self.btn.Bind(wx.EVT_LEFT_UP,  self.OnMouseUp)
        print ("Init pos:",self.btn.GetPosition())

    def OnMouseDown(self, event):
        if (not self.btn.HasCapture()):
            self.btn.CaptureMouse()
            self.btn.ReleaseMouse()
            sx,sy   = self.panel.ScreenToClient(self.btn.GetPosition())
            dx,dy  = self.panel.ScreenToClient(wx.GetMousePosition())
            self.btn._x,self.btn._y   = (sx-dx, sy-dy)

    def OnMouseMove(self, event):
        if event.Dragging() and event.LeftIsDown():
            x, y = wx.GetMousePosition()
            self.btn.SetPosition(wx.Point(x+self.btn._x,y+self.btn._y))
            print(self.btn.GetPosition())

    def OnMouseUp(self, event):
        if (self.btn.HasCapture()): 
            self.btn.ReleaseMouse()
            print ("Final pos:",self.btn.GetPosition())

def main():
    app = wx.App()
    w = Mywin(None, title='Button demo')
    w.Show()
    app.MainLoop()

if __name__ == '__main__':
    main()
© www.soinside.com 2019 - 2024. All rights reserved.