Форум сайта python.su
Всем доброго времени))
У меня появилась задачка: есть набор фреймов, организованных grid'ами в виде таблицы. Необходимо, чтобы они изменяли размер, когда пользователь их растягивает по горизонтали/вертикали с помощью мышки. Я искала подобный функционал в tkinter, не нашла, в результате сделала под свою задачку следующее:
Код рабочий, но хотелось бы узнать, можно подобрать более элегантное решение?
Как грамотно ресайзить фреймы с помощью мыши? Если в tkinter уже есть такой функционал, подскажите, пожалуйста, ссылку.
def AddResizer(self, obj, targetWin, side, minsize, col_row_num): ''' obj - фрейм, в который помещается полоска, за которую его растягиваем targetWin - ряд/колонка таблицы, которую растягиваем side - положение полоски (BOTTOM, TOP, LEFT, RIGHT) minsize - начальное значение минимальной ширины/высоты targetWin col_row_num - номер столбца/колонки ''' # если растягиваем ячейку/ряд по вертикали if side in (BOTTOM, TOP): resFrame = Frame(obj, background=self.CFG['resizer_color'], height=self.CFG['resizer_size']) resFrame.pack( side= side, fill="x") targetWin.rowconfigure(col_row_num, minsize=minsize) ishor = False else: # LEFT, RIGHT resFrame = Frame(obj, background=self.CFG['resizer_color'], width=self.CFG['resizer_size']) resFrame.pack( side = side, fill="y") targetWin.columnconfigure(col_row_num, minsize=minsize) ishor = True obj.xyminsize = minsize resFrame.bind('<ButtonPress-1>', lambda e, o=obj, i=ishor:self.StartMove(e, o, i)) resFrame.bind('<ButtonRelease-1>', lambda e, o=obj, i=ishor:self.StopMove(e, o, i)) resFrame.bind('<B1-Motion>', lambda e, o=obj, i=ishor, tw=targetWin:self.OnMotion(e, o, i, tw)) def StartMove(self, event, obj, ishor): obj.xyevent = event.x if ishor else event.y obj.xyroot = event.x_root if ishor else event.y_root def StopMove(self, event, obj, ishor): obj.xyevent = None obj.xyminsize += (event.x_root - obj.xyroot) if ishor else (event.y_root - obj.xyroot) def OnMotion(self,event, obj, ishor, targetWin): if ishor: targetWin.columnconfigure(0, minsize=(obj.xyminsize + event.x_root - obj.xyroot)) else: targetWin.rowconfigure(0, minsize=(obj.xyminsize + event.y_root - obj.xyroot))
Отредактировано zinaida (Май 11, 2015 22:51:00)
Офлайн
У Вас есть две рамки на одном листе. И Вы тянете линию между ними. Что должно происходить?
Что Вы вообще имеет ввиду под изменением размера пользователем? Они их тянет за края как обычные окна? Я верно понял?
Офлайн
4kpt_III, спасибо за ответ
>> Что Вы вообще имеет ввиду под изменением размера пользователем? Они их тянет за края как обычные окна? Я верно понял?
Да, вы верно поняли. При этом пользователь может растягивать либо по горизонтали, либо по вертикали
>> У Вас есть две рамки на одном листе. И Вы тянете линию между ними. Что должно происходить? - размер одной рамки уменьшается, другой увеличивается, в зависимости от того ,куда тянуть
На примере такая полоса (фиолетового цвета) между зеленым и синим фреймом. Если за нее тянуть, уменьшается размер зеленого и увеличивается размер синего и наоборот
Офлайн
zinaida
4kpt_III, спасибо за ответ
Отредактировано 4kpt_III (Май 11, 2015 23:11:33)
Офлайн
>> Такой механизм уже есть. Это PanedWindow.
Спасибо, видимо, я как-то прошла мимо него, когда искала. Прочитала - то, что нужно
>> Код проинспектировать?
Была бы вам благодарна, если не сильно отнимет у вас время
Офлайн
Вы девушка. На девушек у меня всегда найдется время
По коду.
1. Вам нужно почитать про PEP8. Это стандарт оформление кода. Он есть переведенный на русский, поэтому проблем возникнуть не должно. Эта штука сразу режет глаза. Очень.
2. from Tkinter import * Так делать нельзя никогда.
3. Есть механизм описания докстрингов. У Вас не совсем то и не совсем так
4. Раз Вы уже делаете такое окно, то зачем в нем создавать Frame, который потом планируете использовать для хранения виджетов. Не легче ли наследовать сразу от Frame и не мучить себя контролем за его свойствами? ООП слегка не так в Tkinter используется… Хотя дело Ваше.
5. Код. Много лишнего. Можно конкретно упростить. Отличие ведь маленькие такие
if side in (BOTTOM, TOP): resFrame = Frame(obj, background=self.CFG['resizer_color'], height=self.CFG['resizer_size']) resFrame.pack( side= side, fill="x") targetWin.rowconfigure(col_row_num, minsize=minsize) ishor = False else: # LEFT, RIGHT resFrame = Frame(obj, background=self.CFG['resizer_color'], width=self.CFG['resizer_size']) resFrame.pack( side = side, fill="y") targetWin.columnconfigure(col_row_num, minsize=minsize) ishor = True
resFrame.bind('<ButtonPress-1>', lambda e, o=obj, i=ishor:self.StartMove(e, o, i)) resFrame.bind('<ButtonRelease-1>', lambda e, o=obj, i=ishor:self.StopMove(e, o, i))
Отредактировано 4kpt_III (Май 11, 2015 23:43:56)
Офлайн
Кстати. Забыл сказать. Отличная документация Вот тут вот.
Офлайн
4kpt_III, большое спасибо, что все так подробно расписали!
Я на питоне начала писать не так давно, и ваши замечания мне очень пригодятся
P.S: за доку отдельное большущее спасибо!
Отредактировано zinaida (Май 11, 2015 23:57:37)
Офлайн