55341


はじめまして。  
python3.6を使用して、GUIを作成しています。  
Canvasに配置されるobjectsの範囲内で、scrollbarを操作させたいと考えていますが、方法が分かりません。  
以下のコードは、scrollbarにバインドした、canvas_x、canvas_yにおいて、何等か記述すれば細かく制御できるかと思うのです。info関数は、canvasが現在どの範囲のcanvas内座標を表示しているか確認するためのものです。  
bboxメソッドで現在のobjectsの座標範囲が取得できるため、これを利用しようと思うのですが、scrollbarへの移動範囲設定やノブの表示方法が分かりません。  
どなたか実装方法をご存じないでしょうか。  
よろしくお願いします。

Tkinter 8.5
referenceを確認したところ、canvasウィジット作成時に、scrollregionオプションを入れることで、スクロール範囲が設定できることが分かりました。  
ウィジット作成後に、このscrollregionオプションの変更の仕方をご存知であれば、ご教示をお願いいたします。

[code]

    #! /usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import tkinter as tk
    from tkinter import ttk
    
    
    class CreateScreen(object):
        def __init__(self):
            self.screen_w = 800
            self.screen_h = 600
            self.dlg_pos_x = 100
            self.dlg_pos_y = 100
    
            return super().__init__()
    
        def createMainWindow(self):
    
            obj = ttk.tkinter.Tk() 
    
            geo_string = str(self.screen_w) + "x" + str(self.screen_h) + "+" + str(self.dlg_pos_x)  + "+" + str(self.dlg_pos_y) 
    
            obj.geometry(geo_string) 
    
            return obj
    
        def btn_area(self, parent):
            _if_bt_w = int(self.screen_w)
            _if_bt_h = int(self.screen_h)
    
            self._InFrame_ = ttk.Frame(
                parent,
                width = _if_bt_w,
                height = _if_bt_h
                )
    
            self._Canvas = tk.Canvas(
                self._InFrame_,
                background = 'beige',
                scrollregion=(-1000, -500, 1200, 800)
                )
    
            self.canvas = self._Canvas
    
    
            self._InFrame_.grid(row = 0,column = 0, sticky = tk.E+tk.W)
            self._Canvas.grid(row = 0,column = 0, sticky = tk.N+tk.E+tk.S+tk.W)
    
    
            self._InFrame_.columnconfigure(0, minsize = 760)
            self._InFrame_.rowconfigure(0, minsize = 560)
    
    
            self.canvas_v_scroll = ttk.Scrollbar(
                self._InFrame_,
                orient = tk.VERTICAL,
                command = self.canvas_y
                )
    
            self.canvas['yscrollcommand'] = self.canvas_v_scroll.set
    
            self.canvas_h_scroll = ttk.Scrollbar(
                self._InFrame_,
                orient = tk.HORIZONTAL,
                command = self.canvas_x
                )
    
            self.canvas['xscrollcommand'] = self.canvas_h_scroll.set
    
            self.canvas_v_scroll.grid(row = 0,column = 1, sticky = tk.N+tk.E+tk.S+tk.W)
            self.canvas_h_scroll.grid(row = 1,column = 0, sticky = tk.N+tk.E+tk.S+tk.W)
    
            self.maker1 = self.canvas.create_rectangle(200,100,300,200,fill='blue',tags = 'r1')
            self.maker2 = self.canvas.create_rectangle(-100,-100,100,100,fill='green',tags = 'r2')
            self.maker3 = self.canvas.create_rectangle(400,400,250,250,fill='yellow',tags = 'r3')
    
    
            return
    
        def canvas_x(self,*args, **kwargs):
    
            for a in args:
                print(a)
    
            for b in kwargs:
                print(b)
    
            self.canvas.xview(*args, **kwargs)
            self.info()
    
            return
    
        def canvas_y(self,*args, **kwargs):
    
            for a in args:
                print(a)
    
            for b in kwargs:
                print(b)
    
            self.canvas.yview(*args, **kwargs)
            self.info()
    
            return
    
        def info(self):
            x = self.canvas.winfo_x()
            y = self.canvas.winfo_y()
            w = self.canvas.winfo_width()
            h = self.canvas.winfo_height()
            print(x,y,w,h)
    
            cx1 = self.canvas.canvasx(x)
            cy1 = self.canvas.canvasy(y)
            cx2 = self.canvas.canvasx(x+w)
            cy2 = self.canvas.canvasy(y+h)
    
            print(cx1,cy1,cx2,cy2)
            self.canvas.bbox("all")
            return
    
    if __name__ == '__main__':
        screen_obj = CreateScreen()
    
        MainWindow_obj = screen_obj.createMainWindow()
    
        MainFrame = ttk.Frame(
            MainWindow_obj,
            class_ = 'MainApplication',
            borderwidth = 0
            )
    
        screen_obj.btn_area(MainWindow_obj)
    
        MainWindow_obj.mainloop()
    
    
[/code]


CC BY-SA 4.0
2019-05-29T05:30:56.200
55334
2019-05-29T08:16:43.603
2019-05-29T07:49:05.937
32891
32891
question
python3
python3 canvasのobjectsに存在する範囲内でscrollbarを操作させたい


