简体   繁体   English

如何在 tkinter 中动态创建选项卡

[英]How do I create tabs in tkinter dynamically

I have creatd a menu bar that has options open, edit and some more.我创建了一个菜单栏,其中包含打开、编辑等选项。 The dropmenu in open says open file, save file and save as.打开的下拉菜单说打开文件,保存文件并另存为。 I want to design the GUI in such a way that when click open and choose the file, I want the file contents to be displayed in a new tab and when I click another option I want it to be displayed in another tab.我想以这样一种方式设计 GUI,当单击打开并选择文件时,我希望文件内容显示在新选项卡中,当我单击另一个选项时,我希望它显示在另一个选项卡中。 Can anybody help me with this?有人可以帮我吗? 在此处输入图像描述

    from tkinter import *
from tkinter import filedialog
from tkinter import font
from xml.dom.minidom import parseString
from tkinter import ttk
import subprocess
import os

root = Tk()
root.title('Text-Editor')
root.resizable(width=True, height=True)
root.geometry("1400x660")



def new_file():
    my_text.delete("1.0",END)
    root.title('New File - TextEditor')
    status_bar.config(text="New File        ")

def open_file():
    my_text.delete("1.0",END)
    text_file = filedialog.askopenfilename(initialdir = "/",title="Open file" , filetypes = (("APK Files","*.apk"),("all files","*.*")))
    name=text_file
    status_bar.config(text=f'{name}       ')
    name = name.replace("/", "")
    root.title(f'{name}-TextEditor')
    text_file = open(text_file,'r')
    stuff = text_file.read()
    my_text.insert(END , stuff)
    text_file.close()


def save_as_file():
    text_file = filedialog.asksaveasfilename(defaultextension=".*",initialdir="/",title="Save file",filetypes=(("Text files",".txt"),("All files",".*.*")))
    if text_file:
        name = text_file
        name = name.replace("/","")
        root.title(f'{name} Saved1-TextEditor')

        text_file = open(text_file,'w')
        text_file.write(my_text.get(1.0, END))

        text_file.close()


def get_path(p):
    p = p.split(".")
    p.pop()
    return ''.join(p)


apk_path = filedialog.askopenfilename(initialdir="/",title = "Disassembling", filetypes=(("APK files","*.apk"),("All files","*.apk")))
gpath = get_path(apk_path) + "/AndroidManifest.xml"


def dis_file():
    
    subprocess.run(["apktool","d",apk_path])
    b = str(apkname(apk_path))
    command = "ls " + b + " >" + " a.txt"
    os.system(command)
    os.system("pwd > path.txt")
    file()
    

    
def perm_file():
    tab1 = ttk.Frame(tabcontrol)
    tabcontrol.add(tab1 , text = "Permissions")
    tabcontrol.pack(fill = "both" , expand = 1)
    with open(gpath,'r') as f:
        data = f.read()
    dom = parseString(data)
    nodes = dom.getElementsByTagName('uses-permission')
    l = Listbox(tab1,height=600,
        width=650,
        bg = "grey",
        activestyle="dotbox",
        font="Arial",
        fg="black")
    co = 0
    for c,node in enumerate(nodes):
        co+=1
        l.insert(c,node.getAttribute('android:name'))
    l.insert(0,f'Number of Permissions : {co}')

    l.pack()


def apkname(a):
    a = a.split("/")
    a = a[-1].split(".")
    return a[0]

def act_file():
    tab2 = ttk.Frame(tabcontrol)
    tabcontrol.add(tab2 , text = "Activity Names")
    tabcontrol.pack(fill = "both" , expand = 1)
    with open(gpath,'r') as f:
        data = f.read()
    dom = parseString(data)
    nodes = dom.getElementsByTagName('activity')
    l = Listbox(tab2, height=600,
        width=650,
        bg = "grey",
        activestyle="dotbox",
        font="Arial",
        fg="black")
    co = 0
    for c,node in enumerate(nodes):
        co += 1
        l.insert(c,node.getAttribute('android:name'))
    l.insert(0,f'Number of Activities : {co}')
    l.pack()

def inte_file():
    with open(gpath,'r') as f:
        data = f.read()
    dom = parseString(data)
    nodes = dom.getElementsByTagName('action')
    top = Toplevel()
    l = Listbox(top, height=600,
        width=650,
        bg = "grey",
        activestyle="dotbox",
        font="Arial",
        fg="black")
    top.geometry("700x250")
    co = 0
    for c,node in enumerate(nodes):
        co += 1
        l.insert(c,node.getAttribute('android:name'))
    l.insert(0,f'Number of Intent Actions : {co}')
    l.pack()

