Frage

Ich habe WxPython App, die auf MS Windows ausgeführt wird, und ich möchte es per Drag & Drop zwischen den Instanzen unterstützen (so öffnet der Benutzer meine Anwendung 3 Mal und zieht Daten von einer Instanz zur anderen).

Die einfache Drag & Drop in WxPython funktioniert so:

  1. Benutzer initiiert drag : Das Quellfenster notwendige Daten in wx.DataObject () packt, schafft neuer wx.DropSource, ihre Datensätze und ruft dropSource.DoDragDrop ()
  2. Benutzer fällt Daten auf Zielfenster : Die Drop-Ziel nennt Bibliotheksfunktion GetData (), die tatsächlichen Daten an ihre wx.DataObject Instanz überträgt und schließlich - dataObject.GetData (), um die aktuellen Daten entpackt <. / li>

Ich möchte einige anspruchsvollere Drag & Drop haben, die Benutzer erlauben würde, zu wählen, welche Daten gezogen wird nach er fällt.
Szenario von meine Träume :

  1. Benutzer initiiert drag :. Nur einige Zeiger auf das Quellfenster gepackt ist (eine Funktion oder ein Objekt)
  2. Benutzer fällt Daten auf Zielfenster : Nice Dialog wird angezeigt, welcher Benutzer fragt, die Drag & Drop-Modus wählt er (wie - nur Titel, oder Songtitel und den Künstlernamen oder ganze Album des gezogenen ziehen Künstler).
  3. Benutzer wählen Drag & Drop-Modus : Drop-Ziel eine Funktion auf dem gezogenen Daten-Objekt aufruft, die dann Daten aus der Drag-Quelle abruft und überträgt sie auf das Drop-Ziel
  4. .

Das Szenario meiner Träume scheint machbar in MS Windows, aber die Dokumentation für wxWidgets und WxPython sind ziemlich komplex und mehrdeutig. Nicht alle wx.DataObject Klassen sind in wxPython (nur wx.PySimpleDataObject), so möchte ich jemand seine Erfahrungen mit einem solchen Ansatz zu teilen. Kann ein solches Verhalten in WxPython umgesetzt werden, ohne dass es direkt in winapi kodieren zu müssen?

EDIT: Toni Ruža gab eine Antwort mit Arbeits Drag & Drop-Beispiel, aber das ist nicht genau das Szenario von meine Träume . Sein Code manipuliert Daten, wenn sie fallen gelassen (die HandleDrop () Popup-Menü zeigt), aber die Daten vorbereitet wird, wenn Drag eingeleitet wird (in On_ElementDrag () ). In meiner Anwendung soll es drei verschiedene Drag & Drop-Modus sein, und einige von ihnen erfordern zeitaufwendige Datenaufbereitung. Deshalb mag ich den Datenabruf verschieben, um den Moment Benutzerdaten fallen und wählen (potenziell kostspieliger) d & d-Modus.

Und für Speicherschutz Problem - ich will Inter-Prozess-Kommunikation OLE-Mechanismen verwenden, wie MS Office tut. Sie können Excel-Diagramm kopieren und fügen Sie ihn in MS-Word, wo es wie ein Bild verhält (na ja, eine Art). Da es funktioniert ich glaube, es kann in winapi erfolgen. Ich weiß nur nicht, ob ich es in WxPython codieren kann.

War es hilfreich?

Lösung 2

Ok, es scheint, dass es nicht so, wie ich es wollte, durchgeführt werden.

Mögliche Lösungen sind:

  1. Führen Sie einige Parameter in d & d und einige Inter-Prozess-Kommunikation auf eigene Faust, nach Benutzerdaten in Soll-Prozesse Fenster fällt.
  2. Verwenden Sie DataObjectComposite mehrere Drag & Drop-Formate und Tastatur unterstützen Modifikatoren aktuelles Format zu wählen. Szenario:
    1. Benutzer initiiert ziehen. State of STRG, ALT und SHIFT aktiviert ist, und je nach ihm das d & d-Format ausgewählt ist. DataObjectComposite erstellt wird, und hat in ausgewählten Format eingestellten Daten.
    2. User fällt Daten in Zielfenster. Drop-Ziel für Datenobjekt unterstützten Format und ruft Daten fallen gelassen fragt, wissen , welches Format es ist in.

