2

MS Windows で実行されている wxPython アプリがあり、そのインスタンス間のドラッグ アンド ドロップをサポートしたい (したがって、ユーザーはアプリを 3 回開き、あるインスタンスから別のインスタンスにデータをドラッグします)。

wxPython での単純なドラッグ アンド ドロップは次のように機能します。

  1. ユーザーがドラッグを開始: ソース ウィンドウは、必要なデータを wx.DataObject() にパックし、新しい wx.DropSource を作成し、そのデータを設定して、dropSource.DoDragDrop() を呼び出します。
  2. ユーザーがデータをターゲット ウィンドウにドロップします。ドロップ ターゲットは、実際のデータをその wx.DataObject インスタンスに転送するライブラリ関数 GetData() を呼び出し、最後に - dataObject.GetData() が実際のデータをアンパックします。

ユーザーがドロップにドラッグするデータを選択できる、より洗練されたドラッグアンドドロップが必要です。私の夢
のシナリオ:

  1. ユーザーがドラッグを開始: ソース ウィンドウへのポインターのみがパックされます (関数またはオブジェクト)。
  2. ユーザーがターゲット ウィンドウにデータをドロップ: 適切なダイアログが表示され、どのドラッグ アンド ドロップ モードを選択するかをユーザーに尋ねます (曲のタイトルのみをドラッグするか、曲のタイトルとアーティスト名またはドラッグしたアーティストのアルバム全体をドラッグするかなど)。
  3. ユーザーがドラッグ アンド ドロップ モードを選択します。ドロップ ターゲットは、ドラッグされたデータ オブジェクトに対して何らかの関数を呼び出し、ドラッグ ソースからデータを取得してドロップ ターゲットに転送します。

私の夢のシナリオは MS Windows で実行可能に思えますが、wxWidgets と wxPython のドキュメントはかなり複雑で曖昧です。すべての wx.DataObject クラスが wxPython で利用できるわけではありません (wx.PySimpleDataObject のみ)。そのような動作は、winAPI で直接コーディングすることなく、wxPython で実装できますか?

編集: Toni Ruža は、ドラッグ & ドロップの例で答えを出しましたが、それはまさに私の夢のシナリオではありません。彼のコードはデータがドロップされたときにデータを操作しますが ( HandleDrop()はポップアップ メニューを表示します)、データはドラッグが開始されたときに準備されます ( On_ElementDrag()で)。私のアプリケーションでは、3 つの異なるドラッグ アンド ドロップ モードが必要であり、そのうちのいくつかは時間のかかるデータ準備が必要です。そのため、ユーザーがデータをドロップして (コストがかかる可能性がある) d&d モードを選択するまで、データの取得を延期したいと考えています。

また、メモリ保護の問題については、MS Office のように、プロセス間通信に OLE メカニズムを使用したいと考えています。Excel の図をコピーして、MS-Word に貼り付けると、画像のように動作します (まあまあ)。それが機能するので、winAPIで実行できると思います。wxPythonでコーディングできるかどうかわかりません。

4

2 に答える 2

3

標準のデータ形式の1つを使用してPythonオブジェクトへの参照を保存することはできないため、新しいデータ形式を作成するのではなく、メソッド呼び出しに必要なパラメーターを保存するためにテキストデータ形式を使用することをお勧めします。とにかく、問題のオブジェクトにアクセスできないため、あるアプリから別のアプリにオブジェクトへの参照を渡すのは良くありません(メモリ保護を覚えていますか?)。

要件の簡単な例を次に示します。

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()

On_SimpleCopyやOn_MessWithItなどのメソッドはドロップ後に実行されるため、ドラッグで転送したテキストまたはその他の標準タイプのデータ(私の場合はself._text)に基づいて、実行したい長い操作を実行できます。 ...OLEなし:)

于 2009-01-24T19:59:58.243 に答える
0

わかりました、私が望んでいたようにはできないようです。

考えられる解決策は次のとおりです。

  1. ユーザーがターゲット プロセス ウィンドウにデータをドロップした後、d&d でいくつかのパラメーターを渡し、独自にプロセス間通信を行います。
  2. DataObjectCompositeを使用して複数のドラッグ アンド ドロップ形式をサポートし、キーボード修飾子を使用して現在の形式を選択します。シナリオ:
    1. ユーザーがドラッグを開始します。CTRL、ALT、SHIFT の状態がチェックされ、それに応じて d&d 形式が選択されます。DataObjectComposite が作成され、選択した形式でデータが設定されます。
    2. ユーザーがターゲット ウィンドウにデータをドロップします。ドロップ ターゲットは、ドロップされた DataObject にサポートされている形式を尋ね、その形式を認識してデータを取得します

私はソリューション2.を選択しています。これは、プロセス間の手作業による通信を必要とせず、ユーザーが最も単純なデータのみをドラッグしたい場合に不必要なデータ取得を回避できるためです。

とにかく - トニ、答えてくれてありがとう!少し遊んでみると、d&d と、問題へのアプローチを変えることについて考えさせられました。

于 2009-01-26T14:40:39.423 に答える