すみません。自己解決してしまいました。

w.configureあるいはw[option]にて、scrollregionオプションを指定すればよいことがわかりました。  
なお、ウィジットの座標系は、mainloop()実行後に正常な値となるため、本ソースコードでは、スクロールバーが押されたらオプションを変更しております。実用上では、.afterでメソッドを呼び出して、mainloop()実行後にオプションを変更します。  
また、動的にscrollregionオプションを変更する場合、ウィジットサイズがscrollregionオプションのサイズの関係および現在の表示座標エリアの整合性を取る工夫が必要のようです。

[code]

    #! /usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import tkinter as tk
    from tkinter import ttk
    
    
    class CreateScreen(object):
        def __init__(self):
            self.screen_w = 800
            self.screen_h = 600
            self.dlg_pos_x = 100
            self.dlg_pos_y = 100
    
            return super().__init__()
    
        def createMainWindow(self):
    
            obj = ttk.tkinter.Tk() 
    
            geo_string = str(self.screen_w) + "x" + str(self.screen_h) + "+" + str(self.dlg_pos_x)  + "+" + str(self.dlg_pos_y) 
    
            obj.geometry(geo_string) 
    
            return obj
    
        def btn_area(self, parent):
            _if_bt_w = int(self.screen_w)
            _if_bt_h = int(self.screen_h)
    
            self._InFrame_ = ttk.Frame(
                parent,
                width = _if_bt_w,
                height = _if_bt_h
                )
    
            self._Canvas = tk.Canvas(
                self._InFrame_,
                background = 'beige'
                )
    
            self.canvas = self._Canvas
    
    
            self._InFrame_.grid(row = 0,column = 0, sticky = tk.E+tk.W)
            self._Canvas.grid(row = 0,column = 0, sticky = tk.N+tk.E+tk.S+tk.W)
    
    
            self._InFrame_.columnconfigure(0, minsize = 760)
            self._InFrame_.rowconfigure(0, minsize = 560)
    
    
            self.canvas_v_scroll = ttk.Scrollbar(
                self._InFrame_,
                orient = tk.VERTICAL,
                command = self.canvas_y
                )
    
            self.canvas['yscrollcommand'] = self.canvas_v_scroll.set
    
            self.canvas_h_scroll = ttk.Scrollbar(
                self._InFrame_,
                orient = tk.HORIZONTAL,
                command = self.canvas_x
                )
    
            self.canvas['xscrollcommand'] = self.canvas_h_scroll.set
    
            self.canvas_v_scroll.grid(row = 0,column = 1, sticky = tk.N+tk.E+tk.S+tk.W)
            self.canvas_h_scroll.grid(row = 1,column = 0, sticky = tk.N+tk.E+tk.S+tk.W)
    
            self.maker1 = self.canvas.create_rectangle(200,100,300,200,fill='blue',tags = 'r1')
            self.maker2 = self.canvas.create_rectangle(-100,-100,100,100,fill='green',tags = 'r2')
            self.maker3 = self.canvas.create_rectangle(600,400,850,650,fill='yellow',tags = 'r3')
    
    
            return
    
        def canvas_x(self,*args, **kwargs):
    
            self.canvas.xview(*args, **kwargs)
    
            self.range = self.canvas.bbox("all")
            w = self._Canvas.winfo_width()
            h = self._Canvas.winfo_height()
    
            dx0 = self.range[0]
            dy0 = self.range[1]
            dx1 = self.range[2]
            dy1 = self.range[3]
    
            dw = dx1-dx0
            dh = dy1-dy0
    
            if dw < w:
                dx1 += w-dw
    
            if dh < h:
                dy1 += h-dh
    
    
            self._Canvas['scrollregion'] = (dx0,dy0,dx1,dy1)
    
            return
    
        def canvas_y(self,*args, **kwargs):
    
            self.canvas.yview(*args, **kwargs)
    
            self.range = self.canvas.bbox("all")
            w = self._Canvas.winfo_width()
            h = self._Canvas.winfo_height()
    
            dx0 = self.range[0]
            dy0 = self.range[1]
            dx1 = self.range[2]
            dy1 = self.range[3]
    
            dw = dx1-dx0
            dh = dy1-dy0
    
            if dw < w:
                dx1 += w-dw
    
            if dh < h:
                dy1 += h-dh
    
    
            self._Canvas['scrollregion'] = (dx0,dy0,dx1,dy1)
    
            return
    
    if __name__ == '__main__':
        screen_obj = CreateScreen()
    
        MainWindow_obj = screen_obj.createMainWindow()
    
        MainFrame = ttk.Frame(
            MainWindow_obj,
            class_ = 'MainApplication',
            borderwidth = 0
            )
    
        screen_obj.btn_area(MainWindow_obj)
    
        MainWindow_obj.mainloop()
    
    
[/code]


CC BY-SA 4.0
2019-05-29T08:16:43.603
55341
2019-05-29T08:16:43.603
32891
55334
answer