Ich bin die Lösung der Wahl 2. , weil es erfordert keine Hand Kommunikation zwischen Prozessen Handwerk und es erlaubt mir unnötigen Datenabruf zu vermeiden, wenn Benutzer nur die einfachstenen Daten ziehen wollen.

Wie auch immer - Toni, vielen Dank für Ihre Antwort! Spielte mit ihm ein wenig und es machte mich von d denken & d und meine Herangehensweise an das Problem zu ändern.

Andere Tipps

Da Sie nicht eine der Standard Datenformate Verweise auf python-Objekte zu speichern ich Sie die Parameter für Ihre Methode ein Textdatenformat verwenden, zum speichern benötigen Sie ruft vielmehr ein neues Datenformat als machen würde empfehlen. Und überhaupt, wäre es nicht gut, einen Verweis auf ein Objekt von einer Anwendung zu einem anderen als das betreffenden Objekt nicht zugänglich sein würde passieren (nicht vergessen, Speicherschutz?).

Hier ist ein einfaches Beispiel für Ihre Anforderungen:

import wx


class TestDropTarget(wx.TextDropTarget):
    def OnDropText(self, x, y, text):
        wx.GetApp().TopWindow.HandleDrop(text)

    def OnDragOver(self, x, y, d):
        return wx.DragCopy


class Test(wx.Frame):
    def __init__(self):
        wx.Frame.__init__(self, None)

        self.numbers = wx.ListCtrl(self, style = wx.LC_ICON | wx.LC_AUTOARRANGE)
        self.field = wx.TextCtrl(self)

        sizer = wx.FlexGridSizer(2, 2, 5, 5)
        sizer.AddGrowableCol(1)
        sizer.AddGrowableRow(0)
        self.SetSizer(sizer)
        sizer.Add(wx.StaticText(self, label="Drag from:"))
        sizer.Add(self.numbers, flag=wx.EXPAND)
        sizer.Add(wx.StaticText(self, label="Drag to:"), flag=wx.ALIGN_CENTER_VERTICAL)
        sizer.Add(self.field)

        for i in range(100):
            self.numbers.InsertStringItem(self.numbers.GetItemCount(), str(i))

        self.numbers.Bind(wx.EVT_LIST_BEGIN_DRAG, self.On_ElementDrag)
        self.field.SetDropTarget(TestDropTarget())

        menu_id1 = wx.NewId()
        menu_id2 = wx.NewId()
        self.menu = wx.Menu()
        self.menu.AppendItem(wx.MenuItem(self.menu, menu_id1, "Simple copy"))
        self.menu.AppendItem(wx.MenuItem(self.menu, menu_id2, "Mess with it"))
        self.Bind(wx.EVT_MENU, self.On_SimpleCopy, id=menu_id1)
        self.Bind(wx.EVT_MENU, self.On_MessWithIt, id=menu_id2)

    def On_ElementDrag(self, event):
        data = wx.TextDataObject(self.numbers.GetItemText(event.Index))
        source = wx.DropSource(self.numbers)
        source.SetData(data)
        source.DoDragDrop()

    def HandleDrop(self, text):
        self._text = text
        self.PopupMenu(self.menu)

    def On_SimpleCopy(self, event):
        self.field.Value = self._text

    def On_MessWithIt(self, event):
        self.field.Value = "<-%s->" % "".join([int(c)*c for c in self._text])


app = wx.PySimpleApp()
app.TopWindow = Test()
app.TopWindow.Show()
app.MainLoop()

Methoden wie On_SimpleCopy und On_MessWithIt nach dem Drop ausgeführt werden soll, so längere Arbeits Operationen Sie vielleicht tun können Sie es tun, basierend auf dem Text oder einen anderen Standard-Typ von Daten, die Sie mit dem Drag übertragen (self._text in meinem Fall) und schauen ... kein OLE:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top