Уведомления

Группа в Telegram: @pythonsu
  • Начало
  • » GUI
  • » Tkinter.Canvas, несколько create_window() и scrollregion. [RSS Feed]

#1 Фев. 17, 2011 21:35:22

antib
От:
Зарегистрирован: 2010-02-23
Сообщения: 37
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter.Canvas, несколько create_window() и scrollregion.

Пытаюсь сделать в одном поле канвас три набора виджетов, из трёх одновременно видим должен быть только один. Каждый набор должен иметь возможность скролла, scrollregion определяю по bbox(). И оно таки работает, но не полностью так как я предполагал.

Если все три окна изначально сделать скрытыми (state=HIDDEN, строка 41 и т.д.)и оставить их включение на волю юзера, то все работает, но если одно окно изначально не скрывать или снять коммент с вызова функции show1() , строка 80, то скролл работает так, будто scrollregion не задан, а bbox выводит координаты (0,0,1,1) т.е. все виджеты занимают 1 пиксель.

Почему оно так я не могу ни понять ни нагуглить.
ОС - Дебиан Ленни.

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from Tkinter import *
app=Tk()
toolbar=Frame (app, relief=RIDGE)
field=Frame (app, relief=RIDGE)
canva=Canvas (field, width=1000, height=500, relief=SUNKEN)
sbar=Scrollbar(field, command=canva.yview, orient=VERTICAL, bg="gray", takefocus=0)
canva.configure(yscrollcommand=sbar.set)
def wheel (event): #привязка колеса мыши к "холсту"
if event.num == 5 or event.delta == -120:
canva.yview(SCROLL, 1, "units")
if event.num == 4 or event.delta == 120:
canva.yview(SCROLL, -1, "units")

app.bind ("<Button-4>",wheel)
app.bind ("<Button-5>",wheel)
app.bind ("MouseWheel", wheel)

canva.focus_set()
frame1=Frame(field)
frame2=Frame(field)
frame3=Frame(field)
list1=[]
list1=range(20)
for step in range (20):
list1[step]=Button (frame1, text="First "+str(step)+" of 20")
list1[step].pack (side=TOP)
list2=[]
list2=range(30)
for step in range(30):
list2[step]=Button (frame2, text="Second "+str(step)+" of 30")
list2[step].pack (side=TOP)
list3=[]
list3=range(40)
for step in range (40):
list3[step]=Button (frame3, text="Third "+str(step)+" of 40")
list3[step].pack (side=TOP)
window1=canva.create_window(0,0,window=frame1,anchor=NW)
canva.itemconfig (window1,state=HIDDEN)
window2=canva.create_window(0,0,window=frame2,anchor=NW)
canva.itemconfig (window2,state=HIDDEN)
window3=canva.create_window(0,0,window=frame3,anchor=NW)
canva.itemconfig (window3,state=HIDDEN)

field.pack(side=BOTTOM)
sbar.pack(side=RIGHT,fill=Y)
canva.pack(side=BOTTOM)
toolbar.pack(fill=X,side=TOP)

def show1(): #показать окно1, скрыть окна 2 и 3
canva.itemconfig (window1,state=NORMAL)
canva.itemconfig (window2,state=HIDDEN)
canva.itemconfig (window3,state=HIDDEN)
print canva.bbox(window1)
canva.configure(scrollregion=canva.bbox(window1))
def show2(): #показать окно2, скрыть окна 1 и 3
canva.itemconfig (window2,state=NORMAL)
canva.itemconfig (window1,state=HIDDEN)
canva.itemconfig (window3,state=HIDDEN)
print canva.bbox(window2)
canva.configure(scrollregion=canva.bbox(window2))

def show3(): #показать окно3, скрыть окна 2 и 1
canva.itemconfig (window3,state=NORMAL)
canva.itemconfig (window2,state=HIDDEN)
canva.itemconfig (window1,state=HIDDEN)
print canva.bbox(window3)
canva.configure(scrollregion=canva.bbox(window3))

but1=Button (toolbar, text="switch 1",command=show1)
but1.pack(side=LEFT)
but2=Button (toolbar, text="switch 2",command=show2)
but2.pack(side=LEFT)
but3=Button (toolbar, text="switch 3",command=show3)
but3.pack(side=LEFT)

def main():
#show1()
print "1 "+str(canva.bbox(window1))
print "2 "+str(canva.bbox(window2))
print "3 "+str(canva.bbox(window3))
app.mainloop()
return 0
if __name__ == '__main__': main()



ОС - linux mint, Python ver 3.3

Офлайн

#2 Фев. 23, 2011 15:41:33

antib
От:
Зарегистрирован: 2010-02-23
Сообщения: 37
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter.Canvas, несколько create_window() и scrollregion.

