加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

在wxPython中跨面板拖放图像

发布时间:2020-12-20 13:33:16 所属栏目:Python 来源:网络整理
导读:我目前不确定如何跨面板实现一些对象(在本例中为png)的拖放.我已经查看了wx Python示例中提供的关联DragImage示例,这里的大部分代码都是从中派生出来的.但是,如果您运行下面的代码(您需要生成一个或两个示例PNG),我有三个面板:顶部的面板,我希望PNG连续加载
我目前不确定如何跨面板实现一些对象(在本例中为png)的拖放.我已经查看了wx Python示例中提供的关联DragImage示例,这里的大部分代码都是从中派生出来的.但是,如果您运行下面的代码(您需要生成一个或两个示例PNG),我有三个面板:顶部的面板,我希望PNG连续加载,然后两个它下面的面板.将顶部面板上的PNG排成一行的代码行目前已被注释掉(在MechanismPanel类下面,它位于底部),因为它阻止我获取任何鼠标事件.我不确定是否可以在面板上拖放图像,或者是否可以,如果我正确地进行操作.

编辑:对我正在寻找的内容进行更为简洁的解释.顶部面板中的图像,您可以将其中一个图像拖出并将其添加到其中一个下面板.可以将顶部面板视为一系列要绘制的小部件,将底部的两个面板视为排列小部件的位置.为了帮助区分问题,我还有一个关于在顶部面板here中拖动和复制图像的问题.

import os
import glob

import wx
import wx.lib.scrolledpanel as scrolled

class MainWindow(wx.Frame):
    def __init__(self,parent,title):
        wx.Frame.__init__(self,parent)
        frm_pnl = MainPanel(self)

        self.Show()

class DragShape:
    def __init__(self,bmp):
        self.bmp = bmp
        self.pos = (0,0)
        self.shown = True
        self.text = None
        self.fullscreen = False

    def HitTest(self,pt):
        rect = self.GetRect()
        return rect.InsideXY(pt.x,pt.y)

    def GetRect(self):
        return wx.Rect(self.pos[0],self.pos[1],self.bmp.GetWidth(),self.bmp.GetHeight())

    def Draw(self,dc,op = wx.COPY):
        if self.bmp.Ok():
            memDC = wx.MemoryDC()
            memDC.SelectObject(self.bmp)

            dc.Blit(self.pos[0],self.bmp.GetHeight(),memDC,op,True)

            return True
        else:
            return False

