Откройте графическую форму Tkinter другого файла py (без файла, только графическая форма)

#python #python-3.x #python-2.7 #user-interface #tkinter

Вопрос:

У меня есть основной файл с графической формой Tkinter (классическое окно), который называется, например A.py , и main=Tk() . Кроме того, как я могу вспомнить B.py файл, если он находится во вложенной папке основного проекта?

Нажав, например, на пункт в меню панели, такой как «Открыть форму B», как я могу открыть графическую форму (классическое окно) `B.py? ВАЖНО: без консоли вывода, но только в графической форме P. S: пожалуйста, не используйте «self». Спасибо

ФАЙЛ A.PY: ОСНОВНЫЕ

 from tkinter import *
from tkinter import ttk
import tkinter as tk

main=Tk()
main.title("xxxxxx")
main.geometry("750x750")
main.configure(bg='#282828')

#Bar Menù (no need to write all the code of bar menu)
filemenu.add_command (label = 'Open form B', command = ????)
 

ФАЙЛ B.PY: ВТОРИЧНОЕ

 from tkinter import *
from tkinter import ttk
import tkinter as tk

secondary=Tk()
secondary.title("yyyyyyy")
secondary.geometry("750x750")
secondary.configure(bg='#282828')
 

РЕДАКТИРОВАТЬ (код обновлен, но я не знаю, правильно ли это):

ФАЙЛ A.PY: ОСНОВНЫЕ

 from tkinter import *
from tkinter import ttk
import tkinter as tk
from b import *

main=Tk()
main.title("xxxxxx")
main.geometry("750x750")
main.configure(bg='#282828')

#Bar Menù (no need to write all the code of bar menu)
filemenu.add_command (label = 'Open form B', command = b.draw_graph)
 

ФАЙЛ B.PY: ВТОРИЧНОЕ

 from tkinter import *
from tkinter import ttk
import tkinter as tk
from b import *

def draw_graph():
    secondary=Toplevel("home/mypc/Destkop/Folder1/Folder2/B.py/secondary)
    secondary.title("yyyyyyy")
    secondary.geometry("750x750")
    secondary.configure(bg='#282828')
 

ЗАГРУЗКА 2 (только B.py):

 from tkinter import *
from tkinter import ttk
import tkinter as tk

def draw_graph():
    global secondary=Toplevel()
    secondary.title("yyyyyyy")
    secondary.geometry("750x750")
    secondary.configure(bg='#282828')

#combobox
comboboxx=["xxxxxx", "xxxxx"]
combobox=ttk.Combobox(secondary, width=19)
combobox.place(x=6, y=12)
combobox.config(values=comboboxx)
combobox.set("Scegli")

# I only wrote a small part of the code, showing the combobox.
# But the code is very long. I would not like to put everything 
# in the function (if that is possible) 
 

Ошибка: поле ввода=ttk.Поле ввода(вторичное, ширина=19)
Ошибка имени: имя «вторичное» не определено

Комментарии:

1. Под «графической формой» вы точно подразумеваете окно? Рекомендуемая причина для открытия дополнительных окон tkinter заключается в создании Toplevel виджетов, а не Tk() в многократном вызове.

2. @martineau Да, верно, я имею в виду классическое окно. Не могли бы вы показать мне ответ, пожалуйста? Я новичок в Python. Спасибо 🙂

3. если вы будете хранить код в функциях, то сможете решить, когда запускать их после importing . И функции могут получить parent в качестве аргумента , поэтому при импорте вы можете использовать Toplevel() как parent , а при непосредственном запуске кода вы можете использовать Tk() как parent

4. если вы хотите получить лучший ответ, вам нужно создать лучший вопрос — не ожидайте, что мы напишем весь код для вас. Вы могли бы поместить минимальный рабочий код, который мы могли бы просто скопировать и изменить для создания решения.

5. @furas Разделил ответ на два комментария. Конечно, ты прав. Но, будучи очень простым вопросом, я подумал, что предоставленных мной данных достаточно, например main = Tk (). Мне также нужно было написать main.title («название»), main.geometry («750×750») и main.configure (bg = ‘# 282828’)? То же самое для второго окна? Они бесполезны. Я просто написал необходимые данные, т. е. main.title («заголовок») для первого окна и secondary = Tk () для второго окна, добавив также имена файлов py.

Ответ №1:

Код в b.py вы должны хранить в функциях, чтобы контролировать, когда его запускать

b.py

 import tkinter as tk  # PEP8: `import *` is not preferred
# in file `b.py` you don't need `import b` nor `from b import *` 


def draw_graph():
    win = tk.Toplevel()
    label = tk.Label(win, text="GRAPH")
    label.pack() 
 

а потом можно import b и в жопу command=b.draw_graph

main.py

(Я использую Button для создания минимального рабочего кода, чтобы каждый мог просто скопировать и запустить его)

 import tkinter as tk  # PEP8: `import *` is not preferred
import b  # PEP8: `import *` is not preferred

def main():
    root = tk.Tk()  # PEP8: spaces around `=` when assigning to variable
    
    # ... code ...
    
    #filemenu.add_command(label='Open form A1', command=b.draw_graph)  # PEP8: `=` without spaces when assigning arguments
    # to use `b.draw_graph` you have to use `import b`, not `from b import *`
    
    button = tk.Button(root, text="Open form A1", command=b.draw_graph)
    button.pack() 
    
    root.mainloop()
    
if __name__ == '__main__':    
    main()
 

Если бы вы использовали

 from b import * 
 

тогда вам пришлось бы использовать command=draw_graph вместо command=b.draw_graph


Если у вас есть b.py подпапка с именем other , то вы можете сделать

 from other import b
 

и все еще пользуюсь command=b.draw_graph

или

 import other.b
 

и тогда вам придется использовать command=other.b.draw_graph


PEP 8 — Руководство по стилю для кода на Python


Редактировать:

Я уже писал, как использовать код из подпапки, но я повторяю

если у вас есть Folder1/main.py , а Folder1/Folder2/B.py затем в main.py вас нужно только

 from Folder2 import B

command=B.draw_graph
 

или

 import Folder2.B

command=Folder2.B.draw_graph
 

(если файл имеет имя в верхнем регистре B , то модуль также имеет имя в верхнем регистре B )

Он должен работать без добавления папки sys.path и без добавления файла Folder2/__init__.py

Если у вас будет Folde1/main.py и Folder1/Folder2/Folder3/B.py тогда вам нужно

 from Folder2.Folder3 import B

command=B.draw_graph
 

или

 import Folder2.Folder3.B

command=Folder2.Folder3.B.draw_graph
 

В конце концов, вы можете добавить текущую папку sys.path перед импортом

 import os
import sys

BASE_DIR = os.path.abspath(os.path.dirname(__file__))
sys.path.append(BASE_DIR)

from Folder2 import B
#import Folder2.B
 

и это будет работать также, когда вы запускаете код из другой папки
(другое Current Working Directory — проверка print(os.getcwd()) )

Например

 cd ..
python Folder1/main.py
 

или

 cd /
python /home/mypc/Destkop/Folder1/main.py
 

Комментарии:

1. Большое спасибо. Спасибо 🙂 Прекрасный ответ. Но вы забыли написать, как загрузить B.py если он находится во вложенной папке. Например, если main.py находится в папке home / mypc / Destkop / Folder1 и B.py находится в домашней / mypc / Destkop / Папке 1 / Папке 2 / B.py. Как я могу это получить? Однако завтра я хорошо перепишу вопрос. Я пишу старый исходный код, а затем отдельно добавляю UPLOAD 1, чтобы читатели поняли. Тогда, конечно, я голосую за ваш любезный ответ 🙂 Я буду признателен, если вы измените свой ответ на проблему с подпапками. Спасибо, увидимся завтра

2. Я уже написал это — from Folder2 import B или import Folder2.B — но я использовал имя other . Я только не показал, как добавить Folder1 sys.path , чтобы убедиться, что он найдет Folder2 , когда вы будете запускать код из другой папки, чем Folder1 — ie python Folder1/main.py вместо python main.py

3. Ты написал мне прекрасный ответ. Это похоже на книгу. Хорошо! Искренние поздравления! Теперь я редактирую свой вопрос, как мы говорили вчера. Несколько минут. Однако я получаю ошибку. Я сделал, как вы сказали, но я понял следующее: импорт модуля b не является основанием для: Нет модуля с именем «b». Я пробовал как с импортом b, так и с импортом b *. Я также изменил команду = b.draw_graph или даже команду = draw_graph. Я сделал в точности так, как вы мне написали, как в A.py и B.py. Почему эта ошибка? Спасибо

4. если у вас имя B.py файла в верхнем регистре B , то вы должны import B использовать верхний регистр B — я также написал это в ответе.

5. почему вы используете a = tk.Toplevel () вместо win = tk.Toplevel () . Вы ввели Combobox(win, ...) в действие функцию? если у вас есть внешняя функция, то она выполняется при импорте файла — поэтому она выполняется перед созданием win = ... . Как я уже говорил в начале — вы должны хранить ВЕСЬ КОД в функциях. И Combobox(win, ...) должно быть после win = ... КСТАТИ: в моем коде я создаю Label(win,...) и делаю это внутри draw_graph , после win = ... — это не может быть снаружи draw_graph

Ответ №2:

Используйте функцию верхнего уровня()

  1. сделайте первый файл таким, как вы хотите, как имя, и напишите этот код (a.py для примера)
 from tkinter import *
from tkinter.ttk import *
from b import *

class app:
    def __init__(self, root):
        self.root = root
        self.menu_bar()
        self.root.mainloop()

    def menu_bar(self):
        self.app = app1()
        self.menubar = Menu(self.root)
        self.filemenu = Menu(self.menubar, tearoff=0)
        self.filemenu.add_command(
            label="Open A1", command=lambda: self.app.second(self.root))
        self.filemenu.add_separator()
        self.filemenu.add_command(label="Exit", command=self.root.quit())
        self.menubar.add_cascade(label="File", menu=self.filemenu)
        self.root.config(menu=self.menubar)

if __name__ == "__main__":
    app(Tk())
 

  1. и во втором файле убедитесь, что его имя, как вы пишете в a.py(из импорта имени файла *) (b.py для примера) и напишите так
 class app1:
    def second(self, root):
        self.root = Toplevel(root)
        Label(self.root, text="A2").pack(padx=20, pady=20)
 

это должно решить вашу проблему