При открытии файла в поле Entry пропадает курсор. В чем ошибка?

Igor_K

Новичок
Пользователь
Дек 15, 2021
9
0
1
Москва
Операционная система - Windows 10
Язык программирования Python - Python 3.8.5
Решаю задачу:
- В файле .txt имеется несколько слов, записанных построчно (каждое слово в своей строке),
- Хочу прочитать слово и вывести его на экран в поле Entry,
- Хочу в выведенное слово внести исправление,

В моей программе чтение из файла производится вызовом подпрограммы OpenFile().

Python:
 def OpenFile():
    file_Name=fd.askopenfilename(filetypes=[('Text file','*.txt')] )

    with open(file_Name, encoding='utf8', mode='r') as fr:
        print('File open')
        i_Line=0

        for line in fr:
            i_Line+=1
    print('File rows = ', i_Line)
    return


def main():
    pass

if __name__ == '__main__':
    main()

from tkinter import *
from tkinter import filedialog as fd

screen=Tk()
screen.title('Testing Entry')
screen.geometry('800x300')

# Оформление экрана

lbl_word=Label(text="Слово: ", width=10)
lbl_word.grid(row=1, column=0)

edit_word=Entry(width=20)
edit_word.grid(row=1, column=1)
edit_word.insert(0, "Текст для изменения")


#Открываю файл (чтобы файл не открывался, нужно этот вызов закомментировать -  #OpenFile()   )
OpenFile()

screen.mainloop()