class MainPanel(wx.Panel):
    def __init__(self,parent):
        wx.Panel.__init__(self,-1,size = (900,700))

        self.shapes = []

        #panel for mechanisms
        mechPnl = MechanismPanel(self)

        mechSzr = wx.BoxSizer(wx.HORIZONTAL)
        mechSzr.Add(mechPnl,1)

        #panels for timeline
        posPnl = IdTimelinePanel(self)
        timelinePnl = TimelinePanel(self)

        mainSzr = wx.BoxSizer(wx.HORIZONTAL)
        mainSzr.Add(posPnl,1,wx.EXPAND)
        mainSzr.Add(timelinePnl,wx.EXPAND)

        selfSizer = wx.BoxSizer(wx.VERTICAL)
        selfSizer.Add(mechSzr,wx.EXPAND)
        selfSizer.Add(mainSzr,wx.EXPAND)
        selfSizer.Layout()
        self.SetSizer(selfSizer)



        self.dragImage = None
        self.dragShape = None
        self.hiliteShape = None

        self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))


        #self.Bind(wx.EVT_ERASE_BACKGROUND,self.OnEraseBackground)
        self.Bind(wx.EVT_PAINT,self.OnPaint)
        mechPnl.Bind(wx.EVT_LEFT_DOWN,self.OnLeftDown)
        mechPnl.Bind(wx.EVT_LEFT_UP,self.OnLeftUp)
        mechPnl.Bind(wx.EVT_MOTION,self.OnMotion)
        mechPnl.Bind(wx.EVT_LEAVE_WINDOW,self.OnLeaveWindow)
        timelinePnl.Bind(wx.EVT_LEFT_DOWN,self.OnLeftDown)
        timelinePnl.Bind(wx.EVT_LEFT_UP,self.OnLeftUp)
        timelinePnl.Bind(wx.EVT_MOTION,self.OnMotion)
        timelinePnl.Bind(wx.EVT_LEAVE_WINDOW,self.OnLeaveWindow)

    # The mouse is moving
    def OnMotion(self,evt):
        print "On motion!"

        # Ignore mouse movement if we're not dragging.
        if not self.dragShape or not evt.Dragging() or not evt.LeftIsDown():
            return

        # if we have a shape,but haven't started dragging yet
        if self.dragShape and not self.dragImage:

            # only start the drag after having moved a couple pixels
            tolerance = 2
            pt = evt.GetPosition()
            dx = abs(pt.x - self.dragStartPos.x)
            dy = abs(pt.y - self.dragStartPos.y)
            if dx <= tolerance and dy <= tolerance:
                return

            # refresh the area of the window where the shape was so it
            # will get erased.
            self.dragShape.shown = False
            self.RefreshRect(self.dragShape.GetRect(),True)
            self.Update()

            if self.dragShape.text:
                self.dragImage = wx.DragString(self.dragShape.text,wx.StockCursor(wx.CURSOR_HAND))
            else:
                self.dragImage = wx.DragImage(self.dragShape.bmp,wx.StockCursor(wx.CURSOR_HAND))

            hotspot = self.dragStartPos - self.dragShape.pos
            self.dragImage.BeginDrag(hotspot,self,self.dragShape.fullscreen)

            self.dragImage.Move(pt)
            self.dragImage.Show()


        # if we have shape and image then move it,posibly highlighting another shape.
        elif self.dragShape and self.dragImage:
            onShape = self.FindShape(evt.GetPosition())
            unhiliteOld = False
            hiliteNew = False

            # figure out what to hilite and what to unhilite
            if self.hiliteShape:
                if onShape is None or self.hiliteShape is not onShape:
                    unhiliteOld = True

            if onShape and onShape is not self.hiliteShape and onShape.shown:
                hiliteNew = True

            # if needed,hide the drag image so we can update the window
            if unhiliteOld or hiliteNew:
                self.dragImage.Hide()

            if unhiliteOld:
                dc = wx.ClientDC(self)
                self.hiliteShape.Draw(dc)
                self.hiliteShape = None

            if hiliteNew:
                dc = wx.ClientDC(self)
                self.hiliteShape = onShape
                self.hiliteShape.Draw(dc,wx.INVERT)

            # now move it and show it again if needed
            self.dragImage.Move(evt.GetPosition())
            if unhiliteOld or hiliteNew:
                self.dragImage.Show()

    # Left mouse button up.
    def OnLeftUp(self,evt):
        print "On left up!"

        if not self.dragImage or not self.dragShape:
            self.dragImage = None
            self.dragShape = None
            return

        # Hide the image,end dragging,and nuke out the drag image.
        self.dragImage.Hide()
        self.dragImage.EndDrag()
        self.dragImage = None

        if self.hiliteShape:
            self.RefreshRect(self.hiliteShape.GetRect())
            self.hiliteShape = None

        # reposition and draw the shape

        # Note by jmg 11/28/03 
        # Here's the original:
        #
        # self.dragShape.pos = self.dragShape.pos + evt.GetPosition() - self.dragStartPos
        #
        # So if there are any problems associated with this,use that as
        # a starting place in your investigation. I've tried to simulate the
        # wx.Point __add__ method here -- it won't work for tuples as we
        # have now from the various methods
        #
        # There must be a better way to do this :-)
        #

        self.dragShape.pos = (
            self.dragShape.pos[0] + evt.GetPosition()[0] - self.dragStartPos[0],self.dragShape.pos[1] + evt.GetPosition()[1] - self.dragStartPos[1]
            )

        self.dragShape.shown = True
        self.RefreshRect(self.dragShape.GetRect())
        self.dragShape = None

    # Fired whenever a paint event occurs
    def OnPaint(self,evt):
        print "On paint!"

        dc = wx.PaintDC(self)
        self.PrepareDC(dc)
        self.DrawShapes(dc)

    # Left mouse button is down.
    def OnLeftDown(self,evt):
        print "On left down!"

        # Did the mouse go down on one of our shapes?
        shape = self.FindShape(evt.GetPosition())

        # If a shape was 'hit',then set that as the shape we're going to
        # drag around. Get our start position. Dragging has not yet started.
        # That will happen once the mouse moves,OR the mouse is released.
        if shape:
            self.dragShape = shape
            self.dragStartPos = evt.GetPosition()

    # Go through our list of shapes and draw them in whatever place they are.
    def DrawShapes(self,dc):
        for shape in self.shapes:
            if shape.shown:
                shape.Draw(dc)

    # This is actually a sophisticated 'hit test',but in this
    # case we're also determining which shape,if any,was 'hit'.
    def FindShape(self,pt):
        for shape in self.shapes:
            if shape.HitTest(pt):
                return shape
        return None

    # Clears the background,then redraws it. If the DC is passed,then
    # we only do so in the area so designated. Otherwise,it's the whole thing.
    def OnEraseBackground(self,evt):
        dc = evt.GetDC()
        if not dc:
            dc = wx.ClientDC(self)
            rect = self.GetUpdateRegion().GetBox()
            dc.SetClippingRect(rect)
        self.TileBackground(dc)

    # tile the background bitmap
    def TileBackground(self,dc):
        sz = self.GetClientSize()
        w = self.bg_bmp.GetWidth()
        h = self.bg_bmp.GetHeight()

        x = 0

        while x < sz.width:
            y = 0

            while y < sz.height:
                dc.DrawBitmap(self.bg_bmp,x,y)
                y = y + h

            x = x + w

    # We're not doing anything here,but you might have reason to.
    # for example,if you were dragging something,you might elect to
    # 'drop it' when the cursor left the window.
    def OnLeaveWindow(self,evt):
        pass

