Задать вопрос
Ответы пользователя по тегу Tkinter
  • Как заставить окно постоянно обновляться в tkinter?

    Vindicar
    @Vindicar
    RTFM!
    Потому что под капотом большинства оконных фреймворков крутится вечный цикл вида "получить оконное сообщение - определить событие - вызвать обработчик события". И следующее оконное сообщение не будет обработано, пока обработчик события не завершится. Как следствие, длительный код в обработчике "подвешивает" окно программы.
    Быстрое и грязное решение - дёргать метод update_idletasks() (погугли про него). Он позволит выполнить перерисовку компонентов GUI, не выходя из обработчика события.
    Чуть менее грязное - разбить выполняемую работу на маленькие блоки, выполнять блок, затем планировать выполнение следующего блока через метод after(). Тогда в промежутке между вызовом after() и фактическим выполнением кода у GUI будет время обработать поступающие сообщения. Но не всегда это возможно, да и о конкуррентном запуске надо думать (что если юзер кликнет кнопку дважды, а не однажды?)
    Ещё менее грязное - вынести длительный код в отдельный поток, научить поток оповещать о своём состоянии (например, менять содержимое переменной), а через after() реализовывать только опрос этой переменной и обновление GUI. Но переменную надо будет защищать мьютексом, чтобы не словить конфликт при одновременном обращении двух потоков.
    Ответ написан
    2 комментария
  • Вместо дуги рисуется линия. Как исправить?

    Vindicar
    @Vindicar
    RTFM!
    По-моему, ты некорректно передаёшь параметры в create_line().
    To create a canvas line object on a canvas C, use:
    id = C.create_line(x0, y0, x1, y1, ..., xn, yn, option, ...)
    The line goes through the series of points (x0, y0), (x1, y1), … (xn, yn).
    Ответ написан
    Комментировать
  • Почему не работает позиционирование в tkinter?

    Vindicar
    @Vindicar
    RTFM!
    1. Для одного элемента можно использовать только один менеджер геометрии. Если ты положил кнопку на форму через place(), не делай ей pack().
    2. В рамках одного контейнера можно использовать только один менеджер геометрии. Если ты положил один элемент на панель/в окно через place()/pack()/grid(), другие элементы, положенные непосредственно в ту же панель/окно, должны использовать тот же самый менеджер.
    Ответ написан
    Комментировать
  • Как собрать 32-битный exe файл?

    Vindicar
    @Vindicar
    RTFM!
    Поплярные упаковщики питона в exe просто засовывают туда весь интерпретатор питона (ну может выбирает только используемые модули) вместе с кодом скрипта. Это НЕ настоящая компиляция.
    Так что делай вывод сам, можно ли упаковать скрипт в 32-битный экзешник, не имея 32хбитного питона на машине.
    Если есть полноценный транслятор Питона в C++ или подобный честный комплируемый язык, он мне не известен.
    Ответ написан
    Комментировать
  • Как оптимизировать работу приложения?

    Vindicar
    @Vindicar
    RTFM!
    Вместо цикла и win.update() научись использовать win.after().
    Ответ написан
    2 комментария
  • Как вычесть результат функции из результата другой функции?

    Vindicar
    @Vindicar
    RTFM!
    Ну во-первых тебе стоит поучить питон на более простых вещах, а потом уже браться за GUI.
    Во-вторых, пусть твои функции помещают результат своего расчёта в глобальную переменную, каждая в свою. Сейчас они записывают его текстом в интерфейс, а как число не сохраняют нигде.
    Ответ написан
    Комментировать
  • Позиционирование в tkinter не поддается логике?

    Vindicar
    @Vindicar
    RTFM!
    Во-первых, нельзя смешивать разные менеджеры в рамках одного контейнера. Если ты этого не понял, я фз что ты читал. Т.е. ты можешь гридом разместить несколько панелей, а потом каждую панель наполнять по-разному.
    Во-вторых, стоит чуть-чуть погуглить, и находишь вот такой материал где прямо прописано, что не так со свойством height (ну и width заодно).
    Height of the button in text lines (for textual buttons) or pixels (for images).

    Решение, мягко говоря, спорное, но оно документировано. Размер виджету нужен только как некоторое предпочтительное значение по умолчанию, так как вообще-то всей геометрией занимается выбранный менеджер геометрии. А раз уж хочешь использовать place, почему ты не обратил внимание на параметры width/height?
    В общем, не принимай собственную невнимательность за чужие ошибки.
    from tkinter import *
    
    frame_bot = Tk()
    frame_bot.geometry("640x480")
    # place() возвращает None, как и stack() / grid()
    Button(frame_bot, text="back", bg='gray').place(x=5, y=405, width=30, height=30) 
    Button(frame_bot, text="write", bg='blue').place(x=45, y=405, width=30, height=30)
    Button(frame_bot, text="home", bg='green').place(x=85, y=405, width=30, height=30)
    
    frame_bot.mainloop()
    Ответ написан
    1 комментарий
  • Как получить данные с функции, при нажатии на кнопку?

    Vindicar
    @Vindicar
    RTFM!
    Ну для начала неплохо бы осознать, что понятие "за функцией" существует и в пространстве, и во времени.

    В пространстве - ты описываешь в функции локальную переменную Key, которая не видна снаружи, в глобальной области видимости, а также не видна в других функциях. Если хочешь сохранить это значение глобально, объяви переменную снаружи функции, присвоив ей какое-то начальное значение (скажем, None), а внутри функции опиши переменную как global.

    Во времени - весь приведенный тобой код, вплоть до вызова root.mainloop() (который ты не привёл), выполняется в самом начале работы скрипта - еще до того, как на экране появится окно. Чтобы код мог использовать значение, которое было получено в рамках btn_click(), нужно, чтобы этот код выполнялся гарантированно после btn_click() или же внутри btn_click(), но после получения значения Key. Как это гарантировать - подумай сам. Либо обяжи пользователя нажимать на кнопки в строго определнном порядке, либо привяжи исполнение кода к вызову btn_click().
    Ответ написан
    Комментировать
  • Tkinter grid, как растянуть сетку на все окно?

    Vindicar
    @Vindicar
    RTFM!
    Адаптивность решается через rowconfigure() и columnconfigure().
    А вот сам вопрос кривой: тебе нужно окно на весь экран, или только виджет на всё окно? Это разные вещи, как бы.

    Если нужно растянуть один виджет на всё окно (root), то просто
    widget.pack(fill='both', expand=True)
    Ответ написан
  • Ошибка в 5 строке. как сделать без ошибки?

    Vindicar
    @Vindicar
    RTFM!
    Включаю режим телепатии... ошибка "SyntaxError: unexpected EOF while parsing"?
    Если да, то включить голову и подумать.
    Ты вызываешь a=eval(t.get()). Т.е. пытаешься выполнить код, записанный в поле ввода t.
    Учитывая, что у тебя интерфейс ещё только создаётся, в этом поле ввода сейчас пусто.
    Строка выполняется до того как ты увидишь окно и успеешь туда что-то ввести.
    Вот eval() и ругается на пустую строку.
    Собственно, замечания только 2.
    1. Напиши обработчик щелчка по кнопке, и забирай значение из поля ввода в этом обработчике.
    2. На кой огурец тебе eval()? Чем int() не устроил?
    Ответ написан
    5 комментариев
  • Как синхронизировать БД sqlite и виджет tkinter ttk.treeview?

    Vindicar
    @Vindicar
    RTFM!
    Питоновский модуль для sqlite этого не умеет, хотя sqlite сама по себе предоставляет update_hook. См stackoverflow.
    Более простое решение - периодически опрашивать сервер, но это может быть напряжно.

    Но с учетом твоего другого вопроса, PostgreSQL реализует синтаксис LISTEN/NOTIFY. Есть модули для питона, которые позволяют этим пользоваться. Периодический опрос всё ещё потребуется, но он будет потреблять куда меньше ресурсов, чем SELECT.
    Ответ написан
    Комментировать
  • Как синхронизировать два файла базы данных sqlite в приложении на python?

    Vindicar
    @Vindicar
    RTFM!
    Сделать нормальный сервер БД вместо SQLite. Возьми MariaDB, или Postgre, или что угодно.

    Потому что иначе всё равно придётся разрешать конфликты записей. Например, в таблице X один пользователь добавил запись A с id=10, а другой независимо добавил запись B с id=10. Придётся одну перенумеровывать. А если у них ещё и связанные записи в других таблицах?
    Ответ написан
    Комментировать
  • Почему не обновляется текстовый виджет Tkinter?

    Vindicar
    @Vindicar
    RTFM!
    fan_gpu_info.after(1000, fan_gpu_info)
    Может, имелось ввиду это?
    fan_gpu_info.after(1000, fans_gpu)
    Ответ написан
    2 комментария
  • Как узнать индекс динамического виджета tkinter?

    Vindicar
    @Vindicar
    RTFM!
    Есть два подхода. Один основан на лямбдах:
    for i in range(2):
        buttonFrame_update=Button(frame,text="Добавить", command= lambda arg=i: update_main_db(arg))

    Приём с аргументом лямбды необходим, чтобы сохранить текущее значение i - иначе в момент вызова лямбды она прочитает последнее значение i, а оно будет указывать на последнюю строку.

    Второй способ, которя я бы выбрал - написать свой виджет - строку таблицы. Тогда обработчик нажатия на кнопку сможет брать данные из экземплярной переменной.
    class MyTableRow(Frame):
        def __init__(self, master, *args, **kwargs):
            super().__init__(master, *args, **kwargs)
            self.widgets = []
            for i in range(3):
                widget = Entry(frame)
                widget.pack(side="left")
                self.widgets.append(widget)
            self.update_btn = Button(self, text = "Добавить", command = self.update_clicked)
            self.update_btn.pack(side="right")
            self.delete_btn = Button(self, text = "Удалить", command = self.delete_clicked)
            self.delete_btn.pack(side="right")
      
        def update_clicked(self):
            print(self.widgets[0].get())
        
        def delete_clicked(self):
            print("whatever")
    
    
    for i in range(2):
        item = MyTableRow(doth, borderwidth=2, relief="groove")
        frames.append(item)
        item.pack(side="top", fill="x")
    Ответ написан
    5 комментариев
  • Как убрать ошибку при выведении в окно типа text из текстового файла docx?

    Vindicar
    @Vindicar
    RTFM!
    if var == 0:
    Так не сработает. Нужно
    if var.get() == 0:
    Ответ написан
    Комментировать
  • Как грамотно использовать progress bar в коде?

    Vindicar
    @Vindicar
    RTFM!
    Тебе нужно дать ткинтеру шанс перерисоваться, и обработать другие оконные сообщения.

    pb.config(value=format(per))
    win.update_idletasks()
    Ответ написан
  • Почему в tkinter не обновляется текст на экране?

    Vindicar
    @Vindicar
    RTFM!
    Потому что ты не понимаешь, что делаешь.
    btn_ent = Button(frame_btn, text='Ввести', font=100, bd=2, height=5, command=click())

    Ты присваиваешь в качестве обработчика щелчка по кнопке результат вызова функции click(). У неё нет ни одного return, так что она возвращает None.
    Если ты хотел назначить click() как обработчик, то нужно было указать саму функцию, а не результат её вызова.
    command=click


    Далее, сравнение
    txt == 'чтототам'
    некорректно, так как StringVar() и str - разные типы данных, и они не будут равны. Используй
    txt.get() == 'чтототам'
    . Одинокий вызов txt.get() в начале click() бесполезен, так как ты игнорируешь возвращаемое get() значение.

    Собственно, я не вижу где ты инициализируешь переменную txt. У тебя нет ни одного вызова txt.set().

    Ну и до кучи, присваивание TextR перед root.mainloop() ни на что не повлияет, так как она использовалась ранее.
    Если хочешь, чтобы присваивание переменной тут же отражалось в элементах управления, нужно использовать еще один StringVar(), и вызывать его метод .set() для смены значения.
    Ответ написан
    Комментировать
  • Как решить проблему с видимостью переменной root?

    Vindicar
    @Vindicar
    RTFM!
    @bot.message_handler(content_types=['text'])
    def get_command(message):
        if message.text == "Start":
          root = tk.Tk()
          img = ImageTk.PhotoImage(Image.open('lol.png'))
          createNewWindow(root, img)
          root.mainloop()
        elif message.text == "Stop":
          root.destroy()

    Ух как всё запущено.
    Во-первых, если ты ввёл Start, то get_command() создаёт локальную root, настраивает её, и уходит в бесконечный цикл внутри root.mainloop(). Я не знаю как pytelegrambotapi разруливает это, но бот после такого должен просто встать колом, пока все окна не будут закрыты. Подозреваю что обработчик вызывается в отдельном потоке, но фз. В любом случае, не надо так делать. Лучше иметь один root, который крутится внутри mainloop() в отдельном потоке всё время работы скрипта, а окна создавать и удалять по мере надобности, не создавая и не убивая root.
    Вообще подружить бота с оконным интерфейсом - задача нетривиальная.
    Во-вторых, переменная root - локальная. Она существует только внутри того экземпляра get_command(), который был вызван с командой старт. Если ты вызываешь его с командой Stop, у тебя запускается отдельный экземпляр, где выполняется только ветка Stop - а в этой ветке root объявлен не был, он был объявлен только в ветке Start, в другом экземпляре.
    В-третьих, окна будут спамиться только на той машине где запущен бот. Это так, на всякий случай.
    Ответ написан
    Комментировать
  • Как найти объект по координатам в tkinter?

    Vindicar
    @Vindicar
    RTFM!
    Всё что мне приходит в голову - перебрать все виджеты и найти те, чей прямоугольник содержит искомую точку.
    winfo_x()/winfo_y() - позиция виджета относительно родительского виджета.
    winfo_rootx()/winfo_rooty() - если не путаю, позиция виджета относительно начала экрана.
    winfo_width()/winfo_height() - текущий размер виджета
    winfo_children() - список дочерних виджетов для данного виджета.

    Но зачем тебе это понадобилось? Может, есть способ попроще?
    Ответ написан
    3 комментария