web-dev-qa-db-ja.com

アプリケーションに切り取り/コピー/貼り付け機能を追加するにはどうすればよいですか?

私はPython 2.7、Gtk + 3、Gladeを使用して選挙電卓( https://launchpad.net/electoralcalculator )を開発しており、カット/コピー/貼り付けを追加したいアプリケーションの機能。

メニュー項目(編集>切り取り、編集>コピー、および編集>貼り付け)、ツールバーボタンまたはキーボードショートカット(Ctrl + X、Ctrl + C、Ctrl +)を使用して、テキストを切り取り/コピー/貼り付けする機会をユーザーに与えたいV)。

選択したテキストを取得して切り取り/コピーするにはどうすればよいですか?多くのテキスト入力ウィジェットがあり、選択したテキストはそれらのいずれかに入れることができます。

カーソルの場所を知るにはどうすればよいので、クリップボードの内容をそこに貼り付けることができますか?

私はこの例について見つけました:
http://python-gtk-3-tutorial.readthedocs.org/en/latest/clipboard.html

しかし、この例ではテキスト入力ウィジェットは1つしかありませんが、私のアプリケーションにはたくさんあります。
選択したテキストがどこにあるか(どのテキスト入力ウィジェットで)それを切り取り/コピーするかを知るにはどうすればよいですか?
貼り付け機能のカーソルの位置を確認するにはどうすればよいですか?

英語は私の第一言語ではありません。エラーをお許しください。

ご協力いただきありがとうございます

編集:
Ian/Timoのコードに基づいて切り取り、コピー、貼り付けのボタンを使用した例を作成しました。
ご協力いただき、ティモとイアンB.に感謝します。ほんとうにありがとう。

例に何か問題があるかどうかを教えてください。

キーボードショートカット(Ctrl + X、Ctrl + C、およびCtrl + V)は、コードを追加せずに自動的に機能します。

from gi.repository import Gtk, Gdk

class TwotextWindow(Gtk.Window):
    __gtype_= "TwotextWindow"

    def __init__(self):
        super(TwotextWindow, self).__init__()
        self.connect('delete-event', Gtk.main_quit)

        self.vbox = Gtk.VBox(False, 8)
        for x in range(4):
            self._build_entry()

        button_cut = Gtk.Button(label='Cut')
        button_cut.connect('clicked', self.on_cut_clicked)
        self.vbox.pack_start(button_cut, False, False, 0)

        button_copy = Gtk.Button(label='Copy')
        button_copy.connect('clicked', self.on_copy_clicked)
        self.vbox.pack_start(button_copy, False, False, 0)

        button_paste = Gtk.Button(label='Paste')
        button_paste.connect('clicked', self.on_paste_clicked)
        self.vbox.pack_start(button_paste, False, False, 0)

        self.add(self.vbox)
        self.show_all()

        # Code for other initialization actions should be added here.
        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)

    def _build_entry(self):
        entry = Gtk.Entry(text='Hello, World!')
        entry.connect('focus-in-event', self.on_entry_focus)
        self.vbox.pack_start(entry, False, False, 0)

    def on_cut_clicked(self, widget):
        # Get the bounds of the selected text
        bounds = self.focus.get_selection_bounds()

        # if the bounds of the selection are not an empty Tuple,
        # put the selection in the variable chars
        # and copy it to the clipboard
        # (get_selection_bounds returns an empty Tuple if there is no selection)
        # then delete the selection
        if bounds:
            chars = self.focus.get_chars(*bounds)
            print "Copying '%s' from: %s" % (chars, self.focus)
            self.clipboard.set_text(chars, -1)
            print "Deleting text selection: characters from position %s to %s" % (bounds[0], bounds[1])
            self.focus.delete_text(bounds[0], bounds[1])
        else:
            print "Can't cut if you don't select text"

    def on_copy_clicked(self, widget):
        # Get the bounds of the selected text
        bounds = self.focus.get_selection_bounds()

        # if the bounds of the selection are not an empty Tuple,
        # put the selection in the variable chars
        # and copy it to the clipboard
        # (get_selection_bounds returns an empty Tuple if there is no selection)
        if bounds:
            chars = self.focus.get_chars(*bounds)
            print "Copying '%s' from: %s" % (chars, self.focus)
            self.clipboard.set_text(chars, -1)
        else:
            print "Can't copy if you don't select text"

    def on_paste_clicked(self, widget):
        # Get the text from the clipboard
        text = self.clipboard.wait_for_text()

        if text != None:
            # If there's text selected in the target
            # delete it and paste the contents of the clipboard
            bounds = self.focus.get_selection_bounds()
            if bounds:
                print "Deleting text selection: characters from position %s to %s" % (bounds[0], bounds[1])
                self.focus.delete_text(bounds[0], bounds[1])
                print "Pasting '%s' into: '%s' at the position %s" % (text, self.focus, bounds[0])
                self.focus.insert_text(text, bounds[0])

            # else insert the text in the current position of the cursor in the target
            else:
                pos = self.focus.get_position()
                #print "Cursor position in the target: %s" % pos
                print "Pasting '%s' into: '%s' at the position %s" % (text, self.focus, pos)
                self.focus.insert_text(text, pos)
        else:
            print "No text on the clipboard."

    def on_entry_focus(self, widget, event):
        print "Focused:", widget
        self.focus = widget


if __== '__main__':
    win = TwotextWindow()
    Gtk.main()

内部変数を使用して最後のアクティブなウィジェットを保存するのはどうですか?エントリのイベント内フォーカス信号(キーボードがフォーカスを取得するとき)を使用して、その変数の名前を変更します(すべてのテキストエントリに共通のコールバックを使用できます)。次に、何かをコピーまたは貼り付ける必要がある場合、その変数を使用して(getattrを介して)どこに配置するかを知ることができます。これが私が作り上げた小さな例です。

スタンドアロンで動作して質問を解決するために編集された元のコード

from gi.repository import Gtk, Gdk

class TwotextWindow(Gtk.Window):
    __gtype_= "TwotextWindow"

    def __init__(self):
        super(TwotextWindow, self).__init__()
        self.connect('delete-event', Gtk.main_quit)

        self.vbox = Gtk.VBox(False, 8)
        for x in range(4):
            self._build_entry()

        button = Gtk.Button(label='Copy')
        button.connect('clicked', self.on_copy_clicked)
        self.vbox.pack_start(button, False, False, 0)

        self.add(self.vbox)
        self.show_all()

        # Code for other initialization actions should be added here.
        self.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)

    def _build_entry(self):
        entry = Gtk.Entry(text='Hello, World!')
        entry.connect('focus-in-event', self.on_entry_focus)
        self.vbox.pack_start(entry, False, False, 0)

    def on_copy_clicked(self, widget):
        bounds = self.focus.get_selection_bounds()
        chars = self.focus.get_chars(*bounds)
        print "Copying '%s' from: %s" % (chars, self.focus)
        #TODO: do the actual copying

    def on_entry_focus(self, widget, event):
        print "Focused:", widget
        self.focus = widget


if __== '__main__':
    win = TwotextWindow()
    Gtk.main()

これを行うためのより良い方法があるかどうかわからない。私もこれにかなり慣れています。

2
Ian B.