def intent_cat():
    with open(gpath,'r') as f:
        data = f.read()
    dom = parseString(data)
    nodes = dom.getElementsByTagName('category')
    top = Toplevel()
    l = Listbox(top, height=600,
        width=650,
        bg = "grey",
        activestyle="dotbox",
        font="Arial",
        fg="black")
    top.geometry("700x250")
    co = 0
    for c,node in enumerate(nodes):
        co += 1
        l.insert(c,node.getAttribute('android:name'))
    l.insert(0,f'Number of Intents Categories : {co}')
    l.pack()

def serv_file():
    with open(gpath,'r') as f:
        data = f.read()
    dom = parseString(data)
    nodes = dom.getElementsByTagName('service')
    top = Toplevel()
    l = Listbox(top, height=600,
        width=650,
        bg = "grey",
        activestyle="dotbox",
        font="Arial",
        fg="black")
    top.geometry("700x250")
    co = 0
    for c,node in enumerate(nodes):
        co += 1
        l.insert(c,node.getAttribute('android:name'))
    l.insert(0,f'Number of Services : {co}')
    l.pack()

def prov_file():
    with open(gpath,'r') as f:
        data = f.read()
    dom = parseString(data)
    nodes = dom.getElementsByTagName('provider')
    top = Toplevel()
    l = Listbox(top, height=600,
        width=650,
        bg = "grey",
        activestyle="dotbox",
        font="Arial",
        fg="black")
    top.geometry("700x250")
    co = 0
    for c,node in enumerate(nodes):
        co += 1
        l.insert(c,node.getAttribute('android:name'))
    l.insert(0,f'Number of providers : {co}')
    l.pack()

def recv_file():
    with open(gpath,'r') as f:
        data = f.read()
    dom = parseString(data)
    nodes = dom.getElementsByTagName('receiver')
    top = Toplevel()
    l = Listbox(top, height=600,
        width=650,
        bg = "grey",
        activestyle="dotbox",
        font="Arial",
        fg="black")
    top.geometry("700x250")
    co = 0
    for c,node in enumerate(nodes):
        co += 1
        l.insert(c,node.getAttribute('android:name'))
    l.insert(0,f'Number of Receivers : {co}')
    l.pack()

def app_file():
    with open(gpath,'r') as f:
        data = f.read()
    dom = parseString(data)
    nodes = dom.getElementsByTagName('manifest')
    top = Toplevel()
    l = Listbox(top, height=600,
        width=650,
        bg = "grey",
        activestyle="dotbox",
        font="Arial",
        fg="black")
    top.geometry("700x250")
    co = 0
    for node in nodes:
        co += 1
        l.insert(1,f'Package Name:{node.getAttribute("package")}')
        l.insert(2,f'compileSdkVersion:{node.getAttribute("android:compileSdkVersion")}')
        l.insert(3,f'compileSdkVersionCodename:{node.getAttribute("android:compileSdkVersionCodename")}')
        l.insert(4,f'XMLNS:{node.getAttribute("xmlns:android")}')
        l.insert(5,f'platformBuildVersionCode:{node.getAttribute("platformBuildVersionCode")}')
        l.insert(6,f'platformBuildVersionName:{node.getAttribute("platformBuildVersionName")}')

    l.insert(0,f'Count = {co}')
    l.pack()

def file():
    with open('/home/prajwal/Downloads/a.txt','r') as f:
        data = f.read()
    a = data.split('\n')
    top = Toplevel()
    l = Listbox(top, height=600,
        width=650,
        bg = "grey",
        activestyle="dotbox",
        font="Arial",
        fg="black")
    top.geometry("700x250")
    l.insert(0,"Extracted Files:")
    for c,i in enumerate(a):
        l.insert(c+1,i) 
    l.pack()

my_frame = Frame(root)
my_frame.pack(pady=3)

tabcontrol = ttk.Notebook(my_frame)

text_scroll = Scrollbar(root)
text_scroll.pack(side=RIGHT , fill=Y)

my_text = Text(root , font=("Arial", 16), selectbackground="yellow", selectforeground="black", undo=True, yscrollcommand=text_scroll.set)
my_text.pack(fill=BOTH , expand=1)

text_scroll.config(command=my_text.yview)

my_menu = Menu(root)
root.config(menu=my_menu)

file_menu = Menu(my_menu , tearoff = False)
my_menu.add_cascade(label="File" , menu = file_menu)
file_menu.add_command(label="New",command=new_file) 
file_menu.add_command(label="Open",command=open_file)
file_menu.add_command(label="Save")
file_menu.add_command(label="Save As",command=save_as_file)
file_menu.add_separator()
file_menu.add_command(label="Exit", command = root.quit)

edit_menu = Menu(my_menu , tearoff=False)
my_menu.add_cascade(label="Edit" , menu = edit_menu)
edit_menu.add_command(label="Cut")
edit_menu.add_command(label="Copy")
edit_menu.add_command(label="Paste")
edit_menu.add_command(label="Undo")
edit_menu.add_command(label="Redo")

