Форум сайта python.su
задача создать форму ввода значений, каждая ячейка формы состоит из tkinter.ttk.Label, tkinter.ttk.Entry и несколько tkinter.ttk.Button'ов. Форма динамическая- пользователь может добавлять-удалять ячейки, соответственно нужен скроллбар. Отсюда вопрос: как узнать высоты tkinter.ttk.Label, tkinter.ttk.Entry, tkinter.ttk.Button, чтобы высчитать необходимые значения для скроллбара и канваса, мне в лучшем случае выдает 0, а в худшем вообще нет атрибута height?
Офлайн
Как это нет атрибута. Обманываете. Ох и обманываете.
Я отвечу на Ваш вопрос, но он неверен в корне. Такой графические интерфейс уже изначально представляется мне неверным. Как это “пользователь должен добавлять”. А правило 7 плюс минус 2 никто не отменял. Как в этом случае быть. Тогда лучше в виде таблицы…
Короче. По вашему вопросу.
Можно использовать два подхода:
1. Рассчитать заранее - это хардкор, но такой подход тоже имеет право на жизнь. Для этого необходимо делать предварительно .update_idletasks() для виджета, размеры которого хотите померять. Размеры, естественно, вернуться в пикселях и можно будет настраивать Вашу рамку. Все виджеты можно померять методами widget.winfo_width(), widget.winfo_height() или widget.winfo_geometry().
2. Более корректный, но все равно плохой с точки зрения дизайна пользовательского интерфейса.
Можно использовать метод .create_window() в виджете Canvas.
Еще хотел бы обратить Ваше внимание на то, что с размерами рамки есть небольшие ньюансы у разных методов геометрии объектов. Будьте внимательны
Нужна будет еще помощь - пишите.
Отредактировано 4kpt_II (Дек. 2, 2013 18:27:39)
Офлайн
да, я уже после как написал, повнимательней dir просмотрел и увидел, но вот widget.winfo_height() у меня 1 возвращает, тип инт. Мне нужны эти значения для canvas.create_window(…, height=…, …) и tkinter.Canvas(…, scrollregion=…), чтоб вычислить и задать вышеуказанные параметры.
Эта форма пока скорее для тренировки, но в дальнейшем- ввод размеров участков помещения, их может быть 1, а может и 50, пользователь жмет ‘добавить’-добавляется новая ячейка. Заранее делать 50 неэстетично. Посоветуйте как лучше быть
Офлайн
Простите. Очень сложно ответить, так как не знаю задачи.
Попробую просто рассмотреть возможные варианты:
1. Связанные списки, увеличивающиеся на 1 ячейку, если количество введенных данных становится равным длине списков. Например: список для ввода данных имеет длину 5 строк. Когда пользователь введет пятую строку - добавить шестую и т.п. При этом сохраняется ментальная модель и структура ввода данных. Если списков несколько, то хорошо организовывать ввод в отдельном toplevel.
2. Если количество невелико и максимальное значени известно - можно сделать таблицу из полей ввода, только делать поля неактивные (с возможностью активации) когда в них вводят данные. Тогда пользователю будет четко видно, где он и что ввел. При этом рационально их верстать в виде таблицы, т.е. столько-то колонок на столько-то строк.
3. Если виджеты не однородные, то можно использовать мастер. Только должно быть две отдельные кнопки - “далее” и “завершить”. На “далее” создается новая порция виджетов. На “завершить” - завершается процесс ввода. Обязательно нужно организовать возможность перехода по этим страницам и корректное отображение места, где находится пользователь вверху или внизу базового окна.
4. Если данные поддаются группировке - то слева укрупненный список, а справа - небольшая табличка для ввода. Может быть организована в виде набора полей ввода или в виде связанных списков. Только в отличии от пункта 1 она имеет фиксированный размер. Аналог - меню “Параметры” в LibreOffice. Только ни в коем случае не делать как в MicrosoftOffice. Убил бы за такое использование notebook на месте…
P.S. Еще много вариантов. Я рассмотрел основные. Помните. Главная задача: Сохранить нормальную ментальную модель ввода данных. Должно быть либо все четко сгруппировано, либо количество виджетов на всех страницах постоянно (исключение - последняя страница). Например. Вы намерены ввести 50 данных - 5 страниц на 9 виджетов и 6 страница на 5 виджетов и т.п.
Будут вопросы - пишите.
Отредактировано 4kpt_II (Дек. 2, 2013 22:23:56)
Офлайн
Спасибо за варианты. Нужно все перепробывать самому, чтоб вникнуть. Разобрался я с размерами, высоту виджетов узнавал widget.winfo_reqheight(), вроде оно, все укладывается
Офлайн
Можно и так. Но лучше обновить информацию по виджету перед получением размеров методом
widget.update_idletasks() print windet.winfo_width()
These methods return the requested height of widget w. This is the minimum height necessary so that all of w's contents have the room they need. The actual height may be different due to negotiations with the geometry manager.
Отредактировано 4kpt_II (Дек. 3, 2013 02:00:03)
Офлайн
да, мне это все ново и придется изучать не один день. Извините за назойливость, скажите, как установить значение в Entry по-умолчанию, например ‘0’, как только пользователь начинает ввод, оно меняется на введенное, если все стер- то снова ‘0’, и можно ли задать тип разрешенных вводимых символов, например только цифры (как например inputType в android'e)?
Офлайн
Нет, но можно перехватывать нажатие клавиш. Если пользователь нажмет клавишу из недопустимых, то можно просто не выводить ее в виджет. Или подсветить его красным цветом с указанием ошибки. Вариантов уйма Тоже самое можно сделать и в том случае, если надо ввести какие-то подсказки в виджете. При первом нажатии любой клавиши на активном виджете, подсказка стирается и виджет заполняется необходимыми данными.
Я когда-то создавал собственный базовый класс, у которого было такое свойство как тип передаваемых данных, но я его уже сейчас не найду. Там была простая обвязка вокруг метода bind. На самом деле Tkinter очень гибкий и написать там свое поведение очень и очень легко.
P.S. Я не работаю на android, поэтому не знаю как там
P.S.S. Никакой назойливость. Нормальный такой интерес
Будут вопросы - пишите.
Офлайн