Pythonといくつかのtclを使用して作成されたCanvasウィジェットとTextウィジェットで新しいクラスオブジェクトを作成する際の問題?

prerakl123

tkinter.Canvas行番号用に追加されたテキストエディタを作成しました。tkinter.Textウィジェットtkinter.Canvasはの中にありtkinter.Frame、そのフレームはtkinter.ttk.Notebookタブに追加されていました追加しようとした[ノートブック]タブから切り取ったコードは次のとおりです。

from tkinter import *
import tkinter as tk


class LineNumberCanvas(Canvas):
    def __init__(self, *args, **kwargs):
        Canvas.__init__(self, *args, **kwargs)
        self.text_widget = None
        self.breakpoints = []

    def connect(self, text_widget):
        self.text_widget = text_widget

    def re_render(self):
        """Re-render the line canvas"""
        self.delete('all') # To prevent drawing over the previous canvas

        temp = self.text_widget.index("@0, 0")
        while True :
            dline= self.text_widget.dlineinfo(temp)
            if dline is None: 
                break
            y = dline[1]
            x = dline[0]
            linenum = str(temp).split(".")[0]

            id = self.create_text(2, y, anchor="nw", text=linenum, font='Consolas 13')

            if int(linenum) in self.breakpoints:                
                x1, y1, x2, y2 = self.bbox(id)
                self.create_oval(x1, y1, x2, y2, fill='red')
                self.tag_raise(id)

            temp = self.text_widget.index("%s+1line" % temp)

    def get_breakpoint_number(self,event):
         if self.find_withtag('current'):
            i = self.find_withtag('current')[0]
            linenum = int(self.itemcget(i,'text'))

            if linenum in self.breakpoints:
                self.breakpoints.remove(linenum)
            else:
                self.breakpoints.append(linenum)
            self.re_render()
            
            

class CustomText:
    def __init__(self, text):
        self.text = text
        self.master = text.master
        self.mechanise()
        self._set_()
        self.binding_keys()

    def mechanise(self):
        self.text.tk.eval('''
            proc widget_interceptor {widget command args} {

                set orig_call [uplevel [linsert $args 0 $command]]

              if {
                    ([lindex $args 0] == "insert") ||
                    ([lindex $args 0] == "delete") ||
                    ([lindex $args 0] == "replace") ||
                    ([lrange $args 0 2] == {mark set insert}) || 
                    ([lrange $args 0 1] == {xview moveto}) ||
                    ([lrange $args 0 1] == {xview scroll}) ||
                    ([lrange $args 0 1] == {yview moveto}) ||
                    ([lrange $args 0 1] == {yview scroll})} {

                    event generate  $widget <<Changed>>
                }

                #return original command
                return $orig_call
            }
            ''')
        self.text.tk.eval('''
            rename {widget} new
            interp alias {{}} ::{widget} {{}} widget_interceptor {widget} new
        '''.format(widget=str(self.text)))
        return


    def binding_keys(self):
        for key in ['<Down>', '<Up>', "<<Changed>>", "<Configure>"]:
            self.text.bind(key, self.changed)
        self.linenumbers.bind('<Button-1>', self.linenumbers.get_breakpoint_number)
        return

    def changed(self, event):
        self.linenumbers.re_render()
        #print "render"
        return


    def _set_(self):
        self.linenumbers = LineNumberCanvas(self.master, width=30)
        self.linenumbers.connect(self.text)
        self.linenumbers.pack(side="left", fill="y")
        return       


if __name__ == '__main__':
    root = Tk()
    l = Text(root, font='Consolas 13')
    CustomText(l)
    l.pack(expand=TRUE, fill=BOTH)
    root.mainloop()

ここでの問題は、tcl言語がわからないことと、プログラムが生成するエラーがCustomTextクラスのmechanise関数にあり、「new」キーワードがあることです。それは言う:

  File "C:\Users\Prerak\AppData\Local\Programs\Python\Python37\EZ_PY\ColorText.py", line 590, in mechanise
    '''.format(widget=str(self)))
_tkinter.TclError: can't rename to "new": command already exists

誰かplsがこれを解決するのを手伝ってくれますか...そして私がしているのは、CustomTextオブジェクトがtkinter.Notebookタブに追加されているボタンをクリックした後に新しいタブを追加することだけです。

ドナーフェロー

問題はそれが何であるかということです:Tclインタープリターにはすでに。というコマンドがありnewます。これは基本のTclコマンドセットの一部ではないため、デフォルトでロードされているパッケージからのものである可能性があります。それが何であれ、それがあなたのものでない場合は、おそらくそのままにしておく必要があります。そうしないと、何か他のものが壊れてしまいます。

これを処理する最も簡単な方法は、一意のカウンターを使用して、インターセプトされたすべてのウィジェットが一意のものを取得することです(これはgensymLispで行うことと類似しています)。この問題はTcl側で発生するため、そのカウンターをその側に保持できますinstall_widget_interceptorこれを行う便利な方法には、2番目の手順を作成することが含まれますこれをと呼びますボーナスとして、それを利用するための呼び出しがより簡単になりCustomText、一度に2つのインスタンスを持つことができるようになります。

(…変更されないコードを省略し、widget_interceptor手順をもう少し慣用的にするように整理しました…)

    # You probably shouldn't repeat this bit every time you create a widget
    self.text.tk.eval('''
        proc widget_interceptor {widget command args} {
            set orig_call [uplevel 1 [linsert $args 0 $command]]
            if {
                [lindex $args 0] in {insert delete replace} ||
                ([lrange $args 0 2] == {mark set insert}) || 
                ([lrange $args 0 1] == {xview moveto}) ||
                ([lrange $args 0 1] == {xview scroll}) ||
                ([lrange $args 0 1] == {yview moveto}) ||
                ([lrange $args 0 1] == {yview scroll})
            } then {
                event generate $widget <<Changed>>
            }
            #return original command
            return $orig_call
        }
        proc install_widget_interceptor {widget} {
            global unique_widget_id
            set handle ::_intercepted_widget_[incr unique_widget_id]
            rename $widget $handle
            interp alias {} ::$widget {} widget_interceptor $widget $handle
        }
        ''')

    # This bit you absolutely need each time
    self.text.tk.eval('''
        install_widget_interceptor {widget}
    '''.format(widget=str(self.text)))

コードに記載されているように、Tcl側でのプロシージャの作成は、Pythonクラスの作成時に1回だけ実行する必要があります。毎回それを行うことは重要ではありません。ただ無駄です。

また、Tk自体は<<Modified>>、テキストウィジェットが変更されると、それらのイベントを生成します。モデルのビューではなく、管理するモデルへの変更に焦点を当てて、重要なものの異なる感覚を使用します(したがって、カーソルを移動したりスクロールしたりしてもトリガーされません)。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