class IdTimelinePanel(wx.Panel):
    def __init__(self,size = (400,200))
        self.SetBackgroundColour((255,255))

        lbl1 = wx.StaticText(self,label="Position")
        lbl2 = wx.StaticText(self,label="Size")

        posPnlSzr = wx.BoxSizer(wx.VERTICAL)
        posPnlSzr.Add(lbl1,wx.FIXED&wx.LEFT)
        posPnlSzr.Add(lbl2,wx.FIXED&wx.LEFT)

        self.SetSizer(posPnlSzr)

        #wx.StaticText(self,"This is the horizontal ID space for the timeline")
        self.SetAutoLayout(1)

class TimelinePanel(scrolled.ScrolledPanel):
    def __init__(self,parent):
        scrolled.ScrolledPanel.__init__(self,size = (300,0))

        lbl12 = wx.StaticText(self,label="Position")
        lbl22 = wx.StaticText(self,label="Size")

        posPnlSzr2 = wx.BoxSizer(wx.VERTICAL)
        posPnlSzr2.Add(lbl12,wx.GROW)
        posPnlSzr2.Add(lbl22,wx.GROW)

        self.SetSizer(posPnlSzr2)

        #wx.StaticText(self,"This is the horizontal scroll space for the timeline")
        self.SetAutoLayout(1)
        self.SetupScrolling(scroll_y = False)

class MechanismPanel(scrolled.ScrolledPanel):
    def __init__(self,140))
        self.SetBackgroundColour((211,211,211))

        mechPnlSzr = wx.BoxSizer(wx.HORIZONTAL)

        os.chdir("./figures")
        for file in glob.glob("icon*.png"):
            print file
            imgIcon = wx.Image(file,wx.BITMAP_TYPE_PNG).ConvertToBitmap()
            staticBitmap = wx.StaticBitmap(self,imgIcon,(0,0),(50,50))
            shape = DragShape(staticBitmap.GetBitmap())
            shape.pos = (50,50)
            shape.fullscreen = True
            parent.shapes.append(shape)
            #mechPnlSzr.Add(staticBitmap,wx.FIXED,border = 20)

        self.SetSizer(mechPnlSzr)

        self.SetAutoLayout(1)
        self.SetupScrolling(scroll_y = False)

app = wx.App(False)
frame = MainWindow(None,"Trading Client")
app.MainLoop()

解决方法

您的类都没有实现wx.PyDropTarget接口或包含对拖放所需的wx.FileDataObject()的引用.

我想你想看看演示中的DragAndDrop示例,而不仅仅是DragImage.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读