tkinter文本小部件:盒子选择的多行闪烁式镜头

发布于 2025-02-10 22:42:17 字数 233 浏览 2 评论 0原文

我为tk.text创建了一个框选择功能。小部件获取font高度,并从中构建.xbm图像。 .xbm通过image_create用于所有选定的行,除了真正的行人所在的行之外。

如何使人造图像实例(s)与真实的商人眨眼?

还是

我可以朝着这些结果迈出的另一个方向?

I've created a box-select feature for tk.Text. The widget gets the font height and concocts an .xbm image from it. The .xbm is used as a faux-caret, via image_create, for all selected lines except the line the real caret is on.

How do I make the faux-caret image instance(s) blink in time with the real caret?

or

What is another direction I can go to get these results?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

悲欢浪云 2025-02-17 22:42:17

我的解决方案是明显地摆脱了真正的脑袋,在每一行上画一个人造镜头,然后调用一个函数,该功能不断用“ Off”的人造毛衣来交换“ On”人造毛衣。以下是一些相关的代码段。注意:我实际上有3个人造牌,因为我想要真正的活动线上的镜头更暗。

    #FAUX-CARET
    #concoct, load, assign, and delete xbm for faux-caret
    def __loadcarets(self) -> None:
        #store insert on/off times for faux-caret `.after` calls
        self.__instime = (self['insertofftime'], self['insertontime'])
        
        fh = self.__fh    #font height from 'linespace'
        
        #make a temp xbm file
        with tempfile.NamedTemporaryFile(mode='w+b', suffix='.xbm', delete=False) as f:
            #create prettyprint xbm data
            xbmdata = ',\n\t'.join(','.join('0xFF' for _ in range(min(8, fh-(8*i)))) for i in range(math.ceil(fh/8)))
            #write xbm
            f.write((f"#define image_width {INSWIDTH}\n#define image_height {fh}\n"
                     "static unsigned char image_bits[] = {\n\t"
                     f'{xbmdata}}};').encode())
                     
        #load xbm files for faux-caret ~ they have to be in this order 
        #I gave this a placeholder name because you should never have to access this directly
        #__fauxcaret does everything          
        self.__  = (tk.BitmapImage(file=f.name, foreground='#999999'),                   #shadow caret 
                    tk.BitmapImage(file=f.name, foreground=self['background']),          #off caret
                    tk.BitmapImage(file=f.name, foreground=self['insertbackground']))    #main caret  
        
        #delete file
        os.unlink(f.name)
    
    #faux-caret create or config
    def __fauxcaret(self, index:str, on:bool=True, main:bool=False, cfg:bool=False) -> None:
        (self.image_create, self.image_configure)[cfg](index, image=self.__[(main<<on)|(on^1)])
    
    #blink the faux-caret(s)
    def __blink(self, on:bool=True):
        #nothing to do
        if not self.__boxselect: return
        
        #so we only do this once per first blink
        if not self.__blinksrt:
            #sort image indexes
            self.__blinksrt = sorted((self.index(n) for n in self.image_names()), key=float)
            
        if idx:=self.__blinksrt:
            #flip `on`
            on = not on
            #consider direction in forward perspective
            fw = not self.__lbounds.rv
            #reconfigure all carets
            for i in idx: self.__fauxcaret(i, on=on, cfg=True)
            #reconfigure "active line" caret, if off it will assign off again
            self.__fauxcaret(idx[-fw], on=on, main=True, cfg=True)
            #schedule next call
            self.__blinkid = self.after(self.__instime[on], self.__blink, on)
            return
            
        raise ValueError('__blink: Nothing to sort!')
    
    #reset blink
    def __blinkreset(self) -> None:
        #cancel after
        self.after_cancel(self.__blinkid)
        #reset blinksort
        self.__blinksrt  = None
   

My solution was to get rid of the real caret visibly, draw a faux caret on every line, and then call a function that keeps swapping out an 'on' faux-caret with an 'off' faux-caret. Below are some relevant code snippets. Note: I actually have 3 faux-carets because I want the caret that is on the true active line to be a little darker.

    #FAUX-CARET
    #concoct, load, assign, and delete xbm for faux-caret
    def __loadcarets(self) -> None:
        #store insert on/off times for faux-caret `.after` calls
        self.__instime = (self['insertofftime'], self['insertontime'])
        
        fh = self.__fh    #font height from 'linespace'
        
        #make a temp xbm file
        with tempfile.NamedTemporaryFile(mode='w+b', suffix='.xbm', delete=False) as f:
            #create prettyprint xbm data
            xbmdata = ',\n\t'.join(','.join('0xFF' for _ in range(min(8, fh-(8*i)))) for i in range(math.ceil(fh/8)))
            #write xbm
            f.write((f"#define image_width {INSWIDTH}\n#define image_height {fh}\n"
                     "static unsigned char image_bits[] = {\n\t"
                     f'{xbmdata}}};').encode())
                     
        #load xbm files for faux-caret ~ they have to be in this order 
        #I gave this a placeholder name because you should never have to access this directly
        #__fauxcaret does everything          
        self.__  = (tk.BitmapImage(file=f.name, foreground='#999999'),                   #shadow caret 
                    tk.BitmapImage(file=f.name, foreground=self['background']),          #off caret
                    tk.BitmapImage(file=f.name, foreground=self['insertbackground']))    #main caret  
        
        #delete file
        os.unlink(f.name)
    
    #faux-caret create or config
    def __fauxcaret(self, index:str, on:bool=True, main:bool=False, cfg:bool=False) -> None:
        (self.image_create, self.image_configure)[cfg](index, image=self.__[(main<<on)|(on^1)])
    
    #blink the faux-caret(s)
    def __blink(self, on:bool=True):
        #nothing to do
        if not self.__boxselect: return
        
        #so we only do this once per first blink
        if not self.__blinksrt:
            #sort image indexes
            self.__blinksrt = sorted((self.index(n) for n in self.image_names()), key=float)
            
        if idx:=self.__blinksrt:
            #flip `on`
            on = not on
            #consider direction in forward perspective
            fw = not self.__lbounds.rv
            #reconfigure all carets
            for i in idx: self.__fauxcaret(i, on=on, cfg=True)
            #reconfigure "active line" caret, if off it will assign off again
            self.__fauxcaret(idx[-fw], on=on, main=True, cfg=True)
            #schedule next call
            self.__blinkid = self.after(self.__instime[on], self.__blink, on)
            return
            
        raise ValueError('__blink: Nothing to sort!')
    
    #reset blink
    def __blinkreset(self) -> None:
        #cancel after
        self.after_cancel(self.__blinkid)
        #reset blinksort
        self.__blinksrt  = None
   
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文