dis_menu = Menu(my_menu , tearoff = False)
my_menu.add_cascade(label = "APK",menu=dis_menu)
dis_menu.add_command(label = "Disassemble", command = dis_file)
dis_menu.add_command(label = "Show Permissions", command = perm_file)
dis_menu.add_command(label = "Show Activity Names", command = act_file)
dis_menu.add_command(label = "Show Intents", command = inte_file)
dis_menu.add_command(label = "Show Intent Category", command = intent_cat)
dis_menu.add_command(label = "Show Services", command = serv_file)
dis_menu.add_command(label = "Show Providers", command = prov_file)
dis_menu.add_command(label = "Show Recievers", command = recv_file)
dis_menu.add_command(label = "Show App Info", command = app_file)

status_bar = Label(root, text='Ready        ', anchor = E)
status_bar.pack(fill=X ,side=BOTTOM , ipady =5)
root.mainloop() 

Look at this code:看看这段代码:

import tkinter as tk
from tkinter import ttk
from tkinter import filedialog


class Tab:
    def __init__(self, notebook:ttk.Notebook):
        self.filename = None
        self.notebook = notebook

        self.text_widget = tk.Text(self.notebook)
        self.text_widget.bind("<Control-o>", self.open)
        self.text_widget.bind("<Control-s>", self.save)
        self.text_widget.bind("<Control-Shift-S>", self.saveas)
        self.notebook.add(self.text_widget, text="The tab name")

    def open(self, _=None):
        filename = filedialog.askopenfilename()
        if filename != "":
            with open(filename, "r") as file:
                data = file.read()
            self.text_widget.delete("0.0", "end")
            self.text_widget.insert("end", data)
            self.filename = filename
        return "break"

    def save(self, _=None):
        if self.filename is None:
            self.saveas()
        else:
            self._save()
        return "break"

    def saveas(self, _=None):
        filename = filedialog.asksaveasfilename()
        if filename == "":
            return "break"
        self.filename = filename
        self._save()

    def _save(self):
        assert self.filename is not None, "self.filename shouldn't be None"
        data = self.text_widget.get("0.0", "end")
        with open(self.filename, "w") as file:
            file.write(data)


class App:
    def __init__(self):
        self.root = tk.Tk()
        self.new_tab_button = tk.Button(self.root, text="New tab", command=self.add_new_tab)
        self.new_tab_button.pack()
        self.open_button = tk.Button(self.root, text="Open file", command=self.open_file)
        self.open_button.pack()
        self.save_button = tk.Button(self.root, text="Save file", command=self.save_file)
        self.save_button.pack()
        self.notebook = ttk.Notebook(self.root)
        self.notebook.pack()
        self.tabs = []

    def add_new_tab(self):
        tab = Tab(self.notebook)
        self.tabs.append(tab)

    def get_current_tab(self):
        # This code gets the currently selected tab
        idx = self.notebook.index(self.notebook.select())
        tab = self.tabs[idx]
        return tab

    def open_file(self):
        tab = self.get_current_tab()
        tab.open() # Call `open` on the tab

    def save_file(self):
        tab = self.get_current_tab()
        tab.save() # Call `save` on the tab

    def mainloop(self):
        self.root.mainloop()


if __name__ == "__main__":
    app = App()
    app.mainloop()

It creates an App object which creates new Tab objects each time the "New tab" button is pressed.它创建一个App object,每次按下"New tab"按钮时都会创建新的Tab对象。 It also supports opening files.它还支持打开文件。 Adding the rest of the functionality should be easy.添加 rest 的功能应该很容易。

Is this the code You want (simple example):这是您想要的代码吗(简单示例):

from tkinter import Tk, Menu, Text
from tkinter.ttk import Notebook
from tkinter.filedialog import askopenfile


text_list = []


def add_tab(parent, contents, name):
    text = Text()
    text_list.append(text)
    text = text_list[len(text_list) - 1]
    
    parent.add(text, text=name)
    text.insert('end', contents)


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

    if file:
        add_tab(notebook, file.read(), file.name.split('/')[-1])


root = Tk()

menu_bar = Menu(root)

file_menu = Menu(menu_bar, tearoff=0)
menu_bar.add_cascade(label='File', menu=file_menu)
file_menu.add_command(label='Open', command=open_file)

root.config(menu=menu_bar)

notebook = Notebook(width=700, height=500)
notebook.pack()

root.mainloop()

There is not much to say about this, the only thing to add is that when using tabs and text You need to somehow store the index of text widget so that You can always access it (to perform actions on that specific text widget) (and I can tell that it won't be easy) but so far this works and does what You asked for.对此没什么好说的,唯一要补充的是,在使用选项卡和文本时,您需要以某种方式存储文本小部件的索引,以便您始终可以访问它(对特定文本小部件执行操作)(以及我可以说这并不容易)但到目前为止,这可行并且可以满足您的要求。

Sources:资料来源:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM