scrollbar dependencies

M

Marion

Hello.

I am using Tkinter and Pmw.
I would like to build 2 canvases/frames that are scrollable together
horizontally, and independently vertically (so, the vertical
scrollbars should not be moved by the horizontal one).

So I built a Pmw.ScrolledFrame() containing the 2 canvases,
horizontally scrollable. Now I am trying to build 2 independent
vertical scrollbars,
--> wich command is linked to each canvas (whose parent is
Pmw.ScrolledFrame.component('frame'),
--> and which parent is root (to be packed outside the Pmw.ScrolledFrame).

Is this possible or not ? If not, does somebody allready did that another way ?

Thanks a lot.

Marion.
 
E

Eric Brunel

Hello.

I am using Tkinter and Pmw.
I would like to build 2 canvases/frames that are scrollable together
horizontally, and independently vertically (so, the vertical
scrollbars should not be moved by the horizontal one).

So I built a Pmw.ScrolledFrame() containing the 2 canvases,
horizontally scrollable.

I'd not go that way: a Pmw.ScrolledFrame is not supposed to be used this way, and you may have great troubles making it work as you want...

[snip]
Is this possible or not ? If not, does somebody allready did that another way ?

Here is a solution using only pure-Tkinter:

--DualCanvas.py--------------------------------------------------
from Tkinter import *

## Main window
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(0, weight=1)

## First canvas
c1 = Canvas(root, width=200, height=100, bd=2, relief=SUNKEN,
scrollregion=(0, 0, 500, 500))
c1.grid(row=0, column=0, sticky='nswe')

## Second canvas
c2 = Canvas(root, width=200, height=100, bd=2, relief=SUNKEN,
scrollregion=(0, 0, 500, 500))
c2.grid(row=1, column=0, sticky='nswe')

## Special function scroll both canvases horizontally
def xscrollboth(*args):
c1.xview(*args)
c2.xview(*args)

## Horizontal scrollbar for both canvases
hScroll = Scrollbar(root, orient=HORIZONTAL, command=xscrollboth)
hScroll.grid(row=2, column=0, sticky='we')

## Vertical scrollbars
vScroll1 = Scrollbar(orient=VERTICAL, command=c1.yview)
vScroll1.grid(row=0, column=1, sticky='ns')

vScroll2 = Scrollbar(orient=VERTICAL, command=c2.yview)
vScroll2.grid(row=1, column=1, sticky='ns')

## Associate scrollbars to canvases
c1.configure(xscrollcommand=hScroll.set, yscrollcommand=vScroll1.set)
c2.configure(xscrollcommand=hScroll.set, yscrollcommand=vScroll2.set)

## Put a few things in canvases so that we see what's going on
c1.create_oval(80, 80, 120, 120, fill='red')
c1.create_oval(380, 80, 420, 120, fill='red')
c1.create_oval(80, 380, 120, 420, fill='red')
c1.create_oval(380, 380, 420, 420, fill='red')

c2.create_oval(80, 80, 120, 120, fill='blue')
c2.create_oval(380, 80, 420, 120, fill='blue')
c2.create_oval(80, 380, 120, 420, fill='blue')
c2.create_oval(380, 380, 420, 420, fill='blue')

## Go!
root.mainloop()
 
H

Harlin Seritt

Pardon a question I should already know the answer to, but what are the
*args in the:

def xscrollboth(*args):
c1.xview(*args)
c2.xview(*args)

Thanks,

Harlin
 
E

Eric Brunel

Pardon a question I should already know the answer to, but what are the
*args in the:

def xscrollboth(*args):
c1.xview(*args)
c2.xview(*args)

Thanks,

Harlin

If your question is about the syntax, it's just the way of passing any number of arguments to a function as explained in:
http://docs.python.org/tut/node6.html#SECTION006730000000000000000

If your question is about what will actually be passed in these arguments, the answer is simply: I don't know, and I don't care. That's why I used a *args: I just want to pass to the c1.xview and c2.xview methods exactly what was passed to my xscrollboth function. Since Python allows me to just pass the list of arguments unchanged, I happily do it.
 
M

Marion

Thanks a lot, Eric Brunel.
Harlin, if it's still actual (don't think so, but whoever...) here is
a simple code that works.
---------------------------------------
from Tkinter import *

## Main window
root = Tk()
root.grid_rowconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=1)
root.grid_columnconfigure(0, weight=1)

## First canvas
c1 = Canvas(root, width=200, height=100, bd=2, relief=SUNKEN,
scrollregion=(0, 0, 500, 500))
c1.grid(row=0, column=0, sticky='nswe')

## Second canvas
c2 = Canvas(root, width=200, height=100, bd=2, relief=SUNKEN,
scrollregion=(0, 0, 500, 500))
c2.grid(row=1, column=0, sticky='nswe')

## Special function scroll both canvases horizontally
def xscrollboth(self,*args):
c1.xview(self,*args)
c2.xview(self,*args)

## Horizontal scrollbar for both canvases
hScroll = Scrollbar(root, orient=HORIZONTAL, command=xscrollboth)
hScroll.grid(row=2, column=0, sticky='we')

## Vertical scrollbars
vScroll1 = Scrollbar(orient=VERTICAL, command=c1.yview)
vScroll1.grid(row=0, column=1, sticky='ns')
c1.config(yscrollcommand=vScroll1.set,xscrollcommand=hScroll.set)

vScroll2 = Scrollbar(orient=VERTICAL, command=c2.yview)
vScroll2.grid(row=1, column=1, sticky='ns')
c2.config(yscrollcommand=vScroll2.set,xscrollcommand=hScroll.set)

root.mainloop()
---------------------------------------
 
M

Marion

Next mystery :
a picture drawn in the canvas c1 is scrollable.
a picture-containing canvas "grided" in the canvas c1 is not.

so why ???
Marion
---------------------------------------------------------------
from tkinter import *
from PIL import *

class Main:
def __init__(self):
## Main window
self.root = Tk()
self.root.grid_rowconfigure(0, weight=1)
self.root.grid_rowconfigure(1, weight=1)
self.root.grid_columnconfigure(0, weight=1)
## datas :
self.PIC=[]
self.ANN=[]

## First canvas (picture)
self.c1 = Canvas(
self.root,
width=500,
height=100,
bd=2,
relief=SUNKEN,
scrollregion=(0, 0, 100, 100))

self.c1.grid(
row=0,rowspan=2,
column=1,
sticky='nswe')

#-------------------------------#
# this is scrollable :
#-------------------------------#
image =Image.new("RGB",(100,100))
dessin = ImageDraw.Draw(image)
dessin.rectangle([(10,10),(50,50)],fill="rgb(255,0,0)")
photo=ImageTk.PhotoImage(image)
item = self.c1.create_image(0,0,anchor=NW,image=photo)

#-------------------------------#
# this is not ! :
#-------------------------------#
canvas=Canvas(self.c1,background="WHITE")
image =Image.new("RGB",(100,100))
dessin = ImageDraw.Draw(image)
dessin.rectangle([(10,10),(50,50)],fill="rgb(255,0,0)")
photo=ImageTk.PhotoImage(image)
item = canvas.create_image(0,0,anchor=NW,image=photo)
canvas.grid()


## Second canvas (annot)
c2 = Canvas(
self.root,
width=500,
height=100,
bd=2,
relief=SUNKEN,
scrollregion=(0, 0, 1000, 1000))
c2.grid(
row=2,rowspan=2,
column=1,
sticky='nswe')

## Special function scroll both canvases horizontally
def xscrollboth(a,*args):
self.c1.xview(a,*args)
c2.xview(a,*args)

## Horizontal scrollbar for both canvases
hScroll = Scrollbar(self.root, orient=HORIZONTAL, command=xscrollboth)
hScroll.grid(
row=4,rowspan=1,
column=1,
sticky='we')

## Vertical scrollbars
vScroll1 = Scrollbar(orient=VERTICAL, command=self.c1.yview)
vScroll1.grid(
row=0,rowspan=2,
column=2,
sticky='ns')
self.c1.config(yscrollcommand=vScroll1.set,xscrollcommand=hScroll.set)

vScroll2 = Scrollbar(orient=VERTICAL, command=c2.yview)
vScroll2.grid(
row=2,rowspan=2,
column=2,
sticky='ns')
c2.config(yscrollcommand=vScroll2.set,xscrollcommand=hScroll.set)
---------------------------------------------------------------
 
E

Eric Brunel

Next mystery :
a picture drawn in the canvas c1 is scrollable.
a picture-containing canvas "grided" in the canvas c1 is not.

so why ???
Marion
--------------------------------------------------------------- [snip]
#-------------------------------#
# this is not ! :
#-------------------------------#
canvas=Canvas(self.c1,background="WHITE")
image =Image.new("RGB",(100,100))
dessin = ImageDraw.Draw(image)
dessin.rectangle([(10,10),(50,50)],fill="rgb(255,0,0)")
photo=ImageTk.PhotoImage(image)
item = canvas.create_image(0,0,anchor=NW,image=photo)
canvas.grid()

You don't want to do that. Canvases are not meant to be containers where you can pack or grid items. They strangely accept it, but it will never do what you want. If you want to pack or grid items in a container, use a Frame. If you want to include a widget in a Canvas, use a canvas window:

Canvas windows are scollable; widgets packed or gridded in Canvases are not. So this really seems to be your problem here.

HTH
 
M

Marion

ok, we must redefine each canvas scroll individually ... but what a ()
strange language... !!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,114
Latest member
GlucoPremiumReview
Top