Если подпрограмма OpenFile() вызывается, то в поле Entry курсор НЕ ставится и исправления НЕЛЬЗЯ произвести.
Если вызов подпрограммы ЗАКОММЕНТИРОВАТЬ (в программе этот вызов нужно закомментировать #), то подпрограмма не вызывается, при этом курсор в поле ENTRY СТАВИТСЯ и исправление текста ВЫПОЛНЯЕТСЯ .
В чем причина потери курсора?
Как сохранить возможность вносить изменения в текст?
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 599
464
83
ваш код ужасен... ничего не менял
вот так работает
Python:
def OpenFile():
    file_Name=fd.askopenfilename(filetypes=[('Text file','*.txt')] )

    with open(file_Name, encoding='utf8', mode='r') as fr:
        print('File open')
        i_Line=0
        line = fr.read()

        for line in fr:
            i_Line+=1
    print('File rows = ', i_Line)
    return line


def main():
    pass

if __name__ == '__main__':
    main()

from tkinter import *
from tkinter import filedialog as fd

paste_line = OpenFile()
screen=Tk()
screen.title('Testing Entry')
screen.geometry('800x300')

# Оформление экрана

lbl_word=Label(text="Слово: ", width=10)
lbl_word.grid(row=1, column=0)

edit_word=Entry(width=20)
edit_word.grid(row=1, column=1)
edit_word.insert(0, paste_line)


#Открываю файл (чтобы файл не открывался, нужно этот вызов закомментировать -  #OpenFile()   )
# OpenFile()

screen.mainloop()
 

Igor_K

Новичок
Пользователь
Дек 15, 2021
9
0
1
Москва
Спасибо за оперативность. Все работает. Разбираюсь.
По поводу "ваш код ужасен... " - я был уверен в его элегантности:(
Любопытно в чем ужас ???
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 599
464
83
Спасибо за оперативность. Все работает. Разбираюсь.
По поводу "ваш код ужасен... " - я был уверен в его элегантности:(
Любопытно в чем ужас ???
def OpenFile(): - в питоне функции и методы принято обзывать с маленькой буквы, а классы с большой, если нужен пробел, то ставиться нижнее подчеркивание


Python:
for line in fr:
            i_Line+=1
    print('File rows = ', i_Line)
тут вы считаете количество строк в файле, можно прочитать файл в список и узнать его длину, это и будет количество строк


Python:
def main():
    pass

if __name__ == '__main__':
    main()
вы знаете что это за конструкция и что она делает?
если на пальцах, то:
если ваш код импортировать в другой код в качестве модуля, то выполниться все что идет до if __name__ == '__main__':, в вашем случае определяться функции OpenFile и main, а если запустить ваш код напрямую, как самостоятельный скрипт, то выполниться весь код...
это сделано для того, чтобы исполняемая часть вашего кода не мешала другому коду, в котором импортировали ваш код...
соответственно - если эта конструкция посередине кода, она бессмыслена, так как код, который идет за ней, тоже выполниться...
в вашем коде она вообще не нужна...
более подробно и более научно можете сами погуглить почитать...


from tkinter import * - такой импорт не приветствуется, так как вы импортируете все имена в свою область видимости, это может вызвать конфликты с уже существующими именами и, как следствие, вызвать неопределенное поведение кода и трудноулавливаемые ошибки...


вот так можно переписать
Python:
import tkinter as tk
from tkinter import filedialog as fd


def open_file():
    file_name = fd.askopenfilename(filetypes=[('Text file', '*.txt')])

    with open(file_name, "r", encoding='utf8') as fr:
        print('File open')
        line = fr.readlines()
        print('File rows = ', len(line))
    return line


screen = tk.Tk()
paste_line = open_file()
screen.title('Testing Entry')
screen.geometry('800x300')

lbl_word = tk.Label(screen, text="Слово: ", width=10)
edit_word = tk.Entry(screen, width=20)
edit_word.insert(0, "".join(paste_line))

lbl_word.grid(row=1, column=0)
edit_word.grid(row=1, column=1)

screen.mainloop()
 
  • Мне нравится
Реакции: Vershitel_sudeb

Igor_K

Новичок
Пользователь
Дек 15, 2021
9
0
1
Москва
Уважаемый regnor, спасибо за ясный и подробный ответ.
Постараюсь "впитать" - надеюсь получится.
Остался один вопрос: "В чем причина потери курсора?" - в Вашем последнем варианте "вот так можно переписать" курсор пропадает точно так же!!!
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 599
464
83
Остался один вопрос: "В чем причина потери курсора?" - в Вашем последнем варианте "вот так можно переписать" курсор пропадает точно так же!!!
поменяйте местами строки
screen = tk.Tk()
paste_line = open_file()
что бы функция запускалась до определения объекта tk
то есть вот так
Python:
import tkinter as tk
from tkinter import filedialog as fd


def open_file():
    file_name = fd.askopenfilename(filetypes=[('Text file', '*.txt')])

    with open(file_name, "r", encoding='utf8') as fr:
        print('File open')
        line = fr.readlines()
        print('File rows = ', len(line))
    return line


paste_line = open_file()
screen = tk.Tk()
screen.title('Testing Entry')
screen.geometry('800x300')

lbl_word = tk.Label(screen, text="Слово: ", width=10)
edit_word = tk.Entry(screen, width=20)
edit_word.insert(0, "".join(paste_line))

lbl_word.grid(row=1, column=0)
edit_word.grid(row=1, column=1)

screen.mainloop()
 

Igor_K

Новичок
Пользователь
Дек 15, 2021
9
0
1
Москва
Уважаемый regnor, спасибо.
Я сменил строки местами и все заработало!
Вы крут!!!
Не понимаю как это работает.
Как влияет открытие файла на работу поля Entry?
Где про это можно прочитать?
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 599
464
83
Уважаемый regnor, спасибо.
Я сменил строки местами и все заработало!
Вы крут!!!
Не понимаю как это работает.
Как влияет открытие файла на работу поля Entry?
Где про это можно прочитать?
я не знаю как работает ткинтер внутри, но при открытии файла тоже создается окно, и если открыть файл после определения объекта tk, то фокус будет в том окне, в первом, если наше окно где текст свернуть и развернуть, то фокус вернется в нужное окно, второе (это чисто наблюдение, повторюсь, не знаю как ткинтер работает внутри)...
решается тем, что бы определить объект tk после открытия файла, тем самым сделать фокус на этот объект...
 

Igor_K

Новичок
Пользователь
Дек 15, 2021
9
0
1
Москва
В дополнение к предыдущему еще один вопрос.
Какая-то команда, возможно import tkinter as tk, открывает виртуальный экран стандартного размера с именем tk
до момента открытия подпрограммы open_file()
После чтения данных из файла срабатывают строки
screen = tk.Tk()
screen.title('Testing Entry')
screen.geometry('800x300')
На экране монитора появляется поле с именем 'Testing Entry' размера 800х300, но поле с именем tk остается на мониторе.
В результате видны два экрана!
Как избавиться от виртуального экрана tk ?
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 599
464
83
В дополнение к предыдущему еще один вопрос.
Какая-то команда, возможно import tkinter as tk, открывает виртуальный экран стандартного размера с именем tk
до момента открытия подпрограммы open_file()
После чтения данных из файла срабатывают строки
screen = tk.Tk()
screen.title('Testing Entry')
screen.geometry('800x300')
На экране монитора появляется поле с именем 'Testing Entry' размера 800х300, но поле с именем tk остается на мониторе.
В результате видны два экрана!
Как избавиться от виртуального экрана tk ?
на 10ке второго окна нет, на семерке появляеться да...
можно скрыть это окно, но в таком случае при закрытии второго окна программа не завершаеться...
для завершения программы можно переопределить событие WM_DELETE_WINDOW...

в общем вот так, должно работать, проверил на 10ке и на 7ке
Python:
import tkinter as tk
from tkinter import filedialog as fd
import sys


def open_file():
    tk.Tk().withdraw()
    file_name = fd.askopenfilename(filetypes=[('Text file', '*.txt')])

    with open(file_name, "r", encoding='utf8') as fr:
        print('File open')
        line = fr.readlines()
        print('File rows = ', len(line))
    return line


def close():
    sys.exit(0)


paste_line = open_file()
screen = tk.Tk()
screen.protocol("WM_DELETE_WINDOW", close)
screen.title('Testing Entry')
screen.geometry('800x300')

lbl_word = tk.Label(screen, text="Слово: ", width=10)
edit_word = tk.Entry(screen, width=20)
edit_word.insert(0, "".join(paste_line))

lbl_word.grid(row=1, column=0)
edit_word.grid(row=1, column=1)

screen.mainloop()

upd
возможно, разное поведение зависит еще от версии питона, на 10ке питон 3.10 - окна нет, на 7ке питон 3.8 - окно есть
выше приведенный код проверил на этих версиях питона, вроде нормально...
 
Последнее редактирование:

Igor_K

Новичок
Пользователь
Дек 15, 2021
9
0
1
Москва
Уважаемый @regnor,
screen.protocol("WM_DELETE_WINDOW", close) закрывает виртуальное окно.
ОК
У меня при этом возникает несколько необычная ситуация:
нажатие на кнопку "крестик" на окне вверху справа завершает программу (приходит сообщение Exit code = 0) , но окно screen остается на экране монитора. Закрыть/спрятать его невозможно.
Согласен - основную проблему потери курсора мы решили (!!!), а "зависание" экрана screen для меня не принципиально.
Эта проблема была бы важна, если бы программа предназначалась на продажу.

Использование "WM_DELETE_WINDOW" уводит нас в самый глубокий уровень tkinter.
Если это сложно - можем на этом остановиться, но если Вам интересно - буду рад в компании с Вами углубиться в этот вопрос.
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 599
464
83
Уважаемый @regnor,
screen.protocol("WM_DELETE_WINDOW", close) закрывает виртуальное окно.
ОК
У меня при этом возникает несколько необычная ситуация:
нажатие на кнопку "крестик" на окне вверху справа завершает программу (приходит сообщение Exit code = 0) , но окно screen остается на экране монитора. Закрыть/спрятать его невозможно.
Согласен - основную проблему потери курсора мы решили (!!!), а "зависание" экрана screen для меня не принципиально.
Эта проблема была бы важна, если бы программа предназначалась на продажу.

Использование "WM_DELETE_WINDOW" уводит нас в самый глубокий уровень tkinter.
Если это сложно - можем на этом остановиться, но если Вам интересно - буду рад в компании с Вами углубиться в этот вопрос.
у меня нет таких ошибок, я не знаю как ее воспроизвести, покажите код который вызывает у вас такую ошибку...
как вы запускаете код, через какую то IDE ?
еще попробуйте питон поставить новый, вы писали что у вас вин 10, можно установить питон 3.10, на нем и окна второго не было...
 

Igor_K

Новичок
Пользователь
Дек 15, 2021
9
0
1
Москва
Уважаемый regnor, как Вы посоветовали скачал Python 3.10 и к нему IDLE.
Раньше с версией 3.8 у меня запускался Питон с полем для набора текста программы.
Сейчас он запускается только >>>.
Жаль, я не силен и не помню что и как я делал с версией 3.8 :(((
Если не сложно - подскажите как включить режим набора текста или где прочитать.

,
 

regnor

Модератор
Команда форума
Модератор
Июл 7, 2020
2 599
464
83
советую почитать любую книгу по основам питона
 

Ципихович Эндрю

Активный пользователь
Пользователь
Мар 27, 2021
490
25
28
то ставьте - Пайчарм советую
 

Igor_K

Новичок
Пользователь
Дек 15, 2021
9
0
1
Москва
Уважаемый regnor, приятно иметь дело со знающим и квалифицированным специалистом. Благодарю за совместную работу.
 

Igor_K

Новичок
Пользователь
Дек 15, 2021
9
0
1
Москва
Уважаемый Ципихович Эндрю, спасибо за совет.
Я пользуюсь PyScripter. Отличный удобный инструмент. Думаю, он представляет собой автономную среду, в которой Python 3.8 написан самим PyScripter, и поэтому официальный Python 3.10 подключить к нему невозможно.
Если я правильно понимаю, PyCharm это редактор, который использует Python, как инструмент. Если это так, то мне понадобится Python подключить к PyCharm. Поищу инструкцию.
Если Вы это делали - пришлите, пожалуйста, ссылку на инструкцию - буду признателен.
Благодарю.
 

Ципихович Эндрю

Активный пользователь
Пользователь
Мар 27, 2021
490
25
28
Я пользуюсь PyScripter-ну так и PyCharm тогда не нужен, то что Python 3.10 не подключить это же ваши раздумья, гуглите
насколько я знаю, нет такого понятия - PyCharm подключить к питону, ставите и всё, пользуетесь, там правда есть заморочки - окружение при установке модулей
я делаю это, но не понимая что делаю))
 

Форум IT Специалистов