Интересно, моя проблема слишком лёгкая или слишком трудная? :)



ОС - linux mint, Python ver 3.3

Отредактировано (Фев. 23, 2011 15:56:18)

Офлайн

#3 Фев. 23, 2011 23:31:31

Griffon
От: Ukrain, Zaporozhie
Зарегистрирован: 2009-03-04
Сообщения: 324
Репутация: +  11  -
Профиль   Отправить e-mail  

Tkinter.Canvas, несколько create_window() и scrollregion.

Банально нет времени попробовать. Попробуй выполнить функцию не сразу, а, скажем, через 100мс.



Офлайн

#4 Фев. 26, 2011 13:25:22

antib
От:
Зарегистрирован: 2010-02-23
Сообщения: 37
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter.Canvas, несколько create_window() и scrollregion.

Griffon
Банально нет времени попробовать. Попробуй выполнить функцию не сразу, а, скажем, через 100мс.
Так?
show1()
app.after(1000)
app.mainloop()
Разницы не наблюдается.

Мне непонятно, почему при переключении видимости/невидимости групп виджетов слетает скролл - одинаковым образом созданные группы могут или наползать на видежеты за пределами канвас или же прокручиваться не выходя за ее границы.

Видимо, я не понимаю чего-то в принципе отображения объектов canvas.create_window.
Я пытаюсь сделать переключение между несколькими “полями”, которые бы работали как вкладки. Каждая “вкладка” это окно, изначально все окна создаются так.
self.window=self.canva.create_window(0,0,window=self.frame)
self.canva.itemconfig(self.window,state=HIDDEN)
Потом я наполняю этот self.frame всякими виджетами и по ходу пьесы окна можно переключать меняя state одного на NORMAL. После переключения я переопределяю scrollregion скроллбара.
self.canva.configure(scrollregion=self.canva.bbox(self.window))
Если окна со скроллом создается вместе с прочими элементами (напр. тулбары) то переключение между ними происходит нормально. Если окно перенаполняется виджетами по новой, после того как другие уже были созданы, то при скролле его элементы проплывают над тулбарами, если их размер больше канвас. Если это разме меньше, то они скролятся (хотя необходимости в этом нет), но остаются в пределах канвас.

Что я упускаю из виду?



ОС - linux mint, Python ver 3.3

Отредактировано (Фев. 26, 2011 20:15:00)

Офлайн

#5 Фев. 27, 2011 00:14:07

Griffon
От: Ukrain, Zaporozhie
Зарегистрирован: 2009-03-04
Сообщения: 324
Репутация: +  11  -
Профиль   Отправить e-mail  

Tkinter.Canvas, несколько create_window() и scrollregion.

Изменил

def print_bbox():
show2()
print "1 "+str(canva.bbox(window1))
print "2 "+str(canva.bbox(window2))
print "3 "+str(canva.bbox(window3))
def main():
app.after(100, print_bbox)
app.mainloop()
return 0
Добавил
toolbar.pack(fill=X,side=TOP)
field.pack()
sbar.pack(side=RIGHT,fill=Y)
canva.pack(side=BOTTOM)

Frame(app, relief=GROOVE, bg="red", height=50).pack(side=BOTTOM, fill=BOTH)

....

def show3(): #показать окно3, скрыть окна 2 и 1
canva.itemconfig (window3,state=NORMAL)
canva.itemconfig (window2,state=HIDDEN)
canva.itemconfig (window1,state=HIDDEN)
list3.append(Button (frame3, text="Third %s of %s" % (len(list3), len(list3)+1)))
list3[-1].pack (side=TOP)
canva.update()
print canva.bbox(window3)
canva.configure(scrollregion=canva.bbox(window3))
Питон 2.7.1. Всё работает как ожидается. Никаких проблем.



Офлайн

#6 Фев. 27, 2011 02:00:22

antib
От:
Зарегистрирован: 2010-02-23
Сообщения: 37
Репутация: +  0  -
Профиль   Отправить e-mail  

Tkinter.Canvas, несколько create_window() и scrollregion.

Заработало, спасибо.
Буду думать.

    list3.append(Button (frame3, text="Third %s of %s" % (len(list3), len(list3)+1)))
list3[-1].pack (side=TOP)
canva.update()
Вероятно где-то тут закопан ответ на вопрос в конце моего предыдущего поста.

upd:
Время создания window влияет. Если создать window и соотв. ей frame в начале программы, а наполнение этих фреймов оставить на потом, то скролл работает правильно. Если window и frame создаются в процессе, то всё выглядит печальнее.



ОС - linux mint, Python ver 3.3

Отредактировано (Фев. 27, 2011 13:30:06)

Офлайн

  • Начало
  • » GUI
  • » Tkinter.Canvas, несколько create_window() и scrollregion.[RSS Feed]

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version